On Thursday, July 05, 2018 11:31:15 FeepingCreature via Digitalmars-d wrote: > On Wednesday, 4 July 2018 at 10:47:12 UTC, Jonathan M Davis wrote: > > At this point, to operate on anything that's shared, either > > means using atomics or protecting the data with a mutex (be > > that with a synchronized block / function or a mutex object) > > and temporarily casting away shared while operating on the > > data. Afterwards, the mutex is released, and at that point, > > there should just be only shared references to the data. About > > the only time that operating directly on a shared object then > > makes sense is when it manages the atomics or mutex and > > associated cast internally. > > > > ... > > It's a very difficult problem. Synchronized classes were > > proposed in an attempt to solve it, but even if they were fully > > implemented, they'd only help partially, because they can only > > strip off the outermost layer of shared. In order for the > > compiler to cast away shared for you, it has to be able to > > guarantee that there are no unprotected references to that > > data, and because D doesn't have any kind of ownership system > > in the language, we don't have a clean way to do it. > > Once we have DIP1000, can accessing shared class members in a > synchronized class (optionally? implicitly?) result in scoped > rvalues?
I'm not quite sure what you're asking exactly, but if you're wondering if scope can help indicate that a reference hasn't escaped from a synchronized class, then I don't think so. e.g. something like mySynchObj.foo().func(); or scope foo = mySynchObj.foo(); foo.bar(); would already be a problem, even though scope prevents the reference from being kept around, because another thread could come in and access foo or what it refers to at the same time. The mutex would have been released as soon as the member function returned. Maybe some changes could be made to how synchronized works so that the mutex would be left locked until the expression terminated, and then if all you're allowed to do is call a member function on the scope reference that's returned, then maybe it could work - but even then, you have the problem of a reference escaping via that member function call, and even a scoped reference is unacceptable, because then it could escape the mutex's lock, even if it didn't last long - and that's assuming that the mutex was made to stay locked for the duration of the expression rather than for the duration of the member function call. scope is designed around making sure that the lifetime of a reference, ref, pointer, or dynamic array is not longer than the lifetime of the object it refers to and not around the lifetime of a function call or mutex lock. It has to be guaranteed that any time the data is accessed, the mutex protecting it is locked. If it could be guaranteed that the data never escapes - even temporarily - from any member function call (i.e. they never return any references to any member variables or anything they refer to, and all of the member functions are pure), and it's guaranteed that the data in the member variables was all created inside the class (so any data that was passed to a member function - including the constructor - and then assigned to or passed to a member variable is a value type or it was a reference type that was duped - though we don't really have a way to guarantee at this point that data was duped), then I think that it would be possible to strip away the other layers of shared and call free functions inside member functions. But that would be a pretty big restriction as well as probably a pain to code correctly in the compiler. I don't know. Some improvements may be possible there, but it's very tricky. You have to be able to guarantee that no data that ever has shared implicitly removed from it is ever accessed while the mutex isn't locked, and the more you try to allow, the harder it is to plug the holes. Much as I agree that the casting sucks, I'm increasingly of the opinion that the extra complications required to implicitly remove shared from even part of an object quickly become too much to be worth it. Ultimately, I think that the only real downside to the casting is that it requires that the programmer get it right, whereas any time we can automate it, the compiler guarantees it. Having the compiler guarantee it is very desirable, but the extra restrictions required to make that guarantee can't be too restrictive, or it quickly becomes saner to just do the cast even if it makes you verify it yourself. - Jonathan M Davis
