tauran tauran - 6 days ago 6
C++ Question

C++0x has no semaphores? How to synchronize threads?

Is it true that C++0x will come without semaphores? There are already some questions on Stack Overflow regarding the use of semaphores. I use them (posix semaphores) all the time to let a thread wait for some event in another thread:

void thread0(...)
{
doSomething0();

event1.wait();

...
}

void thread1(...)
{
doSomething1();

event1.post();

...
}


If I would do that with a mutex:

void thread0(...)
{
doSomething0();

event1.lock(); event1.unlock();

...
}

void thread1(...)
{
event1.lock();

doSomethingth1();

event1.unlock();

...
}


Problem: It's ugly and it's not guaranteed that thread1 locks the mutex first (Given that the same thread should lock and unlock a mutex, you also can't lock event1 before thread0 and thread1 started).

So since boost doesn't have semaphores either, what is the simplest way to achieve the above?

Answer

You can easily build one from a mutex and a condition variable:

#include <boost/thread/condition.hpp>
#include <boost/thread/mutex.hpp>

class semaphore
{
private:
    boost::mutex mutex_;
    boost::condition_variable condition_;
    unsigned long count_;

public:
    semaphore()
        : count_()
    {}

    void notify()
    {
        boost::mutex::scoped_lock lock(mutex_);
        ++count_;
        condition_.notify_one();
    }

    void wait()
    {
        boost::mutex::scoped_lock lock(mutex_);
        while(!count_)
            condition_.wait(lock);
        --count_;
    }
};

C++11 version:

#include <condition_variable>
#include <mutex>

class semaphore
{
private:
    std::mutex mutex_;
    std::condition_variable condition_;
    unsigned long count_;

public:
    semaphore()
        : count_()
    {}

    void notify()
    {
        std::unique_lock<decltype(mutex_)> lock(mutex_);
        ++count_;
        condition_.notify_one();
    }

    void wait()
    {
        std::unique_lock<decltype(mutex_)> lock(mutex_);
        while(!count_)
            condition_.wait(lock);
        --count_;
    }
};