Zohar81
Zohar81

Reputation: 5074

How to avoid waiting for pthread_cond_t where signal already sent

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

Answers (2)

Gaurav Sehgal
Gaurav Sehgal

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

463035818_is_not_an_ai
463035818_is_not_an_ai

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

Related Questions