MistyD
MistyD

Reputation: 17253

How to use the following Semaphore code

I am reading about Semaphores. From what I understand is that a Semaphore allows only a certain number of threads to access a specific resource. I came across this post which explains how to create a simple semaphore class using condition variables and a mutex. The code for ease of access is pasted here from that link

#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;
};

My question is how would I use the above class to make this method accessible to only 3 threads at a time

void SomeFunction
{
  ------------------------------> Only 3 threads should be allowed access to this function concurrently
  int a = getSomeValue();
  //Do something useful
  ------------------------------>
}

I am thinking that I would do something like this

   Semaphore s(3);
   void SomeFunction
    {
        s.wait();
        int a = getSomeValue();
       //Do sometning useful
        s.notify();
    }

However I am not sure when wait() and notify() would be called ?

Upvotes: 1

Views: 724

Answers (1)

Serge Rogatch
Serge Rogatch

Reputation: 15100

It would be better to use RAII idiom for a semaphore:

class SemaphoreLock
{
public:
    SemaphoreLock(Semaphore& s)
        : _pS(&s)
    {
        _pS->wait();
    }
    ~SemaphoreLock()
    {
        _pS->notify();
    }
private:
    Semaphore* _pS;
};

Semaphore s(3);
void SomeFunction()
{
    SemaphoreLock sl(s);
    // implement the function here
}

If SemaphoreLock object is declared in the very beginning of the body of the function, then wait() would be called upon entering the function and notify() would be called just before exiting the function, also in the case if an exception is thrown and stack unwinding is not terminated.

An even better solution could be in renaming the methods of Semaphore: wait into lock and notify into unlock. In this case one would be able to use std::lock_guard<Semaphore> in place of self-written SemaphoreLock class.

Upvotes: 2

Related Questions