Difference between __gshared and shared.
Jonathan M Davis via Digitalmars-d
digitalmars-d at puremagic.com
Wed Jul 8 09:59:06 PDT 2015
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
More information about the Digitalmars-d
mailing list