In the man page it appears that even if you initialise a semaphore to a value of one:
sem_init(&mySem, 0, 1);
It 开发者_运维问答could still be incremented to a value greater than 1 with multiple calls to
sem_post(&mySem);
But in this code example the comment seems to think differently:
sem_init(&mutex, 0, 1); /* initialize mutex to 1 - binary semaphore */
Is it possible to initialise a strictly binary semaphore in C?
Note: The reason for doing this instead of using a mutex in this case is the sem_post and sem_wait may be called by different threads.
If you want a strictly binary semaphore on Linux, I suggest building one out of mutexes and condition variables.
struct binary_semaphore {
pthread_mutex_t mutex;
pthread_cond_t cvar;
bool v;
};
void mysem_post(struct binary_semaphore *p)
{
pthread_mutex_lock(&p->mutex);
if (p->v)
abort(); // error
p->v = true;
pthread_cond_signal(&p->cvar);
pthread_mutex_unlock(&p->mutex);
}
void mysem_wait(struct binary_semaphore *p)
{
pthread_mutex_lock(&p->mutex);
while (!p->v)
pthread_cond_wait(&p->cvar, &p->mutex);
p->v = false;
pthread_mutex_unlock(&p->mutex);
}
you can create a wrapper function for sem_post that will check the semaphore value before sem_post().
example:
int semaphore_give(sem_t *sem)
{
int value, ret;
if (!sem)
return -1;
if (sem_getvalue(sem, &value))
return -1;
if (value == 0)
return sem_post(sem);
return -1;
}
I don't like the implementation of semaphores in Linux but have to use it.
To make it simple I decrement sem value till zero with sem_trywait
if it is returned one on the first check:
if (sem_trywait(pProcess->sem_id) < 0 && errno != EINTR ) {
return ERROR;
}
else {
while (sem_trywait(pProcess->sem_id) == 0);
return OK;
}
Be careful if sem_post
is called too often. You can stuck in the while()
clause. In my case it's called no more than once per second.
精彩评论