shared - i need it to be useful

Isaac S. spam-no-reply-isaac at outlook.com
Wed Oct 17 03:16:02 UTC 2018


On Tuesday, 16 October 2018 at 06:21:22 UTC, Manu wrote:
> On Mon, Oct 15, 2018 at 8:55 PM Isaac S. via Digitalmars-d 
> <digitalmars-d at puremagic.com> wrote:
>>
>> On Tuesday, 16 October 2018 at 02:26:04 UTC, Manu wrote:
>> >> I understand your point but I think the current shared (no 
>> >> implicit conversion) has its uses.
>> >> *snip*
>> >
>> > If you can give a single 'use', I'm all ears ;)
>>
>> My usages are a custom ref counted template and list types 
>> (which are built on top of the former). The ref counted 
>> template will initialize naively when not shared but utilize 
>> compare-and-set and thread yielding if needed when shared 
>> (ensureInitialized can occur any time after declaration). The 
>> list types (which are not shared-compatible *yet*) will 
>> utilize a read-write mutex only when shared (no cost beyond a 
>> little unused memory to non-shared objects). As such, casting 
>> any of the non-shared versions of these types to shared would 
>> be unsafe.
>>
>> (Technically the types can be safely casted to shared so long 
>> as no non-shared reference to them exists and vice versa.)
>
> Can you link to code? It doesn't sound incompatible with my 
> proposal. Mutexes are blunt instruments, and easy to model. My 
> whole suggestion has virtually no effect on the mutex protected 
> case, which is what most people seem to talk about.

On Wednesday, 17 October 2018 at 00:26:58 UTC, Manu wrote:
> *snip*
>
> Overloading for shared and unshared is possible, and may be 
> desirable in many cases.
> There are also many cases where the code duplication and 
> tech-debt
> does not carry its weight. It should not be required, because 
> it's not technically required.

Overloading for shared and unshared is my reason for not allowing 
implicit conversion on my types (I have no problems with implicit 
conversion being optional or disableable). The unshared function 
performs no synchronization of any kind while the shared function 
always does. This means that having an unshared and shared 
reference to the same object is unsafe.

As for an actual link to code, I can really only link to my ref 
counted template
as I haven't gotten around to making the containers 
shared-compatible yet. The main point of interest is at lines 
103-131:

https://github.com/isaacs-dev/Familiar/blob/66f1a94fc099601465e755d40a2c68bf4200cabd/containers/familiar/containers/safe_ref_counted.d#L103

The unshared ensureInitialized() doesn't worry about threads 
simultaneously calling it. The shared version of it uses 
compare-and-set to prevent two threads from initializing it at 
the same time. An unsafe example would require a shared 
reference/pointer to an unshared SafeRefCounted (which would be 
fairly weird to do) and both calling ensureInitialized. While an 
example using the ref counted template is fairly contrived, a 
list-type that only uses a read-write mutex when it's shared 
isn't.


As to the larger part of preventing reading/writing of shared 
objects, I agree with its purpose and have no problems with it.


More information about the Digitalmars-d mailing list