Deutsch English Français Italiano |
<vcb5r9$3c740$1@dont-email.me> View for Bookmarking (what is this?) Look up another Usenet article |
Path: ...!eternal-september.org!feeder3.eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail From: "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> Newsgroups: comp.lang.c++ Subject: Re: Atomic caching of smart pointers Date: Mon, 16 Sep 2024 22:59:05 -0700 Organization: A noiseless patient Spider Lines: 76 Message-ID: <vcb5r9$3c740$1@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> <vcb5ij$3c3g5$1@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 07:59:07 +0200 (CEST) Injection-Info: dont-email.me; posting-host="2d41bb0e6a21724e79465d793e720c2a"; logging-data="3546240"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1+ZJLMRFHICDi63wnRl8QaEKbj94mGcxKQ=" User-Agent: Mozilla Thunderbird Cancel-Lock: sha1:YVcm8ytLu/0ztf2f32CL15a2ycs= In-Reply-To: <vcb5ij$3c3g5$1@dont-email.me> Content-Language: en-US Bytes: 4680 On 9/16/2024 10:54 PM, Paavo Helde wrote: > On 17.09.2024 00:46, 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? > > Correct. The `p->IncrementRefcount();` line will keep the assigned T > object alive, regardless of how many other smartpointers there are > pointing to it in any threads. The refcount is decremented in > ~CachedAtomicPtr(). > >> 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? > > Correct. Otherwise I would need a mutex, DCAS or some other trickery for > avoiding races. > > Thanks for the answer! Humm... Well, afaict this can be modeled in Relacy. I can do it on my end when I get some more time. You mentioned you were having trouble even compiling it? It should be a header only lib, iirc.