synchronized/shared associative array .require error

Steven Schveighoffer schveiguy at gmail.com
Mon Sep 5 18:31:40 UTC 2022


On 9/4/22 11:24 PM, cc wrote:
> On Saturday, 3 September 2022 at 14:37:16 UTC, Steven Schveighoffer wrote:
>> On 9/2/22 3:15 PM, cc wrote:
>>
>>> Tried casting away shared as a workaround but I assume that will 
>>> cause some kind of TLS catastrophe.
>>>
>>
>> I think it will be fine, but you may have an issue. You are returning 
>> a non-shared `VAL`, but your class is `shared`, which means `table`, 
>> and all the `VAL` and `KEY` inside must also be `shared`.
>>
>> If you cast away `shared` you have to put it back upon return.
>>
>> TLS should not be involved here at all, so there is no problem there.
>>
> 
> Alright, so this is safe then?
> ```d
> alias VAL[KEY] T;
> auto require(KEY key) {
>      auto unsharedT = cast(T) table;
>      auto r = unsharedT.require(key);
>      table = cast(shared) unsharedT;
>      return cast(shared) r;
> }
> ```

I think that is fine-ish. You still don't have a shared `KEY` there. But 
it really depends on what KEY is. Most likely it's fine (e.g. if `KEY` 
is string). If you don't ever really fetch anything out of the key, and 
just use it to map to your values, I think it should be fine.

> Was a bit surprised to see mutating `unsharedT` left `table` unchanged 
> and needed reassigning.

Yes, because before an AA contains an element, it is a `null` AA. When 
you add the first element, it's allocated. When you make a copy of a 
`null` AA, it doesn't affect the original.

You can fix this by reinterpret casting the AA instead of copying it:

```d
auto r = .require(*(cast(T*)&table), key);
// I think this might also work:
auto r = (cast()table).require(key);
```

-Steve


More information about the Digitalmars-d-learn mailing list