Implement your own Semaphore using Mutex and cond variables

Let me know your comments on below code -

#include <iostream>
#include <pthread.h>
#include <unistd.h>
#include <condition_variable>

using namespace std;

#define THREAD_CNT 30

class semaphore {
private:
   int m_value;                    // Value of semaphore.
   pthread_mutex_t sync_mutex;               // Controls access.
   pthread_cond_t condition;; // Controls waiting and restart
public:
    semaphore(int init): m_value(init) {
       pthread_mutex_init(&sync_mutex, NULL);
       pthread_cond_init(&condition, NULL);
    }
    ~semaphore(){
       pthread_mutex_destroy(&sync_mutex);
       pthread_cond_destroy(&condition);
    }
    void down() {
        pthread_mutex_lock(&sync_mutex);
       // Check the mutex value, and wait if need be.
       if(--m_value < 0) {
           // Make us wait.  When we wait, the mutex is unlocked until the
           // wait ends.
           pthread_cond_wait(&condition, &sync_mutex);
       }
    }
    void up() {
       // Start a waiting thread if required.
       if(++m_value <= 0) {
           pthread_cond_signal(&condition);
       }
       pthread_mutex_unlock(&sync_mutex);
    }
};
semaphore sem(1);

int shared_resource = 0;
void *thread_handler(void *vargp)
{
	sem.down();

    shared_resource++;
    std::cout << "Job" << *(int *)vargp << " started, shared_resource=" << shared_resource << endl << std::flush;
    sleep(1);
    std::cout << "Job" << *(int *)vargp << " finished, shared_resource=" << shared_resource << endl << std::flush;

    sem.up();
    return NULL;
}

int main()
{
    pthread_t thread_id[THREAD_CNT];
    int thread_arg[THREAD_CNT];

    for(int i = 0; i < THREAD_CNT; i++) {
    	thread_arg[i] = i;
    	pthread_create(&thread_id[i], NULL, thread_handler, (void *)&thread_arg[i]);
    }

    for(int i = 0; i < THREAD_CNT; i++) {
        pthread_join(thread_id[i], NULL);
    }

    return 0;
}

Output

Job0 started, shared_resource=1
Job0 finished, shared_resource=1
Job1 started, shared_resource=2
Job1 finished, shared_resource=2
Job2 started, shared_resource=3
Job2 finished, shared_resource=3
Job3 started, shared_resource=4
Job3 finished, shared_resource=4
Job4 started, shared_resource=5
Job4 finished, shared_resource=5
Job5 started, shared_resource=6
Job5 finished, shared_resource=6
Job6 started, shared_resource=7
Job6 finished, shared_resource=7
Job7 started, shared_resource=8
Job7 finished, shared_resource=8
Job8 started, shared_resource=9
Job8 finished, shared_resource=9
Job9 started, shared_resource=10
Job9 finished, shared_resource=10
Job10 started, shared_resource=11
Job10 finished, shared_resource=11
Job11 started, shared_resource=12
Job11 finished, shared_resource=12
Job12 started, shared_resource=13
Job12 finished, shared_resource=13
Job13 started, shared_resource=14
Job13 finished, shared_resource=14
Job14 started, shared_resource=15
Job14 finished, shared_resource=15
Job15 started, shared_resource=16
Job15 finished, shared_resource=16
Job16 started, shared_resource=17
Job16 finished, shared_resource=17
Job17 started, shared_resource=18
Job17 finished, shared_resource=18
Job18 started, shared_resource=19
Job18 finished, shared_resource=19
Job19 started, shared_resource=20
Job19 finished, shared_resource=20
Job20 started, shared_resource=21
Job20 finished, shared_resource=21
Job21 started, shared_resource=22
Job21 finished, shared_resource=22
Job22 started, shared_resource=23
Job22 finished, shared_resource=23
Job23 started, shared_resource=24
Job23 finished, shared_resource=24
Job24 started, shared_resource=25
Job24 finished, shared_resource=25
Job25 started, shared_resource=26
Job25 finished, shared_resource=26
Job26 started, shared_resource=27
Job26 finished, shared_resource=27
Job27 started, shared_resource=28
Job27 finished, shared_resource=28
Job28 started, shared_resource=29
Job28 finished, shared_resource=29
Job29 started, shared_resource=30
Job29 finished, shared_resource=30

Comments (3)