Liste des Groupes | Revenir à cl c++ |
On 9/16/2024 2:46 PM, Chris M. Thomasson wrote:Yes, all correct!On 9/16/2024 2:31 PM, Paavo Helde wrote:So as long as CachedAtomicPtr stays alive, the refcount on its successfully _installed_ point will always be +1. In other words in order for the count to drop to zero wrt its installed smart pointer, is only _after_ CachedAtomicPtr has been destroyed and its dtor called? Am I getting close or WAY off in the damn weeds somewhere out there.... ;^) ? So one a smart pointer is installed in a CachedAtomicPtr, it will never change? Am I right, or totally wrong?On 15.09.2024 23:13, Chris M. Thomasson wrote:>On 9/15/2024 11:54 AM, Paavo Helde wrote:>
I am thinking of developing some lock-free data structures for better scaling on multi-core hardware and avoiding potential deadlocks. In particular, I have got a lot of classes which are mostly immutable after construction, except for some cached data members which are calculated on demand only, then stored in the object for later use.
>
Caching single numeric values is easy. However, some cached data is large and accessed via a std::shared_ptr type refcounted smartpointers. Updating such a smartpointer in a thread-shared object is a bit more tricky. There is a std::atomic<std::shared_ptr> in C+ +20, but I wonder if I can do a bit better by providing my own implementation which uses CAS on a single pointer (instead of DCAS with additional data fields or other trickery).
>
This is assuming that
>
a) the cached value will not change any more after assigned, and will stay intact until the containing object destruction;
>
b) it's ok if multiple threads calculate the value at the same time; the first one stored will be the one which gets used.
>
My current prototype code is as follows (Ptr<T> is similar to std::shared_ptr<T>, but is using an internal atomic refcounter; using an internal counter allows me to generate additional smartpointers from a raw pointer).
>
template<typename T>
class CachedAtomicPtr {
public:
CachedAtomicPtr(): ptr_(nullptr) {}
>
/// Store p in *this if *this is not yet assigned.
/// Return pointer stored in *this, which can be \a p or not.
Ptr<T> AssignIfNull(Ptr<T> p) {
const T* other = nullptr;
if (ptr_.compare_exchange_weak(other, p.get(), std::memory_order_release, std::memory_order_acquire)) {
p->IncrementRefcount();
return p;
} else {
// wrap in an extra smartptr (increments refcount)
return Ptr<T>(other);
}
}
So as long as CachedAtomicPtr is alive, the cached pointer, the one that gets installed in your AssignIfNull function, will be alive? Sorry if my question sounds stupid or something. Get trying to get a handle on your usage pattern. Also, the first pointer installed in CachedAtomicPtr will remain that way for the entire duration of the lifetime of said CachedAtomicPtr instance?
Les messages affichés proviennent d'usenet.