Thin Lock Implementation
Sean Kelly
sean at invisibleduck.org
Tue Aug 19 14:41:37 PDT 2008
Steven Schveighoffer wrote:
> "Bartosz Milewski" wrote
>> Steven Schveighoffer wrote:
>>> Reading further messages in your blog, I see that you expect sharing
>>> casts to be recursive (to preserve the transitive nature of it). What if
>>> two shared objects have references to the same shared object? If you
>>> 'unshare' one parent, the other object now is shared, but its
>>> subcomponent is not shared. Is that considered ok?
>> No, it's definitely not ok, but unless there is a reference-counting
>> mechanism in place, we can't do anything about it during casting. However,
>> the sub-objects will be marked as exclusively owned by the casting thread,
>> so any attempt from another thread to lock them will result in an
>> exception. This is true to the spirit of casting in general.
>
> Yes, it's similar to casting something to invariant when you are not sure
> that another reference doesn't exist.
>
> However, in this case, the casting is considered to be an accepted practice
> (and probably more likely than casting something back and forth from
> invariant). Normally, casting has big warning signs all over it, I see this
> as a commonly used feature (or should it be?).
>
> I noticed that you have 'locked' and 'unshared' concepts as separate, the
> former using contention and the latter which is a try-only version. Is
> there any enforcement for not using either of these? For example, if thread
> A tries to access (without casting) a shared object when thread B has casted
> it to unshared, does it succeed?
>
> The thing I'm trying to figure out in all this is, I can see the potential
> with the implementation you are coming up with for some really cool locking
> features, yet the 'shared/unshared' plan also has to do with lock-free
> programming (with fences and stuff, I'm not very familiar with these
> things). It looks to me like you can do one or the other, but not both?
> How do you know which mode you are using a shared variable in?
I think the implication that casting an object to unshared actually
mutates the "shared" bit within the thin lock bitset. Something like this:
shared MyClass c;
void execThreadA()
{
MyClass x = makeLocal( c );
// 'shared' bit in instance of x is now 0
}
T makeLocal(T)( inout T val )
{
// Assume that the state of MyClass is appropriately visible to
// the calling thread because this is a shared object
shared T tmp = val;
val = null;
return cast(unshared) tmp;
}
If the "val = null" assignment is forgotten in makeLocal then an attempt
to synchronize on c will throw a SharingException (or whatever it's called).
The benefit of being able to cast away the shared label is clearly for
performance... if you know that you're the sole owner of a shared object
then you don't need to lock for otherwise synchronized accesses (so
long), much like assertUnique for const/invariant data.
Sean
More information about the Digitalmars-d
mailing list