How to avoid waiting for pthread_cond_t where signal has already been sent

I have logic inside a dynamic library that starts some service requested by the main executable.

When called start_service

from library code, pre-preparation is required before the service is 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 a condition variable and signal the main executable.

I would like to hear some advice on how best to deal with the situation where the library becomes operational BEFORE the main code expecting a conditional variable. in this case, the wait 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);
    ...
}

      

PS The desired behavior should be that the main code avoids waiting for a condition variable if it is already signaled.

+3


source to share


2 answers


You need a predicate and enclose wait

in a check for the predicate:

    pthread_mutex_lock(&mtx);
    while( ! predicate ) pthread_cond_wait(&cnd, &mtx);  
    pthread_mutex_unlock(&mtx);

      

This way, the thread doesn't fire the event when it doesn't need it. The second reason you need this is to avoid the collateral awakenings that can happen, i.e. pthread_cond_wait

may return even if the other thread has not signaled the status.



Then another thread must execute (you need to lock the mutexes to protect the predicate):

 pthread_lock_mutex(&mtx);
 predicate = true;  
 pthread_cond_signal(&cnd);
 pthread_unlock_mutex(&mtx);

      

+2


source


You can use a semaphore with an initial count 0

, so it main

blocks until the start_service()

semaphore increases to 1

. If, before calling the block in main

, start_service()

increments the semaphore to 1

, main will never enter the 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);
    ...
}

      

+2


source







All Articles