Deutsch   English   Français   Italiano  
<vcb5ij$3c3g5$1@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 08:54:28 +0300
Organization: A noiseless patient Spider
Lines: 73
Message-ID: <vcb5ij$3c3g5$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>
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 8bit
Injection-Date: Tue, 17 Sep 2024 07:54:28 +0200 (CEST)
Injection-Info: dont-email.me; posting-host="8634390b878b76fe06bd0d2d4efc76cb";
	logging-data="3542533"; mail-complaints-to="abuse@eternal-september.org";	posting-account="U2FsdGVkX18/kstBsuAEnumZ+tfXlIDzhR/N8168JKA="
User-Agent: Mozilla Thunderbird
Cancel-Lock: sha1:SZ/h1qEzhH0IKC0yHVXJExiTq5k=
Content-Language: en-US
In-Reply-To: <vca8v5$327mo$1@dont-email.me>
Bytes: 4343

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!
Paavo