3

I want to create a queue to store my tasks, I want it to be a buffer queue, and I want to use a semophore to keep it thread-safe, cause I use several threads to execute the tasks popped out from the task queue.. when the size of the queue is less than buffer_size(a variable defined by me), the add_task thread will push new tasks to the task queue, and when it is full, the task thread will be blocked, so I need a semophore whose max value equals buffer_size.

I know in windows api, there is CreateSemophore, in which I can set the max value of the semophore:

CreateSemaphore( 
        NULL,           // default security attributes
        MAX_SEM_COUNT,  // initial count
        MAX_SEM_COUNT,  // maximum count
        NULL);          // unnamed semaphore

but in linux, I can only get the sem_init function:

int sem_init (sem_t *sem, int pshared, unsigned int value)

which I can only set the initial value, but the max value is said to be the range of int..

so my question is how to create a semophore with a max value in C++ on Linux?

hivert
  • 10,579
  • 3
  • 31
  • 56
Roger Liu
  • 1,768
  • 3
  • 16
  • 25

1 Answers1

5

Design around this aparrent limitation - use two semaphores, (and a mutex). This is a 'classic' pattern for a bounded producer-consumer queue.

Initialize one, 'spaceRemaining', to buffer_size - the producer/s wait on it before acquiring the mutex and pushing the data, the consumers signal it after popping the data and releasing the mutex.

Initialize the other, 'entryCount', to zero - the producer/s signal it after pushing the data and releasing the mutex, the consumers wait on it before acquring the mutex and popping the data.

This way, there is no need to place any limit on the semaphore count, pseudocode:

Sema spaceRemaining(buffer_size);
Sema entryCount(0);
..
..
void *Producer(Data data){
  spaceRemaining.wait();
  mutex.acquire();
  queue.push(data);
  mutex.release();
  entryCount.signal();
};

Data Consumer(){
  entryCount.wait();
  mutex.acquire();
  Data localData=queue.pop();
  mutex.release(); 
  spaceRemaining.signal();
  return localData;
};
Martin James
  • 24,453
  • 3
  • 36
  • 60