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.




Reply via email to