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