Reputation: 22576
gcc 4.4.2 c89
I have a function that has to run (config_relays). It make a call to a API function called set_relay, then the code has to wait before continuing until the event for set_relay event has completed. The set_relay is any Async call.
i.e.
void run_processes()
{
switch()
{
case EV_RELAY_SET:
break;
}
}
void config_relays()
{
set_relay();
/* Wait until EV_RELAY_SET has fired */
/* Cannot do init_relay until set_relay event has fired - has to block here */
init_relay();
}
I guess I could put the init_relay() in the switch. However, that event is used for other things and not just for initializing the relay. I would really like to handle everything in the config_relays function.
In C# you can do this by using autoreset. Does C have anything like that.
Many thanks for any advice,
Upvotes: 0
Views: 6489
Reputation: 4040
As Anders wrote, conditional wait is the solution. In the POSIX Thread API you use pthread_cond_wait together with a mutex. It is quite easy, the following pattern works:
int ready_flag = 0;
pthread_mutex_t ready_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t ready_cond = PTHREAD_COND_INITIALIZER;
void wait_ready()
{
pthread_mutex_lock(&ready_mutex);
while(!ready_flag) {
pthread_cond_wait(&ready_cond, &ready_mutex);
}
pthread_mutex_unlock(&ready_mutex);
}
void set_ready(int ready)
{
pthread_mutex_lock(&ready_mutex);
ready_flag = ready;
pthread_cond_signal(&ready_cond);
// or using pthread_cond_broadcast(&ready_cond);
pthread_mutex_unlock(&ready_mutex);
}
The difference between pthread_cond_signal and pthread_cond_broadcast is that if more than one thread waits for the flag to be set, pthread_cond_signal only releases one thread but broadcast releases all threads.
Not that the while loop created around your condition is up to you, you can test multiple conditions or do whatever you want. The code pattern ensures that your tests are performed on protected variables so that race conditions can never cause problems for example
while(resource_a_busy && resource_b_busy) ...
Is a typical problem where both resource states must be protected by a mutex.
The cond_wait can be removed from the loop, but then it would translate the wait_ready to a polling loop which consumes CPU, the pthread_wait_cond does not consume any CPU.
There are porting libraries that provides a Win32 like API on top of pthreads as well as libraries that gives a phread like API on top of Win32 event API, the later is called [Pthreads-w32] 1
Upvotes: 2
Reputation: 69280
It depends on what threading library you are using and how the asynchronous method is called. If you are on Windows, there are auto-reset events in the Windows API that you can use. See the CreateEvent
API. If you are on unix/linux you can look into condition variables in pthreads. Unfortunately pthreads doesn't have auto-reset events, because they are very hard to use in a race-condition-free way.
When choosing your waiting strategy you also have to take into consideration how the asynchronous call is done. Is it on another thread? Is it done through signal handling? Some other asynch mechanism which "borrows" the main thread? If the call is done by "borrowing" the main thread, you have to make sure that your waiting strategy does not stop the thread from being used to perform the asynch call.
Upvotes: 1
Reputation: 2806
1) You can use OS specific API's like createEvent or pthread condition variable to wait on and signal it when set_relay() is completed.
2) Polling approach. Poll periodically to see set_relay() is completed, else sleep for few seconds and retry.
Upvotes: 1