Reputation: 5074
I've got a logic inside a dynamic library that run some service that is requested by the main executable.
Upon calling start_service
from the library code, some preparation is required prior to service ready, and during this time, the main code should not try to access the service.
To notify the main code when the service is ready I use conditional variable and signal the main executable.
I'd like to hear some advices about the best way to handle a situation when the library become serviceable BEFORE the main code wait for the conditional variable. in this case, the waiting can last forever...
here's the service code :
extern pthread_cond_t cnd;
extern pthread_mutex_t mtx;
void start_service()
{
// getting serviceable.
pthread_cond_signal(&cnd);
main_loop();
}
And here's the main code.
pthread_cond_t cnd;
pthread_mutex_t mtx;
int main()
{
pthread_cond_init(&cnd,NULL);
pthread_mutex_init(&mtx, NULL);
std::thread mytrd(&start_service);
...
pthread_mutex_lock(&mtx);
pthread_cond_wait(&cnd, &mtx); // what happens if we get here after the signal already sent.
pthread_mutex_unlock(&mtx);
...
}
P.S the desired behavior should be that the main code avoid waiting for the conditional variable if it's already signaled.
Upvotes: 1
Views: 382
Reputation: 7542
You can use a semaphore with initial count of 0
, so main
gets blocked, until start_service()
increase semaphore count to 1
.If before the block call in main
, start_service()
increases the semaphore count to 1
, main will never enter into wait state.Something like below.
void start_service()
{
// getting serviceable.
sem_post(&sem_mutex);//increases to 1
main_loop();
}
int main()
{
sem_init(&sem_mutex, 0, 0);//initially blocked.
std::thread mytrd(&start_service);
sem_wait(&sem_mutex);
...
}
Upvotes: 2
Reputation: 122133
You need a predicate and enclose the wait
in a check for the predicate:
pthread_mutex_lock(&mtx);
while( ! predicate ) pthread_cond_wait(&cnd, &mtx);
pthread_mutex_unlock(&mtx);
In this way, the thread doesnt event start to wait when it doesnt need to.
The second reason you need this is to avoid spurious wakeups thay may occur, ie pthread_cond_wait
may return even if the other thread did not signal the condition.
The other thread then has to do (you need to lock the mutex to protect the predicate):
pthread_lock_mutex(&mtx);
predicate = true;
pthread_cond_signal(&cnd);
pthread_unlock_mutex(&mtx);
Upvotes: 2