www.digitalmars.com         C & C++   DMDScript  

D - unsynchronize?

reply "Hauke Duden" <H.NS.Duden gmx.net> writes:
I recently looked a bit more closely at the thread synchronizing support in
D.

Is there a way to temporarily release the mutex inside a synchronize block?
This is something that I often wanted to have in JAVA when I was programming
poll-loops.

Here's a small example to demonstrate what I mean:

synchronize
{

    while( continueLoop() )    //the continueLoop call needs to be
synchronized
    {
        flobbox();
        scravench();

        //we need to sleep here to wait for new data to arrive
        //it should NOT be synchronized
        sleep(500);

        receiveData();    //this may receive a command to abort the loop.
    }
}

The problem is the sleep inside the loop. The mutex needs to be released
before the sleep to allow other threads to store new data into the queue. If
I could just put some kind of "unsynchronize" statement around the sleep
everything would be fine. Or is there maybe a way to access to the mutex
directly and call lock/unlock on it?

Without the ability to unsynchronize I would have to restructure the loop to
look like this:


while(true)
{
    synchronize
    {
        if(!continueLoop())
            break;

        flobbox();
        scravench();
    }

    sleep(500);

    synchronize
    {
        receiveData();    //this may receive a command to abort the loop.
    }
}

Even though this example is pretty simplified, it is pretty apparent that
the second version is a lot less readable than the first version.

Any thoughts on this?

Hauke
Sep 28 2003
parent reply Mike Wynn <mike l8night.co.uk> writes:
Hauke Duden wrote:
 I recently looked a bit more closely at the thread synchronizing support in
 D.
 
 Is there a way to temporarily release the mutex inside a synchronize block?
 This is something that I often wanted to have in JAVA when I was programming
 poll-loops.
 
 Here's a small example to demonstrate what I mean:
 
 synchronize
 {
 
     while( continueLoop() )    //the continueLoop call needs to be
 synchronized
     {
         flobbox();
         scravench();
 
         //we need to sleep here to wait for new data to arrive
         //it should NOT be synchronized
         sleep(500);
 
         receiveData();    //this may receive a command to abort the loop.
     }
 }
 
 The problem is the sleep inside the loop. The mutex needs to be released
 before the sleep to allow other threads to store new data into the queue. If
 I could just put some kind of "unsynchronize" statement around the sleep
 everything would be fine. Or is there maybe a way to access to the mutex
 directly and call lock/unlock on it?
 
 Without the ability to unsynchronize I would have to restructure the loop to
 look like this:
 
 
 while(true)
 {
     synchronize
     {
         if(!continueLoop())
             break;
 
         flobbox();
         scravench();
     }
 
     sleep(500);
 
     synchronize
     {
         receiveData();    //this may receive a command to abort the loop.
     }
 }
 
 Even though this example is pretty simplified, it is pretty apparent that
 the second version is a lot less readable than the first version.
 
 Any thoughts on this?
 
 Hauke
 
in java the montor semantics are such that synchronized ( this ) { while( continueLoop() ) { flobbox(); scravench(); this.wait(500); // release monitor // (even if the "count" is greater than 1) receiveData(); } } is what you want (I've used an explict "this" for the wait as "this" could be any object). and this also allows the producer of the data to notify you when data is ready to be recieved rather than you just polling every 500ms. monitors, condition variables or rendevous are far more use than basic mutexes (which can be implemented with the above) and should be availiable in D especially as each OS requires you to subtly different things to create a lockable re-enterable item you want wait on (and obviously notify). you can create what you want in D pseudo code like this assume there is a Mutex class (not looked at D threads/mutex's much yet) auto class Locker { Mutex m; this( Mutex m0 ) { m = m0; m.lock(); } ~this() { m.unlock(); } final void lock() { m.lock(); } final void unlock() { m.unlock(); } } auto class UnLocker { Locker l; this( Locker l0 ) { l = l0; l.unlock(); } ~this() { l.lock(); } } { auto Locker lk( recvMutex ); while( continueLoop() ) { flobbox(); scravench(); { auto Unlocker ulk( lk ); sleep( 500 ); } // ulk destroyed here receiveData(); } } // lk destroyed here. another use for with( auto ... ) with( auto Locker( recvMutex ) ) { while( continueLoop() ) { flobbox(); scravench(); with( auto Unlocker( lk ) ) { sleep( 500 ); } // unlocker destroyed here receiveData(); } } // locker destroyed here.
Sep 28 2003
next sibling parent "Hauke Duden" <H.NS.Duden gmx.net> writes:
"Mike Wynn" wrote:
 in java the montor semantics are such that

 synchronized ( this ) {
       while( continueLoop() ) {
           flobbox();
           scravench();
           this.wait(500); // release monitor
 // (even if the "count" is greater than 1)
           receiveData();
       }
 }

 is what you want (I've used an explict "this" for the wait as "this"
 could be any object). and this also allows the producer of the data to
 notify you when data is ready to be recieved rather than you just
 polling every 500ms.
Thanks! I didn't know that. If I ever have to write a major project in JAVA (I hope not!) I'll keep it in mind ;).
 monitors, condition variables or rendevous are far more use than basic
 mutexes (which can be implemented with the above) and should be
 availiable in D especially as each OS requires you to subtly different
 things to create a lockable re-enterable item you want wait on (and
 obviously notify).
I agree. Synchronize is supported, threading is supported, so ideally D should have the other necessary synchronization primitives as well.
 you can create what you want in D pseudo code like this
 assume there is a Mutex class (not looked at D threads/mutex's much yet)

 auto class Locker {
< Mutex m; <snip> Does this Mutex class exist? It does not seem to be mentioned anywhere in the documentation. Also, using a mutex object and RAII brings us back to where we currently are with C++. And as I understand it, the idea behind the synchronize statement is to have this often used operation (mutex locking/unlocking) as a language construct in order to improve performance and readability. I realize that "unsynchronizing" is used less often than plain synchronize, so I can understand if Walter is reluctant to add a new language construct for it. However, I would very much like it if we could at least have lock/unlock methods for the object mutexes. That way we can use the elegant synchronize statement for the common case and would still be able to use RAII with the lock/unlock methods to simulate "unsynchronize" when needed. Hauke
Sep 28 2003
prev sibling parent reply jhenzie mac.com writes:
I have been giving this some thought over the past week.  I think D should offer
a simple 
mechanism for threading using a similar appriach as Java.

That being 

synchronized ( obj ) {

obj.wait();
obj.wait(uint milliseconds);
obj.tryWait();

obj.notify();1
obj.notifyAll();
}

With the Thread class reduced to the following interface.


class Thread
{
alias int function(void * arg) threadStart;

static Thread detachThread(threadStart selector);
static Thread detachThread(hreadStart selector, void *object);   // PLUS
DELEGATES

static Thread getCurrentThread();

static ThreadPriority getPriority();
static void setPriority(ThreadPriority priority);

static void sleep();
static voif sleep(uint millis);

Object[char[]] getThreadDictionary();   // To provide a simple form of TLS
thread_id getThreadId();

}

The above represents a very simple interface that can accomodate most threading
needs of most 
classifications of application. without exposing developers, particulally the
inexperienced to the 
opportunity to sleep another thread, come on, say it with me, Deadlock.

In recognition that there are circumstance where one might require a more, shall
we say complete, 
thread library, there should also be a collection of function that can act on
the thread_id to provide 
more sophiticated synchronization facilities equivalent to PTHREADS.

Opinions. comments, down right condemnations, all are welcome.

Justin




In article <bl7116$2jin$1 digitaldaemon.com>, Mike Wynn says...
Hauke Duden wrote:
 I recently looked a bit more closely at the thread synchronizing support in
 D.
 
 Is there a way to temporarily release the mutex inside a synchronize block?
 This is something that I often wanted to have in JAVA when I was programming
 poll-loops.
 
 Here's a small example to demonstrate what I mean:
 
 synchronize
 {
 
     while( continueLoop() )    //the continueLoop call needs to be
 synchronized
     {
         flobbox();
         scravench();
 
         //we need to sleep here to wait for new data to arrive
         //it should NOT be synchronized
         sleep(500);
 
         receiveData();    //this may receive a command to abort the loop.
     }
 }
 
 The problem is the sleep inside the loop. The mutex needs to be released
 before the sleep to allow other threads to store new data into the queue. If
 I could just put some kind of "unsynchronize" statement around the sleep
 everything would be fine. Or is there maybe a way to access to the mutex
 directly and call lock/unlock on it?
 
 Without the ability to unsynchronize I would have to restructure the loop to
 look like this:
 
 
 while(true)
 {
     synchronize
     {
         if(!continueLoop())
             break;
 
         flobbox();
         scravench();
     }
 
     sleep(500);
 
     synchronize
     {
         receiveData();    //this may receive a command to abort the loop.
     }
 }
 
 Even though this example is pretty simplified, it is pretty apparent that
 the second version is a lot less readable than the first version.
 
 Any thoughts on this?
 
 Hauke
 
in java the montor semantics are such that synchronized ( this ) { while( continueLoop() ) { flobbox(); scravench(); this.wait(500); // release monitor // (even if the "count" is greater than 1) receiveData(); } } is what you want (I've used an explict "this" for the wait as "this" could be any object). and this also allows the producer of the data to notify you when data is ready to be recieved rather than you just polling every 500ms. monitors, condition variables or rendevous are far more use than basic mutexes (which can be implemented with the above) and should be availiable in D especially as each OS requires you to subtly different things to create a lockable re-enterable item you want wait on (and obviously notify). you can create what you want in D pseudo code like this assume there is a Mutex class (not looked at D threads/mutex's much yet) auto class Locker { Mutex m; this( Mutex m0 ) { m = m0; m.lock(); } ~this() { m.unlock(); } final void lock() { m.lock(); } final void unlock() { m.unlock(); } } auto class UnLocker { Locker l; this( Locker l0 ) { l = l0; l.unlock(); } ~this() { l.lock(); } } { auto Locker lk( recvMutex ); while( continueLoop() ) { flobbox(); scravench(); { auto Unlocker ulk( lk ); sleep( 500 ); } // ulk destroyed here receiveData(); } } // lk destroyed here. another use for with( auto ... ) with( auto Locker( recvMutex ) ) { while( continueLoop() ) { flobbox(); scravench(); with( auto Unlocker( lk ) ) { sleep( 500 ); } // unlocker destroyed here receiveData(); } } // locker destroyed here.
Sep 28 2003
next sibling parent reply "Hauke Duden" <H.NS.Duden gmx.net> writes:
jhenzie mac.com wrote:
 I have been giving this some thought over the past week.  I think D should
offer
 a simple
 mechanism for threading using a similar appriach as Java.

 That being

 synchronized ( obj ) {

 obj.wait();
 obj.wait(uint milliseconds);
 obj.tryWait();

 obj.notify();1
 obj.notifyAll();
 }
I think my opinion on these depends on wether these additional function can be implemented in the generic object without adding additional overhead. I agree that events/signals are needed from time to time, they are not common enough to justify unnecessary bloat for objects that don't need them. I think if these features can not be implemented efficiently it would be best to have standard classes in the RTL instead.
 class Thread
 {
 alias int function(void * arg) threadStart;

 static Thread detachThread(threadStart selector);
 static Thread detachThread(hreadStart selector, void *object);   // PLUS
 DELEGATES
Is detachThread supposed to start a new thread? I would prefer a name like startThread for such a function. Or, even better, a constructor.
 The above represents a very simple interface that can accomodate most
threading
 needs of most
 classifications of application. without exposing developers, particulally
the
 inexperienced to the
 opportunity to sleep another thread, come on, say it with me, Deadlock.
I agree. Killing or suspending other threads is usually a Bad Thing (TM). And quite often it interferes with the semantics of high level languages as well. E.g. it is usually not possible to cleanly kill a thread so that the its resources are properly freed. Just think about finally statements that should be executed or auto objects.that need to be destroyed.
 In recognition that there are circumstance where one might require a more,
shall
 we say complete,
 thread library, there should also be a collection of function that can act
on
 the thread_id to provide
 more sophiticated synchronization facilities equivalent to PTHREADS.
I don't like the idea of using thread ids for this. Why not define thread as an interface instead? That way a "guru level" thread library could easily provide a different implementation, without having to use wrapper objects and stuff like that. How about this: interface IThread { ThreadPriority getPriority(); void setPriority(ThreadPriority priority); bool hasTerminated(); void waitForTermination(int timeout); //AKA join Object[char[]] getDictionary(); //should it be allowed to access the TLS of another thread?? }; alias int function(Object arg) ThreadFunc; IThread createThread(ThreadFunc func,Object arg); IThread createThread(void delegate(Object) dg,Object arg); class ThisThread { static IThread getObject(); static void sleep(int millis=-1); }; A different threading library would simply have to provide a different createThread function that returns an enhanced IThread object. But these objects could still be used as basic threads as well. The only thing that isn't quite consistent with this proposal is that the static IThread object that can be obtained from ThisThread would have to be initialized by the threading library somehow. I'll think about it a bit more... Hauke
Sep 28 2003
parent "Hauke Duden" <H.NS.Duden gmx.net> writes:
"Hauke Duden" wrote:
 I don't like the idea of using thread ids for this. Why not define thread
as
 an interface instead? That way a "guru level" thread library could easily
 provide a different implementation, without having to use wrapper objects
 and stuff like that.

 How about this:
<snip> I just thought about this a bit more and realized that having thread ids is pretty much a necessity to be able to use advanced threading functions. After all, the OS usually provides the actual implementation of threads, so it shouldn't matter which library created them. So, since all threads would have the same abilities, it is pretty nonsensical to artificially limit the functionality of threads that were created by the standard library (the limitation stems from the fact that the "thread object" doesn't support the advanced interfaces). In other words: please disregard the second part of my post ;). Hauke
Sep 28 2003
prev sibling parent reply Mike Wynn <mike l8night.co.uk> writes:
jhenzie mac.com wrote:
 I have been giving this some thought over the past week.  I think D should
offer
 a simple 
 mechanism for threading using a similar appriach as Java.
 
 That being 
 
 synchronized ( obj ) {
 
 obj.wait();
 obj.wait(uint milliseconds);
 obj.tryWait();
 
 obj.notify();1
 obj.notifyAll();
 }
 
I agree IF obj is either a monitor or an object marked as synchronizable. one problem with the Java approach (where all object have an associated monitor) is that every object potentially requires a monitor, this either causes a big resource overhead that is not used, or lots of work for the compiler writer/library writer to deal with the cases when a monitor is not used or only used by one thread. I do not belive that alloing any object to be "synchronized" makes code any more thread safe than only allowing "synchonisation" on specified objects. as D allows lower level programming than Java I think the sync primatives should allow a little more programmer control than the Java approach does. I'm not sure if "wait/notify" should be part of a synchronised obj, interface Syncronizable { /* get monitor (blocks unless you already own the monitor) */ void enter(); /* get monitor (blocks unless you already own the monitor) * will only block for timeout ms, then returns false */ bit enter( int timeout ); /* try to get monitor returns false if already locked * by another thread (never blocks might task switch) */ bit tryEnter(); /* leave monitor (one level) */ void leave() throws UnownedError; /* release all levels */ void release(); } interface Waitable { void wait(); bit wait( int timeout ); // true if notified void notify(); // notify one waiter (non blocking) void notifyAll(); // notify all waiters (non blocking) void notifyExchange(); // notify and switch to waiter } interface SyncWaiter : Waitable, Syncnizable { // here wait/notify calls also call lock thus // notify calls are only non blocking if you have the lock. // so this may be required. bit tryNotify(); // notify if unlocked } synchronized blocks/methods can only be used with objects that implment Syncronizable (implemented internally).
Sep 28 2003
parent reply Graham StJack <grahams adpro.com.au> writes:
I would like to see something pitched at a higher level - the low-level
stuff is just too easy to get wrong.  Something along the lines of the
following code fragment, which is easy to get right, and fairly easy for
the compiler to do, might be worth discussing.  I prefer extending the
language instead of adding new classes because it increases the options
for both compile-time and run-time error checking.

class Queue {
   int itemCount = 0;
   barrier bit empty = true;

   public synchronized void remove() barrier empty {
     itemCount--;
     empty = (itemCount == 0);
   }

   public synchronized void add() {
     itemCount++;
     empty = false;
   }
}

The compiler would:
* Be extended to treat barrier as a keyword.
* Insist on exactly one call that uses a barrier condition for each
   declared barrier.  In the example, it is remove().
* Allow more than one barrier per class.
* For each barrier instance, set up a list of blocked threads.
* Generate extra code for remove() that, if the barrier is true,
   adds the thread to the back of the barrier's list and suspends
   the thread.
* Generate extra code that fires whenever the barrier becomes
   false (ie changes from true to false), that resumes the front thread
   on the barrier's list.


I am assuming here that suspending and resuming threads is a cheap operation.
A similar arrangement could be achieved using pthreads, but I don't know how
to use them directly - I have used Ada protected objects, which do it for me.



Mike Wynn wrote:
 jhenzie mac.com wrote:
 
 I have been giving this some thought over the past week.  I think D 
 should offer
 a simple mechanism for threading using a similar appriach as Java.

 That being
 synchronized ( obj ) {

 obj.wait();
 obj.wait(uint milliseconds);
 obj.tryWait();

 obj.notify();1
 obj.notifyAll();
 }
I agree IF obj is either a monitor or an object marked as synchronizable. one problem with the Java approach (where all object have an associated monitor) is that every object potentially requires a monitor, this either causes a big resource overhead that is not used, or lots of work for the compiler writer/library writer to deal with the cases when a monitor is not used or only used by one thread. I do not belive that alloing any object to be "synchronized" makes code any more thread safe than only allowing "synchonisation" on specified objects. as D allows lower level programming than Java I think the sync primatives should allow a little more programmer control than the Java approach does. I'm not sure if "wait/notify" should be part of a synchronised obj, interface Syncronizable { /* get monitor (blocks unless you already own the monitor) */ void enter(); /* get monitor (blocks unless you already own the monitor) * will only block for timeout ms, then returns false */ bit enter( int timeout ); /* try to get monitor returns false if already locked * by another thread (never blocks might task switch) */ bit tryEnter(); /* leave monitor (one level) */ void leave() throws UnownedError; /* release all levels */ void release(); } interface Waitable { void wait(); bit wait( int timeout ); // true if notified void notify(); // notify one waiter (non blocking) void notifyAll(); // notify all waiters (non blocking) void notifyExchange(); // notify and switch to waiter } interface SyncWaiter : Waitable, Syncnizable { // here wait/notify calls also call lock thus // notify calls are only non blocking if you have the lock. // so this may be required. bit tryNotify(); // notify if unlocked } synchronized blocks/methods can only be used with objects that implment Syncronizable (implemented internally).
Sep 28 2003
parent reply jhenzie mac.com writes:
Interesting,

Every object in D currently has a monitor, check out the memory  model excerpt

Object Model



An object consists of:

offset  contents
------  --------
0:      pointer to vtable
4:      monitor
8...    non-static members


The monitor already exists and provide the serialization primitive for

synchronized ( obj ) {}

While this might appear unnecessary given the ability to synchronize the
encompassing method, 
some classifications of applications desire very low thread contention and thus
the granularity of 
the serialization can be significant thus may require a finer granularity than
by method, the purist 
could argue that one should pull out the granualar critical section and place it
in its own 
synchronized method but at the end of the day ( it gets dark ) , that also has
cost associated with 
it.

Given that desire to provide finer granularity, it would be necessary to support
the monitor per 
object semantics that are already in place and thus the ability to ceed ones
lock on the monitor 
within the scope of the critical section, thus Object.wait(), Object.wait(x);

It is my belief that this is the simplest, most supportable mechanism for
multithreading.  Those of 
us who have had the pleasure, and pain, of using Java can attest to how flexible
this arrangement 
is.

Of course I am also in favour of providing a library as complete as pthreads for
those for which the 
simple solution does not suffice, but to be honest I would be very surprised if
it was often used.

I have yet to fix the linux deadlock problem in the existing implementation,
windows fix has been 
posted to this forum earlier, just a matter of finding the time to sit down at a
linux box,  But once 
done I would very much enjoy collaborating on this, and I am fairly sure Walter
will be thrilled.

I think its a testament to D that the posts on this forum are more often than
not intelligent, 
rational and balanced.  Visit the javalobby to see what can happen <smile/>

Justin




In article <bl89h4$15vl$1 digitaldaemon.com>, Graham StJack says...
I would like to see something pitched at a higher level - the low-level
stuff is just too easy to get wrong.  Something along the lines of the
following code fragment, which is easy to get right, and fairly easy for
the compiler to do, might be worth discussing.  I prefer extending the
language instead of adding new classes because it increases the options
for both compile-time and run-time error checking.

class Queue {
   int itemCount = 0;
   barrier bit empty = true;

   public synchronized void remove() barrier empty {
     itemCount--;
     empty = (itemCount == 0);
   }

   public synchronized void add() {
     itemCount++;
     empty = false;
   }
}

The compiler would:
* Be extended to treat barrier as a keyword.
* Insist on exactly one call that uses a barrier condition for each
   declared barrier.  In the example, it is remove().
* Allow more than one barrier per class.
* For each barrier instance, set up a list of blocked threads.
* Generate extra code for remove() that, if the barrier is true,
   adds the thread to the back of the barrier's list and suspends
   the thread.
* Generate extra code that fires whenever the barrier becomes
   false (ie changes from true to false), that resumes the front thread
   on the barrier's list.


I am assuming here that suspending and resuming threads is a cheap operation.
A similar arrangement could be achieved using pthreads, but I don't know how
to use them directly - I have used Ada protected objects, which do it for me.



Mike Wynn wrote:
 jhenzie mac.com wrote:
 
 I have been giving this some thought over the past week.  I think D 
 should offer
 a simple mechanism for threading using a similar appriach as Java.

 That being
 synchronized ( obj ) {

 obj.wait();
 obj.wait(uint milliseconds);
 obj.tryWait();

 obj.notify();1
 obj.notifyAll();
 }
I agree IF obj is either a monitor or an object marked as synchronizable. one problem with the Java approach (where all object have an associated monitor) is that every object potentially requires a monitor, this either causes a big resource overhead that is not used, or lots of work for the compiler writer/library writer to deal with the cases when a monitor is not used or only used by one thread. I do not belive that alloing any object to be "synchronized" makes code any more thread safe than only allowing "synchonisation" on specified objects. as D allows lower level programming than Java I think the sync primatives should allow a little more programmer control than the Java approach does. I'm not sure if "wait/notify" should be part of a synchronised obj, interface Syncronizable { /* get monitor (blocks unless you already own the monitor) */ void enter(); /* get monitor (blocks unless you already own the monitor) * will only block for timeout ms, then returns false */ bit enter( int timeout ); /* try to get monitor returns false if already locked * by another thread (never blocks might task switch) */ bit tryEnter(); /* leave monitor (one level) */ void leave() throws UnownedError; /* release all levels */ void release(); } interface Waitable { void wait(); bit wait( int timeout ); // true if notified void notify(); // notify one waiter (non blocking) void notifyAll(); // notify all waiters (non blocking) void notifyExchange(); // notify and switch to waiter } interface SyncWaiter : Waitable, Syncnizable { // here wait/notify calls also call lock thus // notify calls are only non blocking if you have the lock. // so this may be required. bit tryNotify(); // notify if unlocked } synchronized blocks/methods can only be used with objects that implment Syncronizable (implemented internally).
Sep 28 2003
next sibling parent reply Hauke Duden <H.NS.Duden gmx.net> writes:
jhenzie mac.com wrote:
 Interesting,
 
 Every object in D currently has a monitor, check out the memory  model excerpt
<snip>
 The monitor already exists and provide the serialization primitive for
 
 synchronized ( obj ) {}
 
 While this might appear unnecessary given the ability to synchronize the
 encompassing method,
I believe "synchronized" methods use that very same object mutex/monitor. I.e. synchronized void method() { ...code... } is just syntactic sugar for void method() { synchronized(this) { ...code... } } So the object mutex is necessary if you want to have something like the synchronized statement. Hauke
Sep 29 2003
parent jhenzie mac.com writes:
Absolutely true.

I guesst what I am saying is that without the synchronize (obj) facility the
granularity of the 
serialized code is at the method level rather than at the critical code level.

JH


In article <bl8si8$24ji$1 digitaldaemon.com>, Hauke Duden says...
jhenzie mac.com wrote:
 Interesting,
 
 Every object in D currently has a monitor, check out the memory  model excerpt
<snip>
 The monitor already exists and provide the serialization primitive for
 
 synchronized ( obj ) {}
 
 While this might appear unnecessary given the ability to synchronize the
 encompassing method,
I believe "synchronized" methods use that very same object mutex/monitor. I.e. synchronized void method() { ...code... } is just syntactic sugar for void method() { synchronized(this) { ...code... } } So the object mutex is necessary if you want to have something like the synchronized statement. Hauke
Sep 29 2003
prev sibling parent reply Graham StJack <grahams adpro.com.au> writes:
jhenzie mac.com wrote:
 Interesting,
 
 Every object in D currently has a monitor, check out the memory  model excerpt
Yes, I know. what I was driving at is that having synchronized methods isn't enough, and hence enter java's Object methods wait(), wait(x) and notify() which allow threads to communicate with each other meaningfully, not just keep out of each other's way. What I am suggesting is an alternative to wait() and notify() that is pitched at a higher level, and is thus easier to use safely. Of course I will be delighted when D is extended to allow inter-thread cooperation, whatever form it takes.
 
 Object Model
 
 
 
 An object consists of:
 
 offset  contents
 ------  --------
 0:      pointer to vtable
 4:      monitor
 8...    non-static members
 
 
 The monitor already exists and provide the serialization primitive for
 
 synchronized ( obj ) {}
 
 While this might appear unnecessary given the ability to synchronize the
 encompassing method, 
 some classifications of applications desire very low thread contention and thus
 the granularity of 
 the serialization can be significant thus may require a finer granularity than
 by method, the purist 
 could argue that one should pull out the granualar critical section and place
it
 in its own 
 synchronized method but at the end of the day ( it gets dark ) , that also has
 cost associated with 
 it.
 
 Given that desire to provide finer granularity, it would be necessary to
support
 the monitor per 
 object semantics that are already in place and thus the ability to ceed ones
 lock on the monitor 
 within the scope of the critical section, thus Object.wait(), Object.wait(x);
 
 It is my belief that this is the simplest, most supportable mechanism for
 multithreading.  Those of 
 us who have had the pleasure, and pain, of using Java can attest to how
flexible
 this arrangement 
 is.
 
 Of course I am also in favour of providing a library as complete as pthreads
for
 those for which the 
 simple solution does not suffice, but to be honest I would be very surprised if
 it was often used.
 
 I have yet to fix the linux deadlock problem in the existing implementation,
 windows fix has been 
 posted to this forum earlier, just a matter of finding the time to sit down at
a
 linux box,  But once 
 done I would very much enjoy collaborating on this, and I am fairly sure Walter
 will be thrilled.
 
 I think its a testament to D that the posts on this forum are more often than
 not intelligent, 
 rational and balanced.  Visit the javalobby to see what can happen <smile/>
 
 Justin
 
 
 
 
 In article <bl89h4$15vl$1 digitaldaemon.com>, Graham StJack says...
 
I would like to see something pitched at a higher level - the low-level
stuff is just too easy to get wrong.  Something along the lines of the
following code fragment, which is easy to get right, and fairly easy for
the compiler to do, might be worth discussing.  I prefer extending the
language instead of adding new classes because it increases the options
for both compile-time and run-time error checking.

class Queue {
  int itemCount = 0;
  barrier bit empty = true;

  public synchronized void remove() barrier empty {
    itemCount--;
    empty = (itemCount == 0);
  }

  public synchronized void add() {
    itemCount++;
    empty = false;
  }
}

The compiler would:
* Be extended to treat barrier as a keyword.
* Insist on exactly one call that uses a barrier condition for each
  declared barrier.  In the example, it is remove().
* Allow more than one barrier per class.
* For each barrier instance, set up a list of blocked threads.
* Generate extra code for remove() that, if the barrier is true,
  adds the thread to the back of the barrier's list and suspends
  the thread.
* Generate extra code that fires whenever the barrier becomes
  false (ie changes from true to false), that resumes the front thread
  on the barrier's list.


I am assuming here that suspending and resuming threads is a cheap operation.
A similar arrangement could be achieved using pthreads, but I don't know how
to use them directly - I have used Ada protected objects, which do it for me.



Mike Wynn wrote:

jhenzie mac.com wrote:


I have been giving this some thought over the past week.  I think D 
should offer
a simple mechanism for threading using a similar appriach as Java.

That being
synchronized ( obj ) {

obj.wait();
obj.wait(uint milliseconds);
obj.tryWait();

obj.notify();1
obj.notifyAll();
}
I agree IF obj is either a monitor or an object marked as synchronizable. one problem with the Java approach (where all object have an associated monitor) is that every object potentially requires a monitor, this either causes a big resource overhead that is not used, or lots of work for the compiler writer/library writer to deal with the cases when a monitor is not used or only used by one thread. I do not belive that alloing any object to be "synchronized" makes code any more thread safe than only allowing "synchonisation" on specified objects. as D allows lower level programming than Java I think the sync primatives should allow a little more programmer control than the Java approach does. I'm not sure if "wait/notify" should be part of a synchronised obj, interface Syncronizable { /* get monitor (blocks unless you already own the monitor) */ void enter(); /* get monitor (blocks unless you already own the monitor) * will only block for timeout ms, then returns false */ bit enter( int timeout ); /* try to get monitor returns false if already locked * by another thread (never blocks might task switch) */ bit tryEnter(); /* leave monitor (one level) */ void leave() throws UnownedError; /* release all levels */ void release(); } interface Waitable { void wait(); bit wait( int timeout ); // true if notified void notify(); // notify one waiter (non blocking) void notifyAll(); // notify all waiters (non blocking) void notifyExchange(); // notify and switch to waiter } interface SyncWaiter : Waitable, Syncnizable { // here wait/notify calls also call lock thus // notify calls are only non blocking if you have the lock. // so this may be required. bit tryNotify(); // notify if unlocked } synchronized blocks/methods can only be used with objects that implment Syncronizable (implemented internally).
Sep 29 2003
parent jhenzie mac.com writes:
Graham,

Totally with you.

IMHO the wait, notify mechanism is pretty easy to use, and, given the ownership
sematics, is very safe, but I am all for providing a mechanism that communicates
the intent.

JH

In article <blact3$16hj$1 digitaldaemon.com>, Graham StJack says...
jhenzie mac.com wrote:
 Interesting,
 
 Every object in D currently has a monitor, check out the memory  model excerpt
Yes, I know. what I was driving at is that having synchronized methods isn't enough, and hence enter java's Object methods wait(), wait(x) and notify() which allow threads to communicate with each other meaningfully, not just keep out of each other's way. What I am suggesting is an alternative to wait() and notify() that is pitched at a higher level, and is thus easier to use safely. Of course I will be delighted when D is extended to allow inter-thread cooperation, whatever form it takes.
 
 Object Model
 
 
 
 An object consists of:
 
 offset  contents
 ------  --------
 0:      pointer to vtable
 4:      monitor
 8...    non-static members
 
 
 The monitor already exists and provide the serialization primitive for
 
 synchronized ( obj ) {}
 
 While this might appear unnecessary given the ability to synchronize the
 encompassing method, 
 some classifications of applications desire very low thread contention and thus
 the granularity of 
 the serialization can be significant thus may require a finer granularity than
 by method, the purist 
 could argue that one should pull out the granualar critical section and place
it
 in its own 
 synchronized method but at the end of the day ( it gets dark ) , that also has
 cost associated with 
 it.
 
 Given that desire to provide finer granularity, it would be necessary to
support
 the monitor per 
 object semantics that are already in place and thus the ability to ceed ones
 lock on the monitor 
 within the scope of the critical section, thus Object.wait(), Object.wait(x);
 
 It is my belief that this is the simplest, most supportable mechanism for
 multithreading.  Those of 
 us who have had the pleasure, and pain, of using Java can attest to how
flexible
 this arrangement 
 is.
 
 Of course I am also in favour of providing a library as complete as pthreads
for
 those for which the 
 simple solution does not suffice, but to be honest I would be very surprised if
 it was often used.
 
 I have yet to fix the linux deadlock problem in the existing implementation,
 windows fix has been 
 posted to this forum earlier, just a matter of finding the time to sit down at
a
 linux box,  But once 
 done I would very much enjoy collaborating on this, and I am fairly sure Walter
 will be thrilled.
 
 I think its a testament to D that the posts on this forum are more often than
 not intelligent, 
 rational and balanced.  Visit the javalobby to see what can happen <smile/>
 
 Justin
 
 
 
 
 In article <bl89h4$15vl$1 digitaldaemon.com>, Graham StJack says...
 
I would like to see something pitched at a higher level - the low-level
stuff is just too easy to get wrong.  Something along the lines of the
following code fragment, which is easy to get right, and fairly easy for
the compiler to do, might be worth discussing.  I prefer extending the
language instead of adding new classes because it increases the options
for both compile-time and run-time error checking.

class Queue {
  int itemCount = 0;
  barrier bit empty = true;

  public synchronized void remove() barrier empty {
    itemCount--;
    empty = (itemCount == 0);
  }

  public synchronized void add() {
    itemCount++;
    empty = false;
  }
}

The compiler would:
* Be extended to treat barrier as a keyword.
* Insist on exactly one call that uses a barrier condition for each
  declared barrier.  In the example, it is remove().
* Allow more than one barrier per class.
* For each barrier instance, set up a list of blocked threads.
* Generate extra code for remove() that, if the barrier is true,
  adds the thread to the back of the barrier's list and suspends
  the thread.
* Generate extra code that fires whenever the barrier becomes
  false (ie changes from true to false), that resumes the front thread
  on the barrier's list.


I am assuming here that suspending and resuming threads is a cheap operation.
A similar arrangement could be achieved using pthreads, but I don't know how
to use them directly - I have used Ada protected objects, which do it for me.



Mike Wynn wrote:

jhenzie mac.com wrote:


I have been giving this some thought over the past week.  I think D 
should offer
a simple mechanism for threading using a similar appriach as Java.

That being
synchronized ( obj ) {

obj.wait();
obj.wait(uint milliseconds);
obj.tryWait();

obj.notify();1
obj.notifyAll();
}
I agree IF obj is either a monitor or an object marked as synchronizable. one problem with the Java approach (where all object have an associated monitor) is that every object potentially requires a monitor, this either causes a big resource overhead that is not used, or lots of work for the compiler writer/library writer to deal with the cases when a monitor is not used or only used by one thread. I do not belive that alloing any object to be "synchronized" makes code any more thread safe than only allowing "synchonisation" on specified objects. as D allows lower level programming than Java I think the sync primatives should allow a little more programmer control than the Java approach does. I'm not sure if "wait/notify" should be part of a synchronised obj, interface Syncronizable { /* get monitor (blocks unless you already own the monitor) */ void enter(); /* get monitor (blocks unless you already own the monitor) * will only block for timeout ms, then returns false */ bit enter( int timeout ); /* try to get monitor returns false if already locked * by another thread (never blocks might task switch) */ bit tryEnter(); /* leave monitor (one level) */ void leave() throws UnownedError; /* release all levels */ void release(); } interface Waitable { void wait(); bit wait( int timeout ); // true if notified void notify(); // notify one waiter (non blocking) void notifyAll(); // notify all waiters (non blocking) void notifyExchange(); // notify and switch to waiter } interface SyncWaiter : Waitable, Syncnizable { // here wait/notify calls also call lock thus // notify calls are only non blocking if you have the lock. // so this may be required. bit tryNotify(); // notify if unlocked } synchronized blocks/methods can only be used with objects that implment Syncronizable (implemented internally).
Sep 29 2003