digitalmars.D - Proposal: adding condition variable to object monitors
- Jeremie Pelletier (19/19) Mar 14 2009 I would like to propose the addition of condition variables to the langu...
- Sean Kelly (18/18) Mar 15 2009 They're already in druntime for D2, though they haven't been distributed...
- Jeremie Pelletier (5/28) Mar 15 2009 Hmm, I wasn't aware of that, it's been a while since I last checked the ...
- Sean Kelly (12/43) Mar 15 2009 I considered this as well, but it imposes limitations that aren't
- Jeremie Pelletier (6/14) Mar 15 2009 That's also true, but this still requires explicitly setting the base cl...
- Graham St Jack (7/27) Mar 19 2009 I like this approach, and agree that it is very useful to be able to hav...
- Sean Kelly (4/33) Mar 20 2009 It was meant to be in the last D2 release and something happened with
- Sean Kelly (2/2) Mar 15 2009 Oh, on Windows, condition variables were added in Vista, so that code
I would like to propose the addition of condition variables to the language, or at least to the standard library. They complement the current monitor's mutex very well, are only allocated when needed and can even be part of the base Object class. I've included the basic implementation i currently use on the language runtime I am working on in my spare time (which is a fork of phobos from about a year ago). It supports vista and posix so far, although I didn't test the posix one yet. The included file also contains a working unittest with sample usage. Here is what I added to my Object declaration for even more convenience: --- abstract class Object { // [...] synchronized void Wait(uint interval = -1) { (cast(Monitor*)this.__monitor).Wait(interval); } synchronized void Notify() { (cast(Monitor*)this.__monitor).Notify(); } synchronized void NotifyAll() { (cast(Monitor*)this.__monitor).NotifyAll(); } } private import dlib.Monitor; ---
Mar 14 2009
They're already in druntime for D2, though they haven't been distributed yet (dunno why). And they can act like they're built in: class C { Mutex m; Condition c; this() { // make m this object's monitor m = new Mutex( this ); c = new Condition( m ); } synchronized void foo() { // m is locked c.notify(); } }
Mar 15 2009
Sean Kelly Wrote:They're already in druntime for D2, though they haven't been distributed yet (dunno why). And they can act like they're built in: class C { Mutex m; Condition c; this() { // make m this object's monitor m = new Mutex( this ); c = new Condition( m ); } synchronized void foo() { // m is locked c.notify(); } }Oh, on Windows, condition variables were added in Vista, so that code won't work on XP or earlier.Hmm, I wasn't aware of that, it's been a while since I last checked the druntime project to tell the truth (my runtime has been running the full set of D features for quite some time now). But my proposal was to make both mutexes and conditions completely transparent, only exposing wait, notify and notifyall through Object, as they are implemented directly in the object's hidden monitor. The way druntime does it from your example is explicit: both the mutex and condition have to be manually declared and set, which may be because automatic object monitors are still allocated through alloc/free. Moreover, if only a handful of instanciated objects uses the condition, there's wasted memory for the condition. I heavily modified my runtime to allow most of it to completely remove it's usage of the C alloc and free routines (i think only memory pool structs still use these), so I implemented my condition variable directly into the monitor struct, the monitor is already created lazily for the object and so is the condition for the monitor. And I am aware conditions were added in vista, the file which runs a check at startup for vista. I just haven't coded a fallback for xp and down yet ;)
Mar 15 2009
Jeremie Pelletier wrote:Sean Kelly Wrote:I considered this as well, but it imposes limitations that aren't present with the current approach. It's possible to have more than one condition associated with a particular mutex, for example, and to plug in a shared mutex for interprocess synchronization using 'synchronized'.They're already in druntime for D2, though they haven't been distributed yet (dunno why). And they can act like they're built in: class C { Mutex m; Condition c; this() { // make m this object's monitor m = new Mutex( this ); c = new Condition( m ); } synchronized void foo() { // m is locked c.notify(); } }Oh, on Windows, condition variables were added in Vista, so that code won't work on XP or earlier.Hmm, I wasn't aware of that, it's been a while since I last checked the druntime project to tell the truth (my runtime has been running the full set of D features for quite some time now). But my proposal was to make both mutexes and conditions completely transparent, only exposing wait, notify and notifyall through Object, as they are implemented directly in the object's hidden monitor.The way druntime does it from your example is explicit: both the mutex and condition have to be manually declared and set, which may be because automatic object monitors are still allocated through alloc/free. Moreover, if only a handful of instanciated objects uses the condition, there's wasted memory for the condition.They could always be added to a project-specific base class. The additional memory allocations are still an issue I suppose, but even normal monitors are allocated on the heap, even if it is via malloc.I heavily modified my runtime to allow most of it to completely remove it's usage of the C alloc and free routines (i think only memory pool structs still use these), so I implemented my condition variable directly into the monitor struct, the monitor is already created lazily for the object and so is the condition for the monitor.So the monitor struct is still dynamically allocated, correct?And I am aware conditions were added in vista, the file which runs a check at startup for vista. I just haven't coded a fallback for xp and down yet ;)Just wanted to make sure you were aware of that limitation :-) Creating a correct condvar implementation is non-trivial, so it's worth being aware of.
Mar 15 2009
Sean Kelly Wrote:I considered this as well, but it imposes limitations that aren't present with the current approach. It's possible to have more than one condition associated with a particular mutex, for example, and to plug in a shared mutex for interprocess synchronization using 'synchronized'.That's a good point, I haven't come across such cases yet. I could be solved using a ChainedMonitor wrapper, but that would still require explicit initialization.They could always be added to a project-specific base class. The additional memory allocations are still an issue I suppose, but even normal monitors are allocated on the heap, even if it is via malloc.That's also true, but this still requires explicitly setting the base class, Object is set as the base class implicitly. The issue with the alloc/free memory allocations is tracking the monitors so they get freed, garbage collection is automatic. I haven't seen benchmarks comparing alloc/free to D's new, but I bet D wins.So the monitor struct is still dynamically allocated, correct?Yes, lazily allocated on the garbage collected heap, the only monitor using alloc is the one needed to bootstrap the memory manager. I used to maintain a freelist of monitors but I dropped the code in favor of centralizing memory to the GC which already maintains freelists. I added pool caching to freelist entries to speed it up a lot, all allocations have at least 16 bytes anyways so there's room to cache data. The overhead of setting a pool pointer on a freelist entry is much smaller than querying the pool after reallocating that entry. I've also centralized all the D ABI which uses memory routines into the manager itself to greatly reduce the overhead. I haven't looked at the state of the GC as of now, but if you're interested in seeing my changes I could email you the file, although it's really a different beast almost entirely.
Mar 15 2009
I like this approach, and agree that it is very useful to be able to have more than one condition share the same mutex. I don't mind the handraulic creation of the mutex and condition when you are using a condition, because of the added flexibility and the fact that it doesn't come up much. Being able to use the Object's monitor for the mutex is really good too. Please release it soon!class C { Mutex m; Condition c; this() { // make m this object's monitor m = new Mutex( this ); c = new Condition( m ); } synchronized void foo() { // m is locked c.notify(); } }
Mar 19 2009
Graham St Jack wrote:It was meant to be in the last D2 release and something happened with the script that assembles the zipfile. I'll make double sure it's in this release.I like this approach, and agree that it is very useful to be able to have more than one condition share the same mutex. I don't mind the handraulic creation of the mutex and condition when you are using a condition, because of the added flexibility and the fact that it doesn't come up much. Being able to use the Object's monitor for the mutex is really good too. Please release it soon!class C { Mutex m; Condition c; this() { // make m this object's monitor m = new Mutex( this ); c = new Condition( m ); } synchronized void foo() { // m is locked c.notify(); } }
Mar 20 2009
Oh, on Windows, condition variables were added in Vista, so that code won't work on XP or earlier.
Mar 15 2009