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

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


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

#include <mutex>#include <condition_variable>class semaphore {    std::mutex mutex_;    std::condition_variable condition_;    unsigned long count_ = 0; // Initialized as locked.public:    void release() {        std::lock_guard<decltype(mutex_)> lock(mutex_);        ++count_;        condition_.notify_one();    }    void acquire() {        std::unique_lock<decltype(mutex_)> lock(mutex_);        while(!count_) // Handle spurious wake-ups.            condition_.wait(lock);        --count_;    }    bool try_acquire() {        std::lock_guard<decltype(mutex_)> lock(mutex_);        if(count_) {            --count_;            return true;        }        return false;    }};


Based on Maxim Yegorushkin's answer, I tried to make the example in C++11 style.

#include <mutex>#include <condition_variable>class Semaphore {public:    Semaphore (int count_ = 0)        : count(count_) {}    inline void notify()    {        std::unique_lock<std::mutex> lock(mtx);        count++;        cv.notify_one();    }    inline void wait()    {        std::unique_lock<std::mutex> lock(mtx);        while(count == 0){            cv.wait(lock);        }        count--;    }private:    std::mutex mtx;    std::condition_variable cv;    int count;};


I decided to write the most robust/generic C++11 semaphore I could, in the style of the standard as much as I could (note using semaphore = ..., you normally would just use the name semaphore similar to normally using string not basic_string):

template <typename Mutex, typename CondVar>class basic_semaphore {public:    using native_handle_type = typename CondVar::native_handle_type;    explicit basic_semaphore(size_t count = 0);    basic_semaphore(const basic_semaphore&) = delete;    basic_semaphore(basic_semaphore&&) = delete;    basic_semaphore& operator=(const basic_semaphore&) = delete;    basic_semaphore& operator=(basic_semaphore&&) = delete;    void notify();    void wait();    bool try_wait();    template<class Rep, class Period>    bool wait_for(const std::chrono::duration<Rep, Period>& d);    template<class Clock, class Duration>    bool wait_until(const std::chrono::time_point<Clock, Duration>& t);    native_handle_type native_handle();private:    Mutex   mMutex;    CondVar mCv;    size_t  mCount;};using semaphore = basic_semaphore<std::mutex, std::condition_variable>;template <typename Mutex, typename CondVar>basic_semaphore<Mutex, CondVar>::basic_semaphore(size_t count)    : mCount{count}{}template <typename Mutex, typename CondVar>void basic_semaphore<Mutex, CondVar>::notify() {    std::lock_guard<Mutex> lock{mMutex};    ++mCount;    mCv.notify_one();}template <typename Mutex, typename CondVar>void basic_semaphore<Mutex, CondVar>::wait() {    std::unique_lock<Mutex> lock{mMutex};    mCv.wait(lock, [&]{ return mCount > 0; });    --mCount;}template <typename Mutex, typename CondVar>bool basic_semaphore<Mutex, CondVar>::try_wait() {    std::lock_guard<Mutex> lock{mMutex};    if (mCount > 0) {        --mCount;        return true;    }    return false;}template <typename Mutex, typename CondVar>template<class Rep, class Period>bool basic_semaphore<Mutex, CondVar>::wait_for(const std::chrono::duration<Rep, Period>& d) {    std::unique_lock<Mutex> lock{mMutex};    auto finished = mCv.wait_for(lock, d, [&]{ return mCount > 0; });    if (finished)        --mCount;    return finished;}template <typename Mutex, typename CondVar>template<class Clock, class Duration>bool basic_semaphore<Mutex, CondVar>::wait_until(const std::chrono::time_point<Clock, Duration>& t) {    std::unique_lock<Mutex> lock{mMutex};    auto finished = mCv.wait_until(lock, t, [&]{ return mCount > 0; });    if (finished)        --mCount;    return finished;}template <typename Mutex, typename CondVar>typename basic_semaphore<Mutex, CondVar>::native_handle_type basic_semaphore<Mutex, CondVar>::native_handle() {    return mCv.native_handle();}