What sync object should i use?

Sean Kelly sean at invisibleduck.org
Tue May 14 11:30:11 PDT 2013


On May 14, 2013, at 9:09 AM, Heinz <thor587 at gmail.com> wrote:

> On Monday, 13 May 2013 at 21:04:23 UTC, Juan Manuel Cabo wrote:
> 
>> There is one thing that should definitely added to the documentation, and that is what happens when one issues a notify while the thread hasn't yet called Condition.wait().
> 
> I can confirm that under Win32 calling notify() before wait()
> internally signals the condition and then calling wait() returns
> immediately and actually does not wait. This is the expected
> behavior and is actually how Win32 events work.

A Win32 event can be simulated basically like so:

class Event {
    Condition c;
    bool signaled = false;

    this() {
        c = new Condition(new Mutex);
    }

    void wait() {
        synchronized (c.mutex) {
            while (!signaled)
                c.wait();
            signaled = false;
        }
    }

    void notify() {
        synchronized (c.mutex) {
            signaled = true;
            c.notify();
        }
    }
}

auto e = new Event;

T get() {
    while (true) {
        e.wait();
        // A -- race here
        synchronized (m) {
            if (!m.isEmpty())
                return m.take();
        }
    }
}

void put(T val) {
    synchronized(m) {
        m.add(val);
    }
    e.notify();
}

You'll notice the redundancy here though to combat the race at point A.  Generally, you really want to avoid the Win32 model and use the mutex/condition pair directly with your container or whatever.


> On Tuesday, 14 May 2013 at 08:58:31 UTC, Dmitry Olshansky wrote:
> 
>> Have to lock it otherwise you have a race condition on a condition variable (wow!).
> 
> Ok, i'll lock it just in case. It also makes me feel my code is
> more robust. This will do right?
> 
> ...
> synchronized(cond.mutex)
>     cond.notify();
>
Yep.


> My internal bool variable that affects the condition (the one
> that decides if the consumer thread should wait) must be setable
> at any moment by any thread so i leave it outside the lock. Also,
> after setting this variable i immediately call notify() with
> mutex unlocked. That's why it is working i think.

I don't understand what you mean here.  If the variable is protected by a lock it can still be set by any thread at any time.  Just only one thread at a time.  Doing a lock-free write of the variable basically just means that the variable will probably be set eventually, which is rarely what you actually want.


More information about the Digitalmars-d-learn mailing list