On Friday, July 10, 2020 12:30:16 PM MDT mw via Digitalmars-d-learn 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 type system has no way of knowing that access to that shared object is currently protected, and baking that into the type system is actually very difficult - especially if you don't want to be super restrictive about what is allowed. The only scheme that anyone has come up thus far with which would work is TDPL's synchronized classes (which have never been implemented), but in order for them to work, they would have to be restrictive about what you do with the member variables, and ultimately, the compiler would still only be able to implicitly remove the outer layer of shared (i.e. the layer sitting directly in the class object itself), since that's the only layer that the compiler could prove hadn't had any references to it escape. So, you'd have to create a class just to be able to avoid casting, and it wouldn't implicitly remove enough of shared to be useful in anything but simple cases. Sure, it would be great if we could have shared be implicitly removed when the object in question is protected by a mutex, but the type system would have to know that that mutex was associated with that object and be able to prove not only that that mutex was locked but that no other piece of code could possibly access that shared object without locking that mutex. It would also have to be able to prove that no thread-local references escaped from the code where shared was implicitly removed. It's incredibly difficult to bake the required information into the type system even while be very restrictive about what's allowed let alone while allowing code to be as flexible as code generally needs to be - especially in a systems language like D. If someone actually manages to come up with an appropriate scheme that lets us implicitly removed shared under some set of circumstances, then we may very well get that ability at some point in the future, but it seems very unlikely as things stand, and even if someone did manage it, it's even less likely that it would work outside of a limited set of use cases, since there are a variety of ways of dealing with safely accessing data across threads. So, for the forseeable future, explicit casts are generally going to be required when dealing with shared. - Jonathan M Davis