阻止直到事件完成

时间:2010-03-31 08:48:55

标签: c

gcc 4.4.2 c89

我有一个必须运行的函数(config_relays)。它调用一个名为set_relay的API函数,然后代码必须等待,直到set_relay事件的事件完成为止。 set_relay是任何异步调用。

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();
}

我想我可以把init_relay()放在交换机中。但是,该事件用于其他事情,而不仅仅用于初始化中继。我真的想处理config_relays函数中的所有内容。

在C#中,您可以使用autoreset来完成此操作。 C有这样的东西。

非常感谢任何建议,

3 个答案:

答案 0 :(得分:2)

正如安德斯所写,条件等待是解决方案。在POSIX Thread API中,您将pthread_cond_wait与互斥锁一起使用。这很容易,以下模式有效:

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);

}

pthread_cond_signal和pthread_cond_broadcast之间的区别在于,如果多个线程等待设置该标志,则pthread_cond_signal仅释放一个线程,但广播会释放所有线程。

并非围绕您的条件创建的while循环取决于您,您可以测试多个条件或执行您想要的任何操作。代码模式确保您的测试在受保护的变量上执行,以便竞争条件永远不会导致问题,例如

while(resource_a_busy && resource_b_busy) ...

这是两个资源状态都必须受互斥锁保护的典型问题。

cond_wait可以从循环中删除,但是它会将wait_ready转换为消耗CPU的轮询循环,pthread_wait_cond不会占用任何CPU。

有一些移植库在pthreads之上提供类似于Win32的API,以及在Win32事件API之上提供类似API的phread的库,后者称为Pthreads-w32

答案 1 :(得分:1)

这取决于您使用的线程库以及如何调用异步方法。如果您使用的是Windows,则可以使用Windows API中的自动重置事件。请参阅CreateEvent API。如果你在unix / linux上,你可以在pthreads中查看条件变量。不幸的是,pthreads没有自动重置事件,因为它们很难以无竞争条件的方式使用。

在选择等待策略时,您还必须考虑异步调用的完成方式。它在另一个线程上吗?它是通过信号处理完成的吗?其他一些“借用”主线程的异步机制?如果通过“借用”主线程完成调用,则必须确保等待策略不会阻止线程用于执行异步调用。

答案 2 :(得分:1)

1)您可以使用特定于OS的API(如createEvent或pthread条件变量)等待,并在set_relay()完成时发出信号。

2)轮询方法。定期轮询以查看set_relay()已完成,否则请休眠几秒钟并重试。