October 02, 2007
Steven Schveighoffer wrote:
> 
> So the code above has to do something special by unlocking the object before waiting using an atomic operation.  I think this requires some language support.

Doing this efficiently typically requires OS support.  The library must indicate to the OS that a context switch may not occur while certain portions of the code are executing.  It is possible to implement condvars without OS support as well, but the implementation tends to be fairly complicated.  Look for version(Win32) blocks in the Tango implementation for one such example.

> BTW, I'm not sure what the ready(count > 0) function does?  Can someone explain it?  It appears that it is the signal, but I'm not sure why the condition is required.

That call encapsulates some of the logic normally written by hand in mutex/condition blocks.  The "count > 0" is the boolean operation to be evaluated.  Personally, I think it's kind of an odd design.


Sean
October 02, 2007
David Brown wrote:
> 
> I've normally seen condition code where the wait decision is made as part
> of the wait, not as part of the signal.  It allows different waiters to
> have different conditions (although having multiple waiters is complicated,
> and requires access to pthread_cond_broadcast).
> 
>    synchronized void add(T item)
>    {
>      add_item_to_queue;
>      count++;
>      ready.signal;
>    }
> 
>    synchronized T remove()
>    {
>      while (count == 0)
>        ready.wait
>      count--;
>      return remove_item_from_queue;
>    }

This is the classic approach for using condition variables, and I think it's more straightforward than the other method suggested.

> When I get to needing threads, I'll definitely look into your condition
> code, and see if I can get it to work.  It shouldn't be too complicated, I
> just wasn't sure how to get access to the object's monitor.
> 
> Is it possible to make 'this' synchronized?

Yup.  In Tango, it's possible to set a Mutex instance as the monitor for another object.  Doing so currently requires some pointer magic, but it would be simple to encapsulate in a function.

Sean
October 02, 2007
"Sean Kelly" <sean@f4.ca> wrote
[snip]
> That call encapsulates some of the logic normally written by hand in mutex/condition blocks.  The "count > 0" is the boolean operation to be evaluated.  Personally, I think it's kind of an odd design.

Mesa vs Hoare ?


October 02, 2007
On Tue, Oct 02, 2007 at 09:18:14AM -0700, Kris wrote:
>"Sean Kelly" <sean@f4.ca> wrote
>[snip]
>> That call encapsulates some of the logic normally written by hand in mutex/condition blocks.  The "count > 0" is the boolean operation to be evaluated.  Personally, I think it's kind of an odd design.
>
>Mesa vs Hoare ? 

I guess so.  Usually, I've just seen that as the difference between needing 'if' vs 'while'.
Since I've never used a system with real Hoare semantics, I'm just not used
to determining the condition on the signalling side.  To me, it puts the
logic in the wrong place.

Dave
October 02, 2007
David Brown wrote:
>
> Since I've never used a system with real Hoare semantics, I'm just not used
> to determining the condition on the signalling side.  To me, it puts the
> logic in the wrong place.

Same here.


Sean
October 02, 2007
"Sean Kelly" <sean@f4.ca> wrote in message news:fdtqpn$259o$1@digitalmars.com...
> Steven Schveighoffer wrote:
>>
>> So the code above has to do something special by unlocking the object before waiting using an atomic operation.  I think this requires some language support.
>
> Doing this efficiently typically requires OS support.  The library must indicate to the OS that a context switch may not occur while certain portions of the code are executing.  It is possible to implement condvars without OS support as well, but the implementation tends to be fairly complicated.  Look for version(Win32) blocks in the Tango implementation for one such example.

Why can't you use SignalObjectAndWait?  Are you not using Win32 Mutexes in Win32?

I implemented a C++ OS abstraction library, and I had no problems implementing conditions on Win32 using OS support...

-Steve


October 02, 2007
Steven Schveighoffer wrote:
> "Sean Kelly" <sean@f4.ca> wrote in message news:fdtqpn$259o$1@digitalmars.com...
>> Steven Schveighoffer wrote:
>>> So the code above has to do something special by unlocking the object before waiting using an atomic operation.  I think this requires some language support.
>> Doing this efficiently typically requires OS support.  The library must indicate to the OS that a context switch may not occur while certain portions of the code are executing.  It is possible to implement condvars without OS support as well, but the implementation tends to be fairly complicated.  Look for version(Win32) blocks in the Tango implementation for one such example.
> 
> Why can't you use SignalObjectAndWait?  Are you not using Win32 Mutexes in Win32?

Nope.  Critical sections.  For what it's worth, the Tango condvar implementation is pretty similar to the one in Boost.

> I implemented a C++ OS abstraction library, and I had no problems implementing conditions on Win32 using OS support...

Frankly, I've never used SignalObjectAndWait.  I think the only place things may get a bit weird is in a notifyAll routine.  I guess you'd have to use a semaphore for the wait object and perhaps a separate counter to track the number of threads waiting on it?


Sean
October 02, 2007
Janice Caron wrote:
> On 10/2/07, David Brown <dlang@davidb.org> wrote:
> 
>> This feature is the very magic about condition variables that makes race
>> free synchronization possible where it isn't with events.
> 
> Now that part is not right. Race-free synchronization is /always/
> possible with events. (Note, however, that I say "possible", not
> "guaranteed".

How so?  Win32 events are widely regarded as broken on comp.programming.threads specifically because of race issues with them.  Personally, I think they're fine with only one consumer, but things get a bit odd with multiple consumers.


Sean
October 02, 2007
On 10/2/07, Sean Kelly <sean@f4.ca> wrote:
> Janice Caron wrote:
> > Now that part is not right. Race-free synchronization is /always/ possible with events. (Note, however, that I say "possible", not "guaranteed".
>
> How so?

class ThreadsafeQueue(T)
{
    Event e;

    this()
    {
        e = new Event;
    }

    sychronized void opCat(T x)
    {
        add_item_to_queue;
        e.signal;
    }

    T remove()
    {
        T x;
        for (;;)
        {
            e.wait;
            synchronized(this)
            {
                if (queue.length != 0)
                {
                    x = remove_item_from_queue;
                    e.signal;
                    return x;
                }
            }
        }
    }
}


> Win32 events are widely regarded as broken on comp.programming.threads

That's prejudice for you.
October 02, 2007
Janice Caron wrote:
> On 10/2/07, Sean Kelly <sean@f4.ca> wrote:
>> Janice Caron wrote:
>>> Now that part is not right. Race-free synchronization is /always/
>>> possible with events. (Note, however, that I say "possible", not
>>> "guaranteed".
>> How so?
> 
> class ThreadsafeQueue(T)
> {
>     Event e;
> 
>     this()
>     {
>         e = new Event;
>     }
> 
>     sychronized void opCat(T x)
>     {
>         add_item_to_queue;
>         e.signal;
>     }
> 
>     T remove()
>     {
>         T x;
>         for (;;)
>         {
>             e.wait;
>             synchronized(this)
>             {
>                 if (queue.length != 0)
>                 {
>                     x = remove_item_from_queue;
>                     e.signal;
>                     return x;
>                 }
>             }
>         }
>     }
> }

That pseudocode doesn't help much, I'm afraid.  Is this an auto or manual reset event?  Is PulseEvent or SetEvent being called by e.signal?

>> Win32 events are widely regarded as broken on
>> comp.programming.threads
> 
> That's prejudice for you.

I'm not sure that prejudice has a lot to do with it.  They complain about pthreads nearly as often, though for different reasons.


Sean