On 5/11/18 2:49 PM, Jonathan M Davis wrote:
On Friday, May 11, 2018 14:31:17 Steven Schveighoffer via Digitalmars-d-
learn wrote:
On 5/11/18 1:25 PM, Danny Arends wrote:
Hey all,

I have been working on creating a multi-threaded application, so I have
a shared configuration object which hold several command line parameters
(which I fill using getopt).

The problem is that I get deprecation warnings when trying to set
numerical values:

/usr/include/dmd/phobos/std/getopt.d(895,36): Deprecation:
read-modify-write operations are not allowed for shared variables. Use
core.atomic.atomicOp!"+="(*receiver, 1) instead.

using getopt with a shared object and boolean values seems completely
broken:

/usr/include/dmd/phobos/std/getopt.d(895,34): Error: operation not
allowed on bool *receiver += 1
/usr/include/dmd/phobos/std/getopt.d(751,46): Error: template instance
`std.getopt.handleOption!(shared(bool)*)` error instantiating
/usr/include/dmd/phobos/std/getopt.d(435,15):        6 recursive
instantiations from here: getoptImpl!(string, shared(string)*, string,
shared(string)*, string, shared(VSync)*, string, shared(ulong)*, string,
shared(bool)*, string, shared(Verbose)*)

Is getopt not supposed to be used with shared structs ?

No, just fill in a local copy, and then copy it to the shared location.

In the case where all you want is read-only access to the data, build it
once and then cast to immutable:

immutable Config config;

void main(string[] args)
{
     Config localConfig;
     getopt(...); // fill in localConfig
     // VERY IMPORTANT, only do this ONCE, and don't use it before this
line *(cast()&config) = localConfig;
}

It should now be accessible from all threads.

Normally, this is not encouraged (casting away immutable), but the
compiler gets that an immutable global is allowed to be initialized once
(in fact, you can do this without casting inside shared static
constructors).

Except that because this is done outside of a shared static constructor,
you're technically mutating immutable data. This _should_ work, but it is
violating the type system, and technically, the compiler is allowed to
assume that config is Config.init everywhere. In practice, I wouldn't expect
a problem, but because it's violating the type system, all bets are off.

It's not a problem. The compiler cannot assume the value is .init because it doesn't have access to the whole codebase to see if some static ctor has changed it. Effectively, you ARE changing it in a static ctor, but just after all the other static ctors have run.

Crucially noted as well: don't use this value inside a static ctor!

-Steve

Reply via email to