Precise GC state

Ola Fosheim Grøstad ola.fosheim.grostad+dlang at gmail.com
Mon Nov 27 20:54:50 UTC 2017


On Monday, 27 November 2017 at 20:13:35 UTC, Dmitry Olshansky 
wrote:
> I’ve seen a tech giant that works on uber high-performance 
> things making heavy use of STL, and being fond of C++14 
> “high-level” features.

Look, I am not against "high level" features, but shared_ptr is 
nothing like the thread local ref-counting you were talking about 
which was at least introduced by Walter and Andrei as a competing 
solution to tracking of borrowed pointers in Rust.


> That must be why you seriously have no idea how people use it. 
> Otherwise you’d know that nobody shares a reference to shared 
> pointer but rather a copy. The whole point of smart pointer is 
> to avoid naked references.

I have an idea of how people use it… why all the ad hominem?

I just don't find it very useful. In practice I'm usually better 
off exchanging through a facade and having the exchanged resource 
wrapped up in a custom type.

It is more maintainable and easy to deal with in terms of 
correctness.


> They are if you use them as intended - value types, that 
> pretend to be pointers.

Sure. Not that this is how they are defined to be used. It is a 
very limited use case.


>> a shared control block is. (Technically you share a pointer, 
>> not an object of type T, but that is a minor detail.)
>
> No, you actually share an object and the last one to decrement 
> the ref will destroy it. Now that is actually thread-safe 
> thanks to atomic counter.

Ok, sure, you share an ownership relation to an object, but it 
isn't general enough, which was what I tried to suggest. For 
instance, if you have a resource on a GPU with an integer ID that 
is also a resource, but shared_ptr does not work (unless you 
accept extra indirections).

So, I'd rather see an owned<T>, which also can handle 
non-pointed-to-objects. Then one might ask, why not just have 
"unique<owningptr<T>>" or "shared<owningptr<T>>" that also would 
work with "unique<Resource>" and "shared<Resource>"?

Then you can build generic ADTs with a generic notion of 
ownership .

The basic idea is that an owned resource that has to go through a 
pointer isn't really necessary or as generic a type as it could 
have been.


> That is my original point, which you now violently agree with :)

Ok, then I didn't get your original point.


> Just underlines that you don’t understand how it is supposed to 
> be used.

I know how it can be used. That doesn't mean that it is as 
generally useful as it should be to be useful for what I want to 
do.


> I also don’t understand what are you trying to prove. My point 
> was: C++ has to do atomic counting, because it has no concept 
> of shared vs local.

That I disagree with. In C++ correct syncing is entirely 
dependent on the programmer. Even if atomic_shared_ptr provide 
some guarantees these guarantees will not hold if you depend on 
more than one entity. So there is no mechanism in C++ that 
provide something to ensure correctness when it comes to 
concurrency. I.e. you totally depend on the programmer's ability.

You can create a concept of D-style local/shared by just creating 
a wrapper type and use a lint-style verification. This is the 
route C++ is heading in general for various properties related to 
pointer types it seems. (e.g. wrap with borrowed, owned, nullable 
etc).

Which is also basically what D has, except shared is a builtin, 
but semantically I see no difference. To get a semantic 
difference that matter you need concurrency to be part of the 
language itself. If you cannot express propositions about 
concurrency in the language, then there is a very limited ability 
to do something interesting with it.


> You did imply it’s useless on single thread and not used in 
> concurrency because you need manual sync. I’d argue you don’t 
> need a sync to access shared_ptr, you’d need it for object it 
> points to.

Listen, if you build a shared graph with shared_ptrs then you are 
in trouble. So you would need atomic_shared_ptrs. That's a 
perfectly reasonable use case.

You are presuming that the shared_ptr objects are thread local 
and that they are not embedded in other objects that are 
reachable by another thread.

Those a very limiting presumptions.


> It still solves the ownership and deterministic destruction in 
> the presense of concurrent shared_ptrs of the same object.

But it doesn't solve correctness. You still rely on the 
programmer to get correctness. Which is a tall order when you use 
encapsulation.

That only works if you never embed shared_ptr in a class.


> Copy & destruction is actually fine, which you seem to ignore. 
> Also accessing const methods of payload is fine. New C++ 
> implies const == thread safe btw, at least in all of STL.

As far as I can see from the description at cppreference.com 
there is no guarantee of freedom for races for anything if both 
threads reference the same shared_ptr object (not the control 
block but the object pointing to the control block).

You can obviously transmit it to another thread using a 
mutex-like/messaging-like setup if that is what you mean.






More information about the Digitalmars-d mailing list