On Monday, 10 April 2017 at 08:11:37 UTC, Atila Neves wrote:
On Sunday, 9 April 2017 at 13:59:14 UTC, Andrei Alexandrescu
Great. Can RefCounted itself be shared? I learned this is
important for composition, i.e. you want to make a RefCounted
a field in another object that is itself shared, immutable etc.
Since it has a destructor, no:
The only way to do that would be to split it into two. Which I
guess I could with a template mixin implementing the guts.
Syntax is not the core of the issue, it's not about just marking
a destructor as shared. Making RefCounted itself shared would
require implementing some form of synchronization of all the
'dereference' operations, including assignments. I.e. if we have
some shared(RefCounted!T) ptr, what should happen when two
threads simultaneously attempt to do ptr =
shared(RefCounted!T)(someNewValue) ? Should a library
implementation even consider this? Or should such synchronization
be left to client's care? It seems like in this regard
shared(RefCounted!T) would be no different from shared(T*), which
brings me to the next point.
On Andrei's comment regarding composition: if we're thinking
about the design of shared data, IMHO, copying and shared are (or
at least, should be) mutually exclusive. The only exception being
references (pointers), and even for those care should be taken
(which is one of the reasons of even having something like a
RefCounted). If you can make a copy, there is no reason to share,
or, conversely, if you intend to share, why would you copy?
From that follows that a shared object should not ever have a
RefCounted field. A Unique field, perhaps, but not a RefCounted.
RefCounted's purpose is to be copied, not shared between threads.
Unless I'm missing something.