Search code examples
c++c++11shared-ptratomiclock-free

Linking pthread disables lock-free shared_ptr implementation


The title pretty much conveys all relevant information, but here's a minimal repro:

#include <atomic>
#include <cstdio>
#include <memory>

int main() {
    auto ptr = std::make_shared<int>(0);
    bool is_lockless = std::atomic_is_lock_free(&ptr);
    printf("shared_ptr is lockless: %d\n", is_lockless);
}

Compiling this with the following compiler options produces a lock-free shared_ptr implementation:

g++ -std=c++11 -march=native main.cpp

While this doesn't:

g++ -std=c++11 -march=native -pthread main.cpp

GCC version: 5.3.0 (on Linux, using libstdc++), tested on multiple machines that should have the necessary atomic instructions to make this work.

Is there any way to force the lock-free implementation (I'd need the lock-free version, regardless of performance)?


Solution

  • If you use shared_ptr in a threaded environment, you NEED to have locks [of some kind - they could be implemented as atomic increment and decrement, but there may be places where a "bigger" lock is required to ensure no races]. The lockless version only works when there is only one thread. If you are not using threads, don't link with -lpthread.

    I'm sure there is some tricky way to convince the compiler that you are not REALLY using the threads for your shared pointers, but you are REALLY in fragile territory if you do - what happens if a shared_ptr is passed to a thread? You may be able to guarantee that NOW, but someone will probably accidentally or on purpose introduce one into something that runs in a different thread, and it all breaks.