www.digitalmars.com         C & C++   DMDScript  

D - Waitable objects

reply mike parker <mike aldacron.com> writes:
I've fallen in love with D over the past few months and recently have 
begun to use for some serious work. I'm currently implementing a server 
with D and one of the things I'm missing is the ability to signal a 
mutex in order to wait on something else - i.e. Java's wait() and notify().

In Java, calling wait() on an object signals any synchronization lock so 
that other threads may operate on the synchronized object. Since I can't 
find a way to do the same via Phobos, I've ported a public domain 
waitiable mutex class from C++. This, of course, means that I have to 
use the mutex rather than the synchronized keyword and that eventually I 
will have to knock up Linux/Mac versions as well.

While it's no big deal since the code is minimal, it would be a better 
fit (for portability and consistency) if the same functionality were 
built in to D. I'm sure others will eventually have need of it as well. 
So, does this already exist and I've overlooked it? And if not, would it 
be possible to include it in a future version?

This isn't a show stopper. Just something I would love to see :)

--
Mike Parker
Apr 20 2004
next sibling parent reply mike parker <mike aldacron.com> writes:
Since my original post appears vague upon reading it, here's an example 
of what I mean:


void waitForSomething()
{
    synchronized(someObject)
    {
       // the wait method signals/releases the synchronization lock on 

       // someObject so that other threads may operate on it.
       while(someObject.isNotReady())
          someObject.wait();
    }
}

void doSomething()
{
    synchronized(someObject)
    {
       someObject.doSomething();
       // notify wakes up the waiting thread will then reacquire the lock
       // on someObject
       someObject.notify();
    }
}

My current solution looks like this:

void waitForSomething()
{
    someObject.mutex.lock();
    if(someObject.isNotReady())
       someObject.mutex.wait();
    someObject.mutex.unlock();
}

void doSomething()
{
    someObject.mutex.lock();
    someObject.doSomething();
    someObject.mutex.notify();
    someObject.mutex.unlock();
}

The former is much more preferable methinks.

mike parker wrote:

 I've fallen in love with D over the past few months and recently have 
 begun to use for some serious work. I'm currently implementing a server 
 with D and one of the things I'm missing is the ability to signal a 
 mutex in order to wait on something else - i.e. Java's wait() and notify().
 

Apr 20 2004
next sibling parent reply "Ben Hinkle" <bhinkle4 juno.com> writes:
 My current solution looks like this:

 void waitForSomething()
 {
     someObject.mutex.lock();
     if(someObject.isNotReady())
        someObject.mutex.wait();
     someObject.mutex.unlock();
 }

 void doSomething()
 {
     someObject.mutex.lock();
     someObject.doSomething();
     someObject.mutex.notify();
     someObject.mutex.unlock();
 }

Could using "auto" help? I haven't actually tried this and who knows what the performance would be, but I'm thinking of something like: void waitForSomething() { auto AutoLock alock = someObject.mutex.autolock(); if(someObject.isNotReady()) alock.wait(); } void doSomething() { auto AutoLock alock = someObject.mutex.autolock(); someObject.doSomething(); alock.notify(); }
Apr 20 2004
parent mike parker <mike aldacron.com> writes:
Ben Hinkle wrote:

 
 Could using "auto" help? I haven't actually tried this and who knows what
 the performance would be, but I'm thinking of something like:
 
 void waitForSomething()
 {
     auto AutoLock alock = someObject.mutex.autolock();
     if(someObject.isNotReady())
        alock.wait();
 }
 
 void doSomething()
 {
     auto AutoLock alock = someObject.mutex.autolock();
     someObject.doSomething();
     alock.notify();
 }

That would certainly make it look better :) But it's not the syntax that bothers me so much as the fact that the built-in synchronization has to be bypassed altogether.
Apr 20 2004
prev sibling parent reply eric anderton at yahoo dot com <eric_member pathlink.com> writes:
I agree that D could definately use some more OS-neutral features like mutexes,
events, thread synchronization, etc.  In the meantime, I may have something you
can use that'll clean up your code:

// Assumes that Mutex is a defined mutex class for brevity.
// (The mutex itself could easily be encapsulated here though.)
// note the use of the 'auto' keyword to make this sensitive to scoping rules.

auto class Synchronized{
Mutex mutex; 

Synchronized(void* obj=this){
mutex.lock(obj);
if(mutex.isNotReady()) mutex.wait();
}

~Sychronized(){
mutex.unlock();
}
}

// The gist here is that the Synchronized object automatically releases 
// its mutex when it falls out of scope.
// Here's a threadsafe counter class using the Sychronized class:

class Counter{
int count;

void increment(){
Synchronized sync(this);
count++;
}

int getCount(){
Synchronized sync(this);
return(count);
}
}

// To synchronize a single function, just declare as static

int count;

int incrementCount(){
static Synchronized sync();
count++;
return(count);
}

I haven't coded in D for a while, but I have used a similar mechanism in C and
C++ programs.  Hope this helps.

In article <c6315f$1vke$1 digitaldaemon.com>, mike parker says...
Since my original post appears vague upon reading it, here's an example 
of what I mean:

 ... code example cut for brevity ...

 I've fallen in love with D over the past few months and recently have 
 begun to use for some serious work. I'm currently implementing a server 
 with D and one of the things I'm missing is the ability to signal a 
 mutex in order to wait on something else - i.e. Java's wait() and notify().
 


Apr 20 2004
parent ericanderton yahoo.com writes:
Ick.

Please ignore the single function example.. it won't work that way.

Sorry for any confusion.

In article <c63nep$5dt$1 digitaldaemon.com>, eric anderton at yahoo dot com
says...
I agree that D could definately use some more OS-neutral features like mutexes,
events, thread synchronization, etc.  In the meantime, I may have something you
can use that'll clean up your code:

// Assumes that Mutex is a defined mutex class for brevity.
// (The mutex itself could easily be encapsulated here though.)
// note the use of the 'auto' keyword to make this sensitive to scoping rules.

auto class Synchronized{
Mutex mutex; 

Synchronized(void* obj=this){
mutex.lock(obj);
if(mutex.isNotReady()) mutex.wait();
}

~Sychronized(){
mutex.unlock();
}
}

// The gist here is that the Synchronized object automatically releases 
// its mutex when it falls out of scope.
// Here's a threadsafe counter class using the Sychronized class:

class Counter{
int count;

void increment(){
Synchronized sync(this);
count++;
}

int getCount(){
Synchronized sync(this);
return(count);
}
}

// To synchronize a single function, just declare as static

int count;

int incrementCount(){
static Synchronized sync();
count++;
return(count);
}

I haven't coded in D for a while, but I have used a similar mechanism in C and
C++ programs.  Hope this helps.

In article <c6315f$1vke$1 digitaldaemon.com>, mike parker says...
Since my original post appears vague upon reading it, here's an example 
of what I mean:

 ... code example cut for brevity ...

 I've fallen in love with D over the past few months and recently have 
 begun to use for some serious work. I'm currently implementing a server 
 with D and one of the things I'm missing is the ability to signal a 
 mutex in order to wait on something else - i.e. Java's wait() and notify().
 



Apr 20 2004
prev sibling parent reply Ben Hinkle <bhinkle4 juno.com> writes:
On Tue, 20 Apr 2004 19:59:43 +0000, mike parker <mike aldacron.com>
wrote:

I've fallen in love with D over the past few months and recently have 
begun to use for some serious work. I'm currently implementing a server 
with D and one of the things I'm missing is the ability to signal a 
mutex in order to wait on something else - i.e. Java's wait() and notify().

D's "synchronized" is implemented on Windows using CriticalSections (see src/phobos/internal/critical.c) and those can't be passed into the Windows wait functions. I don't know if/how Java-style synchronized/wait/notify can be implemented on top of CriticalSections or if it should go in std.thread.
In Java, calling wait() on an object signals any synchronization lock so 
that other threads may operate on the synchronized object. Since I can't 
find a way to do the same via Phobos, I've ported a public domain 
waitiable mutex class from C++. This, of course, means that I have to 
use the mutex rather than the synchronized keyword and that eventually I 
will have to knock up Linux/Mac versions as well.

Can you give a URL to the C++ code? Does it contain other useful stuff besides mutex? A recent thread brought up Doug Lea's concurrent library for Java and some of us are looking at that right now.
While it's no big deal since the code is minimal, it would be a better 
fit (for portability and consistency) if the same functionality were 
built in to D. I'm sure others will eventually have need of it as well. 
So, does this already exist and I've overlooked it? And if not, would it 
be possible to include it in a future version?

If the trade-off is performance of CriticalSections vs flexibility of Mutex I'd rather go with performance. Anyone know what the performance hit is to use Mutex? -Ben
Apr 20 2004
next sibling parent reply mike parker <mike aldacron.com> writes:
Ben Hinkle wrote:

 D's "synchronized" is implemented on Windows using CriticalSections
 (see src/phobos/internal/critical.c) and those can't be passed into
 the Windows wait functions. I don't know if/how Java-style
 synchronized/wait/notify can be implemented on top of CriticalSections
 or if it should go in std.thread.

I think it would be possible using Event objects. Based on an example from MSDN: user synchronizes on an object - D calls EnterCriticalSection user calls object.wait() - D calls LeaveCriticalSection - D calls WaitForSingleObject on an Event object associated with the lock user calls object.notify() - D signals the Event object via SetEvent - WaitForSingleObject returns, and immediately EnterCriticalSection is called to resume the lock Replace WaitForSingleObject with WaitForMultipleObjects, throw in an Event object array, and you have the basis for Object.notifyAll(). notify() would then just signal the first event in the queue. The Event objects would only need to be created/destroyed when wait() is called, or a number of them could be preallocated in a pool. The implementation I ported is a much more basic use of Event objects, boolean flags, and SignalObjectAndWait(). I'm a neophyte with Win32 threads yet (and MTing in general) so I'm not sure which way would be the most efficient.
 Can you give a URL to the C++ code? Does it contain other useful stuff
 besides mutex? A recent thread brought up Doug Lea's concurrent
 library for Java and some of us are looking at that right now.

http://www.jordanzimmerman.com/index.php?n=3&c=1 I didn't look through the site to see what else was there - just stumbled across the Mutex stuff via google.
 If the trade-off is performance of CriticalSections vs flexibility of
 Mutex I'd rather go with performance. Anyone know what the performance
 hit is to use Mutex?

I've looked at a few Win32 Mutex implementations in open source projects over the past couple of years and those which didn't use CriticalSections (which most did) used Event objects via CreateEvent rather than CreateMutex. I'm fairly certain this is because Event objects have less overhead than Mutex objects under the hood. Take a look at this MSDN article: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dndllpro/html/msdn_locktest.asp It deals with something similar to what we're discussing, and the author provides implementations for each of the basic Win32 implementation objects. Pay particular attention to the performance chart near the bottom of the page. Mutex objects suck eggs there, with Semaphores not much better. Standard Events performed just as well as Crit sections. I would guess the same would be true here, but guesses mean nothing until benchmarked.
Apr 20 2004
parent Ben Hinkle <bhinkle4 juno.com> writes:
mike parker wrote:

 Ben Hinkle wrote:
 
 D's "synchronized" is implemented on Windows using CriticalSections
 (see src/phobos/internal/critical.c) and those can't be passed into
 the Windows wait functions. I don't know if/how Java-style
 synchronized/wait/notify can be implemented on top of CriticalSections
 or if it should go in std.thread.

I think it would be possible using Event objects. Based on an example from MSDN: user synchronizes on an object - D calls EnterCriticalSection user calls object.wait() - D calls LeaveCriticalSection - D calls WaitForSingleObject on an Event object associated with the lock user calls object.notify() - D signals the Event object via SetEvent - WaitForSingleObject returns, and immediately EnterCriticalSection is called to resume the lock

Seems reasonable, though at first glance the multi-step actions in wait and notify would have to become atomic or wrapped in locks themselves, I think. Otherwise the notify could call SetEvent before the WaitForSingleEvent has happened.
 Replace WaitForSingleObject with WaitForMultipleObjects, throw in an
 Event object array, and you have the basis for Object.notifyAll().
 notify() would then just signal the first event in the queue. The Event
 objects would only need to be created/destroyed when wait() is called,
 or a number of them could be preallocated in a pool. The implementation
 I ported is a much more basic use of Event objects, boolean flags, and
 SignalObjectAndWait(). I'm a neophyte with Win32 threads yet (and MTing
 in general) so I'm not sure which way would be the most efficient.
 
 Can you give a URL to the C++ code? Does it contain other useful stuff
 besides mutex? A recent thread brought up Doug Lea's concurrent
 library for Java and some of us are looking at that right now.

http://www.jordanzimmerman.com/index.php?n=3&c=1 I didn't look through the site to see what else was there - just stumbled across the Mutex stuff via google.

ok, thanks. I'll check it out.
 If the trade-off is performance of CriticalSections vs flexibility of
 Mutex I'd rather go with performance. Anyone know what the performance
 hit is to use Mutex?

I've looked at a few Win32 Mutex implementations in open source projects over the past couple of years and those which didn't use CriticalSections (which most did) used Event objects via CreateEvent rather than CreateMutex. I'm fairly certain this is because Event objects have less overhead than Mutex objects under the hood. Take a look at this MSDN article:

 
 It deals with something similar to what we're discussing, and the author
 provides implementations for each of the basic Win32 implementation
 objects. Pay particular attention to the performance chart near the
 bottom of the page. Mutex objects suck eggs there, with Semaphores not
 much better. Standard Events performed just as well as Crit sections. I
 would guess the same would be true here, but guesses mean nothing until
 benchmarked.

ah. very interesting article.
Apr 20 2004
prev sibling parent Ben Hinkle <bhinkle4 juno.com> writes:
 D's "synchronized" is implemented on Windows using CriticalSections
 (see src/phobos/internal/critical.c)

oops - synchronized is in internal/monitor.c. I'm not sure now what critical.c is for. An object's monitor (on Windows) is a pointer to a CRITICAL_SECTION. -Ben
Apr 20 2004