Precise GC state

Ola Fosheim Grøstad ola.fosheim.grostad+dlang at gmail.com
Mon Nov 27 18:29:56 UTC 2017


On Monday, 27 November 2017 at 17:16:50 UTC, Dmitry Olshansky 
wrote:
> Really, shared_ptr is the most contagious primitive of modern 
> C++.

Not really. Unique_ptr is, though.

> To quote MS STL guy “I’m surprised we had no non-inteusive 
> ref-counted ptr in std lib for so long”.
> Going Native videos are full of questions on that.

Yeah, they tend to pretend that C++ is a high level language, it 
makes for good talks.

Let me put it this way, C++ is an acceptable low level language, 
but it is a rather poor high level language.

So if you talk with people who use C++ as a high level language 
you probably see different usage  patterns.

>> Err... That was my point... Only assignment and reset is 
>> protected in shared_ptr, all other methods require manual sync.
>
> For the benefit of others, let me destroy that:

Oh well, looks like reset and assignment isn't required per the 
spec to be protected against races either. That doesn't weaken my 
point, the control block is protected but not the methods of 
shared_ptr.

I hardly ever use shared_ptr. In practical programming you 
usually need to exchange more than a single entity so you need 
manual sync anyway.


> - shared_ptr allows to share T with thread-safe ownership, 
> ref-counts are accounted atomically (sharing copies of 
> shared_ptr pointing to the same block). Copy of shared_ptr is 
> thread safe and does the count.

Not sure if I follow that description. Shared shared_ptr's are 
not thread safe, a shared control block is. (Technically you 
share a pointer, not an object of type T, but that is a minor 
detail.)

shared_ptr is pointing to a shared control block that in turn has 
a pointer that points to the resource. This control block  
contains two counters. These counters are incremented and 
decremented atomically.

If you access the same shared_ptr from two threads then you have 
a potential race condition per the spec.

> - atomic_shared_prt would also allow one to initialize a shared 
> variable (eg global) of type shared_ptr safely from multiple 
> threads

The main point is that the methods of atomic_shared_ptr are 
protected against races.

It is needed because you usually would have have ownership 
pointers embedded in a another shared object.

So having a protected control-block is not sufficient outside the 
trivial toy-program.

> The manual synchronization part comes in if you try to work 
> with payload T itself. THAT is manual.

No, none of the methods on shared_ptr guarantees that races won't 
happen. And in general you usually want to access more than one 
unit in a critical section.

So in C++ you typically need manual sync.

There are no suitable language features to get around that in C++ 
and library features are inadequate in the general sense.

Go and Pony have language features that are helpful. C++ doesn't.

> Since C++ doesn’t see a difference at type level of shared vs 
> local, there is no thread-local variation of shared_ptr. It 
> would be too unsafe even for those guys, contrary to what Ola 
> responses imply.

Sigh. I implied that shared_ptr on a single thread is mostly 
useless.

But this:

struct OurSharedCache {
    shared_ptr<T> something;
    shared_ptr<T> somethingelse
}

Not safe.


> Well I can clearly see misinformation and describe it as such. 
> See your point about atomic_shared_ptr.

What about it?

«If multiple threads of execution access the same shared_ptr 
without synchronization and any of those accesses uses a 
non-const member function of shared_ptr then a data race will 
occur»

http://en.cppreference.com/w/cpp/memory/shared_ptr

«The class template atomic_shared_ptr provides thread-safe atomic 
pointer operations over a std::shared_ptr.»

http://en.cppreference.com/w/cpp/experimental/atomic_shared_ptr



More information about the Digitalmars-d mailing list