Deutsch English Français Italiano |
<vcb6el$3c3g5$2@dont-email.me> View for Bookmarking (what is this?) Look up another Usenet article |
Path: ...!weretis.net!feeder8.news.weretis.net!eternal-september.org!feeder3.eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail From: Paavo Helde <eesnimi@osa.pri.ee> Newsgroups: comp.lang.c++ Subject: Re: Atomic caching of smart pointers Date: Tue, 17 Sep 2024 09:09:26 +0300 Organization: A noiseless patient Spider Lines: 79 Message-ID: <vcb6el$3c3g5$2@dont-email.me> References: <vc7ahq$2akr4$1@dont-email.me> <vc7f5o$2atht$5@dont-email.me> <vca82m$32puo$1@dont-email.me> <vca8v5$327mo$1@dont-email.me> <vca96n$32c6u$2@dont-email.me> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 8bit Injection-Date: Tue, 17 Sep 2024 08:09:25 +0200 (CEST) Injection-Info: dont-email.me; posting-host="8634390b878b76fe06bd0d2d4efc76cb"; logging-data="3542533"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1/wW/lnDoYXMpv0+9NbtjaS5iAp99NSrT8=" User-Agent: Mozilla Thunderbird Cancel-Lock: sha1:6MzJ+UHKo++Tf77SfTnN5DJJuNM= In-Reply-To: <vca96n$32c6u$2@dont-email.me> Content-Language: en-US Bytes: 4937 On 17.09.2024 00:50, Chris M. Thomasson wrote: > On 9/16/2024 2:46 PM, Chris M. Thomasson wrote: >> On 9/16/2024 2:31 PM, Paavo Helde wrote: >>> 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? > > 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? Yes, all correct! Now I see I also need to forbid assignment in the CachedAtomicPtr class to avoid modifying the installed smartpointer, and add a proper copy ctor. But that's a bit aside the main functionality of installing the cached smartpointer in a lock-free manner. Thanks for the answer! Paavo