On Wednesday, 8 July 2015 at 14:29:56 UTC, Márcio Martins wrote:
I think a good way to avoid this extra annoyance would be to have shared be implicitly convertible to non-shared, or actually, shared should just be ignored inside synchronized blocks, essentially the net result is that the cast is done implicitly at the beginning of the block.

To solve the wrong mutex problem that Dmitry mentioned, perhaps a declarative approach could be used? I wouldn't mind the extra syntax, as it also provides documentation by giving clarity into which mutexes guard what data. With the implicit stripping/ignoring of shared it would become very succinct as well.

Synchronized classes would be able to remove the outer layer of shared, because they can actually guarantee that no one else has access to their member variables (e.g. it would be illegal to make them public). So, when it locks the mutex on a member function call, it can actually guarantee that stripping that outer layer of shared is safe. But it can only strip away the outer layer, because it can't make any guarantees beyond that.

For shared to work like you're suggesting, the compiler would essentially need to make it so that doing _anything_ to a shared object when the mutex wasn't locked would be illegal, and I don't know how feasible that really is. And even if it could do it, all it would be doing would be the same as a synchronized class and stripping away the outer layer of shared. But even then, it wouldn't be enough, because it has no way of stopping you from assigning that partially-unshared object to something and letting it escape, whereas with a synchronized class, everything you're doing is inside of a member function, so it's encapsulated, allowing the compiler to make better guarantees about what you are or aren't doing with the object. So, for what you're proposing, you pretty much might as well just create a synchronized class which uses opDispatch to forward calls to the member variable. It's slightly more verbose at the declaration site but less verbose wherever you use the object. And regardless, it doesn't solve the problem that all that you can strip away of shared is the outer layer. I'm not sure that it's possible to do any more than that with compiler guarantees.

Another thing to consider is that you might need to lock multiple objects with the same mutex or lock multiple mutexes when accessing an object, in which case, what you're proposing is definitely worse than what we'd get from synchronized classes, since they naturally lock multiple items at once (though they don't really cover the case where multiple mutexes need to be involved except that because all of their functionality is encapsulated, it's easier to put the extra locking where it needs to be without missing it).

Maybe we need to do something like you're suggesting, but really, it doesn't seem like it's improving particularly on synchronized classes.

- Jonathan M Davis

Reply via email to