Блокировать до завершения события - PullRequest
0 голосов
/ 31 марта 2010

gcc 4.4.2 c89

У меня есть функция, которая должна работать (config_relays). Он вызывает функцию API с именем set_relay, затем код должен ждать, прежде чем продолжить, пока не завершится событие для события 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 # вы можете сделать это с помощью автоматического сброса. Есть ли у C что-нибудь подобное.

Большое спасибо за любой совет,

Ответы [ 3 ]

2 голосов
/ 31 марта 2010

Как писал Андерс, условное ожидание - это решение. В 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 в цикл опроса, который потребляет процессор, pthread_wait_cond не потребляет никакой процессор.

Существуют библиотеки портирования, которые предоставляют Win32-подобный API поверх pthreads, а также библиотеки, которые предоставляют phread-подобный API поверх Win32 API событий, последний называется Pthreads-w32

1 голос
/ 31 марта 2010

1) Вы можете использовать специфичные для ОС API, такие как условная переменная createEvent или pthread, чтобы ждать и сигнализировать об этом после завершения set_relay ().

2) Подход к опросу. Периодически опрашивайте, чтобы увидеть, что set_relay () завершена, иначе поспите несколько секунд и повторите попытку.

1 голос
/ 31 марта 2010

Это зависит от того, какую библиотеку потоков вы используете и как вызывается асинхронный метод. Если вы работаете в Windows, в Windows API есть события автоматического сброса, которые вы можете использовать. См. CreateEvent API. Если вы используете unix / linux, вы можете посмотреть переменные условия в pthreads. К сожалению, pthreads не имеет событий автоматического сброса, потому что их очень сложно использовать без условий гонки.

При выборе стратегии ожидания вы также должны принять во внимание, как выполняется асинхронный вызов. Это в другой теме? Это делается с помощью обработки сигналов? Какой-то другой асинхронный механизм, который «заимствует» основной поток? Если вызов выполняется путем «заимствования» основного потока, вы должны убедиться, что ваша стратегия ожидания не препятствует использованию потока для выполнения асинхронного вызова.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...