how to assign to shared obj.systime?

Arafel er.krali at
Sat Jul 11 10:15:29 UTC 2020

On 10/7/20 20:30, mw wrote:
> On Friday, 10 July 2020 at 17:35:56 UTC, Steven Schveighoffer wrote:
>> Mark your setTime as shared, then cast away shared (as you don't need 
>> atomics once it's locked), and assign:
>> synchronized setTime(ref SysTime t) shared {
>>     (cast()this).time = t;
>> }
> I know I can make it work by casting, my question is:
> we had a lock on the owning shared object already, WHY we still need the 
> cast to make it compile.

Because the system don't know if just this lock is enough to protect 
this specific access. When you have multiple locks protecting multiple 
data, things can become messy.

What I really miss is some way of telling the compiler "OK, I know what 
I'm doing, I'm already in a critical section, and that all the 
synchronization issues have been already managed by me".

Within this block, shared would implicitly convert to non-shared, and 
the other way round, like this (in a more complex setup with a RWlock):

setTime(ref SysTime t) shared {
	synchronized(myRWMutex.writer) critical_section {  // From this point I 
can forget about shared
		time = t;

As a workaround, I have implemented the following trivial helpers:

mixin template unshareThis() {
     alias S = typeof(this);
     static if (is(S C == shared C)) {}
     static if (is(S == class) || is(S == interface)) {
         C unshared = cast(C) this;
     } else static if (is(S == struct)) {
         C* unshared = cast(C*) &this;
     } else {
         static assert(0, "Only classes, interfaces and structs can be 

pragma(inline, true);
ref unshare(S)(return ref S s) {
	static if (is (S C == shared C)) { }
     return *(cast(C*) &s);

With them you should be able to do either:

synchronized setTime(ref SysTime t) shared {
	mixin unshareThis;
	unshared.time = t;
(useful if you need multiple access), or:

synchronized setTime(ref SysTime t) shared {
	time.unshare = t;

More information about the Digitalmars-d-learn mailing list