WaitForSingleObject и WaitForMultipleObjects эквивалент в Linux
Я переношу приложение из окон в linux. Я столкнулся с проблемой относительно интерфейсов WaitForSingleObject
и WaitForMultipleObjects
.
В моем приложении я создаю несколько потоков, где все потоки ожидают события от родительского процесса или периодически запускаются в течение каждых t секунд.
Я проверил pthread_cond_timedwait
, но для этого нужно указать абсолютное время.
Как я могу реализовать это в Unix?
Ответы
Ответ 1
Придерживайтесь pthread_cond_timedwait
и используйте clock_gettime
. Например:
struct timespec ts;
clock_gettime(CLOCK_REALTIME, &ts);
ts.tv_sec += 10; // ten seconds
while (!some_condition && ret == 0)
ret = pthread_cond_timedwait(&cond, &mutex, &ts);
Оберните его в функцию, если хотите.
UPDATE: дополнение ответа на основе наших комментариев.
POSIX не имеет единого API для ожидания "всех типов" событий/объектов, как это делает Windows. Каждый из них имеет свои собственные функции. Самый простой способ оповестить поток о завершении - использовать атомные переменные/операции. Например:
Основная тема:
// Declare it globally (argh!) or pass by argument when the thread is created
atomic_t must_terminate = ATOMIC_INIT(0);
// "Signal" termination by changing the initial value
atomic_inc(&must_terminate);
Вторичная тема:
// While it holds the default value
while (atomic_read(&must_terminate) == 0) {
// Keep it running...
}
// Do proper cleanup, if needed
// Call pthread_exit() providing the exit status
Другой вариант - отправить запрос отмены с помощью pthread_cancel
. Отменившаяся нить должна иметь имя pthread_cleanup_push
для регистрации любого необходимого обработчика очистки. Эти обработчики вызываются в порядке, в котором они были зарегистрированы. Никогда не вызывайте pthread_exit
из обработчика очистки, потому что это поведение undefined. Статус выхода отмененного потока PTHREAD_CANCELED
. Если вы выберете эту альтернативу, я рекомендую вам читать в основном о точках и типах отмены.
И последнее, но не менее важное: вызов pthread_join
сделает текущий блок потока до тех пор, пока поток, переданный аргументом, не завершится. В качестве бонуса вы получите статус завершения потока.
Ответ 2
Для чего мы стоим, мы (NeoSmart Technologies) только что выпустили библиотеку с открытым исходным кодом (MIT), называемую pevents, которая реализует события WIN32 вручную и автоматически reset на POSIX и включает в себя как клоны WaitForSingleObject, так и WaitForMultipleObjects.
Хотя я бы посоветовал вам использовать POSIX многопоточность и сигнальные парадигмы при кодировании на машинах POSIX, pevents дает вам другой выбор, если вам это нужно.
Ответ 3
Я понимаю, что это старый вопрос сейчас, но для любого другого, кто наткнулся на него, этот источник предполагает, что pthread_join() делает то же самое, что и WaitForSingleObject():
http://www.ibm.com/developerworks/linux/library/l-ipc2lin1/index.html
Удачи!
Ответ 4
Для WaitForMultipleObjects
с ложным WaitAll
попробуйте следующее:
#include <unistd.h>
#include <pthread.h>
#include <stdio.h>
using namespace std;
pthread_cond_t condition;
pthread_mutex_t signalMutex;
pthread_mutex_t eventMutex;
int finishedTask = -1;
void* task(void *data)
{
int num = *(int*)data;
// Do some
sleep(9-num);
// Task finished
pthread_mutex_lock(&eventMutex); // lock until the event will be processed by main thread
pthread_mutex_lock(&signalMutex); // lock condition mutex
finishedTask = num; // memorize task number
pthread_cond_signal(&condition);
pthread_mutex_unlock(&signalMutex); // unlock condtion mutex
}
int main(int argc, char *argv[])
{
pthread_t thread[10];
pthread_cond_init(&condition, NULL);
pthread_mutex_init(&signalMutex, NULL); // First mutex locks signal
pthread_mutex_init(&eventMutex, NULL); // Second mutex locks event processing
int numbers[10];
for (int i = 0; i < 10; i++) {
numbers[i] = i;
printf("created %d\n", i); // Creating 10 asynchronous tasks
pthread_create(&thread[i], NULL, task, &numbers[i]);
}
for (int i = 0; i < 10;)
{
if (finishedTask >= 0) {
printf("Task %d finished\n", finishedTask); // handle event
finishedTask = -1; // reset event variable
i++;
pthread_mutex_unlock(&eventMutex); // unlock event mutex after handling
} else {
pthread_cond_wait(&condition, &signalMutex); // waiting for event
}
}
return 0;
}