digitalmars.D.learn - synchronized/shared associative array .require error
- cc (18/18) Sep 02 2022 ```d
- Loara (24/42) Sep 03 2022 In current version of D language `synchronized` and `shared` are
- frame (3/7) Sep 03 2022 Not exactly, a synchronized class member function becomes
- Steven Schveighoffer (7/10) Sep 03 2022 I think it will be fine, but you may have an issue. You are returning a
- cc (14/26) Sep 04 2022 Alright, so this is safe then?
- Steven Schveighoffer (15/43) Sep 05 2022 I think that is fine-ish. You still don't have a shared `KEY` there. But...
```d synchronized class SyncTable(KEY, VAL) { private VAL[KEY] table; auto require(KEY key) { return table.require(key); } } auto table = new shared SyncTable!(string, string); table.require("abc"); ``` Fails to compile: ``` // Error: none of the overloads of template `object.require` are callable using argument types `!()(shared(string[string]), string)` ``` Tried casting away shared as a workaround but I assume that will cause some kind of TLS catastrophe.
Sep 02 2022
On Friday, 2 September 2022 at 19:15:45 UTC, cc wrote:```d synchronized class SyncTable(KEY, VAL) { private VAL[KEY] table; auto require(KEY key) { return table.require(key); } } auto table = new shared SyncTable!(string, string); table.require("abc"); ``` Fails to compile: ``` // Error: none of the overloads of template `object.require` are callable using argument types `!()(shared(string[string]), string)` ``` Tried casting away shared as a workaround but I assume that will cause some kind of TLS catastrophe.In current version of D language `synchronized` and `shared` are independent. In particular `shared` should be used only for basic types like integers for which atomic operations are well defined, and not for classes. Anyway if you must send a reference of a `synchronized` class to a different thread then it's safe to cast `shared` and then remove it later: ```d synchronized class A{ ... } void sendTo(Tid to, A a){ to.send(cast(shared A) a); } A receiveA(){ A a; receive( (shared A sa) { a = cast(A) sa; }); return a; } ``` Unfortunately there isn't any traits that tells you if a class is `synchronized` or not, so you can't do a safe template function for this.
Sep 03 2022
On Saturday, 3 September 2022 at 09:49:54 UTC, Loara wrote:In current version of D language `synchronized` and `shared` are independent. In particular `shared` should be used only for basic types like integers for which atomic operations are well defined, and not for classes.Not exactly, a synchronized class member function becomes automatically a shared one.
Sep 03 2022
On Saturday, 3 September 2022 at 14:07:58 UTC, frame wrote:Not exactly, a synchronized class member function becomes automatically a shared one.This is not present in official documentation so other compilers different from `dmd` aren't forced to assume it. This should be consider an experimental feature of D that users should be able to turn off if they want.
Sep 06 2022
On Tuesday, 6 September 2022 at 10:28:53 UTC, Loara wrote:On Saturday, 3 September 2022 at 14:07:58 UTC, frame wrote:Hmm.. LDC does the same to me. I think the whole synchronization class is an experimental feature :DNot exactly, a synchronized class member function becomes automatically a shared one.This is not present in official documentation so other compilers different from `dmd` aren't forced to assume it. This should be consider an experimental feature of D that users should be able to turn off if they want.
Sep 06 2022
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. -Steve
Sep 03 2022
On Saturday, 3 September 2022 at 14:37:16 UTC, Steven Schveighoffer wrote:On 9/2/22 3:15 PM, cc wrote: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; } ``` Was a bit surprised to see mutating `unsharedT` left `table` unchanged and needed reassigning.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. -Steve
Sep 04 2022
On 9/4/22 11:24 PM, cc wrote:On Saturday, 3 September 2022 at 14:37:16 UTC, Steven Schveighoffer wrote: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.On 9/2/22 3:15 PM, cc wrote: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; } ```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.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
Sep 05 2022