Atomic operations on `unique_ptr`

后端 未结 3 904
既然无缘
既然无缘 2021-01-08 01:04

std::shared_ptr has specializations for atomic operations like atomic_compare_exchange_weak and family, but I cannot find documentation on equivale

3条回答
  •  借酒劲吻你
    2021-01-08 01:29

    The reason that it is possible to provide an atomic instance of std::shared_ptr and it is not possible to do so for std::unique_ptr is hinted at in their signature. Compare:

    • std::shared_ptr vs
    • std::unique_ptr where D is the type of the Deleter.

    std::shared_ptr needs to allocate a control-block where the strong and weak count are kept, so type-erasure of the deleter came at a trivial cost (a simply slightly larger control-block).

    As a result, the layout of std::shared_ptr is generally similar to:

    template 
    struct shared_ptr {
        T* _M_ptr;
        SomeCounterClass* _M_counters;
    };
    

    And it is possible to atomically perform the exchange of those two pointers.


    std::unique_ptr has a zero-overhead policy; using a std::unique_ptr should not incur any overhead compared to using a raw pointer.

    As a result, the layout of std::unique_ptr is generally similar to:

    template >
    struct unique_ptr {
        tuple _M_t;
    };
    

    Where the tuple uses EBO (Empty Base Optimization) so that whenever D is zero-sized then sizeof(unique_ptr) == sizeof(T*).

    However, in the cases where D is NOT zero-sized, the implementation boils down to:

    template >
    struct unique_ptr {
        T* _M_ptr;
        D _M_del;
    };
    

    This D is the kicker here; it is not possible, in general, to guarantee that D can be exchange in an atomic fashion without relying on mutexes.

    Therefore, it is not possible to provide an std::atomic_compare_exchange* suite of specialized routine for the generic std::unique_ptr.

    Note that the standard does not even guarantee that sizeof(unique_ptr) == sizeof(T*) AFAIK, though it's a common optimization.

提交回复
热议问题