1

Is it possible to implement atomic swap for smart pointers on x86/x86-64 without using of transactional memory. Especially interested in atomic exchange for shared_ptr.

There are CMPXCHG8B and CMPXCHG16B instructions on modern processors. Can they be used to implement atomic swap for shared_ptr?

Tomilov Anatoliy
  • 15,657
  • 10
  • 64
  • 169
  • A `shared_ptr` typically just hold a regular pointer to a control block. Atomically swapping shared pointers is equivalent to atomically swapping regular pointers. Anyway, are you perhaps looking for [`std::atomic_exchange`](https://en.cppreference.com/w/cpp/memory/shared_ptr/atomic)? I don't quite grasp the nature of the difficulty. – Igor Tandetnik Dec 02 '18 at 15:55
  • 3
    i386/x86-64 does not have atomic DCAS (exchange the contents of two arbitrary memory locations). It does have DWCAS (double-word CAS, like `lock cmpxchg16b`), so if you have two pointers stored adjacent to each other in memory, you can swap them with a CAS retry loop. – Peter Cordes Dec 02 '18 at 16:16
  • @IgorTandetnik "_just hold a regular pointer to a control block_" No. A `shared_ptr` contains a pointer **to the object** referenced. That's two pointers. – curiousguy Dec 04 '18 at 00:35
  • @PeterCordes "_two pointers stored adjacent to each other in memory_" exactly the typical `shared_ptr` implementation – curiousguy Dec 04 '18 at 00:42
  • 1
    @curiousguy: I'm not clear what this question is asking; what they want exchanged with what. If it's something you can do with lockless atomic updates of the control block of *one* shared_ptr, then sure. I thought they were asking about swapping two different `shared_ptr`s with each other, and having the whole thing be atomic so no thread could ever see both shared_ptr pointing to the same object. (Of course you can't atomically read two separate memory locations, so for any order of swapping, two reads could get the same value.) Anyway, this was tagged DCAS, but x86 doesn't have that. – Peter Cordes Dec 04 '18 at 00:53
  • @PeterCordes Surely I asking about atomic swapping of two different `shared_ptr`s, not neccessarily adjacent into the memory. But the case of adjacent `shared_ptr`s (internally consists of just single pointer to the control block of counter+payload) pair is of interest too. My problem really can be solved using RCU or hazard pointers, but imaginary atomic `shared_ptr::swap` is much more attractive. I really can use `alignas(64) struct P { std::shared_ptr< T > dst, src; };` for my purposes if `static_assert(sizeof(void *) == sizeof(std::shared_ptr< T >));`. – Tomilov Anatoliy Dec 04 '18 at 08:46
  • 2
    IIRC, only one thread at a time can modify an actual `std::shared_ptr` object itself, because that part of it isn't thread-safe. Different threads need different `shared_ptr` objects that reference the same control block, created by the shared_ptr copy constructor. Atomically modifying a `shared_ptr` object itself is not even useful in code that doesn't have Data Race UB. Can you give an example of a problem you want to solve with this. (Oversimplified is fine, but like a [mcve] use-case? – Peter Cordes Dec 04 '18 at 08:53
  • "_internally consists of just single pointer_" as I wrote **That's two pointers** – curiousguy Dec 04 '18 at 15:03

0 Answers0