Thread overview
[Issue 20484] Regression: runtime cannot handle shared(AA)
Feb 18, 2020
ZombineDev
Feb 18, 2020
James Blachly
February 18, 2020
https://issues.dlang.org/show_bug.cgi?id=20484

ZombineDev <petar.p.kirov@gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |petar.p.kirov@gmail.com

--- Comment #1 from ZombineDev <petar.p.kirov@gmail.com> ---
Shared AAs were never properly supported in druntime. I would say that before the compiler was accepting invalid code. The reason is that the AA implementation does not implement internal synchronization, and instead assumes that all AA instances are thread-local.

The (pedantically) correct way to go is:
1. Keep using the `shared` type qualifier. It will prevent accidental mutation
of shared of non-internally synchronized data.
2. Use some form of external synchronization (mutex, read-write lock, etc.) to
ensure that there can be either a single writer or zero or more readers.
3. In a block of code where you have acquired exclusive write access (by means
of external synchronization), it's ok to cast the AA from type `shared(K[V])`
to `shared(K)[V]` or simply `K[V]` (*).
In a block where you have acquired read-access, you can safely cast from
`shared(K[V])` to `const(shared(K)[V])` or `const(K[V])` (*)

(*) The distinction between shared(K)[V] and simply K[V] may be subtle, but
it's important and needs to be decided by the author of the code on a
case-by-case basis.

For example:

A) The type `int[][string]` allows mutation of both the AA (e.g. getting,
adding and removing int[] arrays) and each value (e.g. resizing the arrays and
changing each element).

B) With `shared(int[][string])` you can't do anything since druntime does not
(yet) implement internal synchronization of the AA implementation.

C) With `shared(int)[][string]` you can get, add and remove values from the AA,
and you can change the values by making them point to different arrays, but the
array elements can't be read/written to (without e.g. atomicLoad / atomicStore
/ cas)

D) `shared(int[])[string]` is kind of degenerate case between B) and C), but
pedantically speaking it can't work correctly, because to do so, the AA
implementation needs to use atomic load/store in order to guarantee the safe
mutation of values.

--
February 18, 2020
https://issues.dlang.org/show_bug.cgi?id=20484

--- Comment #2 from James Blachly <james.blachly@gmail.com> ---
@ZombineDev: Thanks for the details. Our codebase was already using synchronization.

The runtime is still making a type error that causes compilation failure, but I do not understand runtime internals well enough to appreciate whether the offending block can simply be rolled back.

--
December 07
https://issues.dlang.org/show_bug.cgi?id=20484

--- Comment #3 from dlangBugzillaToGithub <robert.schadek@posteo.de> ---
THIS ISSUE HAS BEEN MOVED TO GITHUB

https://github.com/dlang/dmd/issues/17394

DO NOT COMMENT HERE ANYMORE, NOBODY WILL SEE IT, THIS ISSUE HAS BEEN MOVED TO GITHUB

--