TDPL, shared data, and Phobos

Bane branimir.milosavljevic at gmail.com
Tue Jul 13 17:34:18 PDT 2010


I am few days old in playin with D2 and whole shared stuff, so I am probably wrong in something. 

You should probably declare your example class MyValue synchronized instead of shared. It implies that class is shared too, and this way all methods are synchronized. In D1 you could mix synchronized and non syncrhonized methods in class, in D2 its whole or nothing. This way you don't need _lock var in your example.

So this would work (i guess)

synchronized class MyValue {
     int inc() {
            return _value++;
      }
     int get() {
            return _value;
     }
     private int _value;
}

shared MyValue sharedVal;

void main(){
  sharedVal = new shared(MyValue );
}

 I noticed that in D1 synchronized methods of same class share same lock, while in this D2 example (when the whole class is declared synchronized), each method has its own lock. 

> Also, is there any documentation on the actual semantics of shared? http://www.digitalmars.com/d/2.0/attribute.html is a blank on the subject, and the "migrating to shared" article only talks about simple global state. What are the actual semantics of shared classes, and how do they interact with other code? For instance, after much banging of my head against the desk, I finally wrote a working implementation of a simple shared multi-reader var. Obviously there are better ways to do a simple shared incrementing counter, this is just a first experiment working toward a shared mutable 512MB trie data structure that we have in our app's current C++ implementation:
> 
> > shared class MyValue {
> >     this() {
> >         _lock = cast(shared)new ReadWriteMutex;
> >     }
> > 
> >     int inc() {
> >         synchronized((cast(ReadWriteMutex)_lock).writer) {
> >             return _value++;
> >         }
> >     }
> > 
> >     int get() {
> >         synchronized((cast(ReadWriteMutex)_lock).reader) {
> >             return _value;
> >         }
> >     }
> > 
> >     private ReadWriteMutex _lock;
> >     private int _value;
> > }
> > 
> > shared MyValue sharedVal;
> > ... seems to behave correctly with multiple threads reading and writing ...
> 
> So I can maybe understand the cast(shared) in the ctor. But I have to admit I have absolutely no idea why I had to cast away the shared attribute in the inc/get methods. Is there any documentation on what's really going on in the compiler here? It's a shared method, accessing a shared instance var, why the cast? Is the compiler upset about something in the definition of ReadWriteMutex itself?
> 
> Also, how would one implement this as a struct? My postblit op generates compiler errors about casting between shared/unshared MyValue:
> 
> > shared struct MyValue {
> >    this(this) { _lock = cast(shared) new ReadWriteMutex; } // ERROR
> >    ... same as above ...
> > }
> 
> I recognize the possible race conditions here, but there has to be *some* way to implement a postblit op on a shared struct?
> 
> I hope this doesn't come across as empty complaining, I'm happy to help improve the documentation if I can.



More information about the Digitalmars-d mailing list