web-dev-qa-db-ja.com

Linuxでは、WaitForSingleObjectとWaitForMultipleObjectsは同等ですか?

アプリをWindowsからLinuxに移行しています。 WaitForSingleObjectおよびWaitForMultipleObjectsインターフェイスに関して問題に直面しています。

私のアプリケーションでは、すべてのスレッドが親プロセスからのイベントを待つ、またはt秒ごとに定期的に実行される複数のスレッドを生成します。

確認しました pthread_cond_timedwait、ただし、これには絶対時間を指定する必要があります。

これをUnixに実装するにはどうすればよいですか?

28
Poorna

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

必要に応じて、関数で囲みます。


更新:私たちのコメントに基づいて答えを補足します。

POSIXには、Windowsのように「すべてのタイプ」のイベント/オブジェクトを待機する単一のAPIがありません。それぞれに独自の機能があります。スレッドに終了を通知する最も簡単な方法は、アトミック変数/操作を使用することです。例えば:

メインスレッド:

// 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

もう1つの方法は、pthread_cancelを使用してキャンセルリクエストを送信することです。キャンセルされるスレッドは、必要なクリーンアップハンドラーを登録するためにpthread_cleanup_Pushを呼び出している必要があります。これらのハンドラーは、登録されたときとは逆の順序で呼び出されます。 pthread_exitは、未定義の動作であるため、クリーンアップハンドラーから呼び出さないでください。キャンセルされたスレッドの終了ステータスはPTHREAD_CANCELEDです。この代替手段を選択する場合は、主にキャンセルポイントとキャンセルタイプについて読むことをお勧めします。

最後に重要なことですが、pthread_joinを呼び出すと、引数で渡されたスレッドが終了するまで現在のスレッドがブロックされます。おまけとして、スレッドの終了ステータスを取得します。

12
jweyrich

それだけの価値があるので、私たち(NeoSmart Technologies)は pevents というオープンソース(MITライセンス)ライブラリをリリースしました POSIXでWIN32手動イベントと自動リセットイベント を実装し、WaitForSingleObjectとWaitForMultipleObjectsの両方のクローンを含みます。

POSIXマシンでコーディングするときは、POSIXマルチスレッドとシグナリングパラダイムを使用することをお勧めしますが、peventsは、必要に応じて別の選択肢を提供します。

12

私はこれが古い質問であることに気づきましたが、それに遭遇した他の誰にとっても、このソースはpthread_join()が実質的にWaitForSingleObject()と同じことをすることを示唆しています:

http://www.ibm.com/developerworks/linux/library/l-ipc2lin1/index.html

幸運を!

1
eskimo9

WaitForMultipleObjectsがfalseの場合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;
}
1
Sorcerer