私の C++ プログラムでは、lio_listio
呼び出しを使用して、一度に多数 (最大数百) の書き込み要求を送信します。その後、いくつかの計算を行います。完了したら、次のバッチのリクエストを送信する前に、すべての未処理のリクエストが終了するのを待つ必要があります。これどうやってするの?
今、私は呼び出しaio_suspend
ごとに 1 つの要求をループで呼び出しているだけですが、これは醜いようです。struct sigevent *sevp
への引数を使用する必要があるようlio_listio
です。私の現在の推測では、次のようにする必要があります。
- メイン スレッドで、mutex を作成し、 への呼び出しの直前にロックし
lio_listio
ます。 - への呼び出しで
lio_listio
、このミューテックスをロック解除する通知関数/シグナル ハンドラを指定します。
これで目的の動作が得られるはずですが、確実に機能しますか? シグナルハンドラコンテキストからミューテックスを操作することは許可されていますか? 同じスレッドから再度ロックしようとしたり、別のスレッドからロックを解除しようとすると、pthread ミューテックスがエラー検出を提供して失敗する可能性があることを読みましたが、この解決策はデッドロックに依存しています。
シグナルハンドラを使用したコード例:
void notify(int, siginfo_t *info, void *) {
pthread_mutex_unlock((pthread_mutex_t *) info->si_value);
}
void output() {
pthread_mutex_t iomutex = PTHREAD_MUTEX_INITIALIZER;
struct sigaction act;
memset(&act, 0, sizeof(struct sigaction));
act.sa_sigaction = ¬ify;
act.sa_flags = SA_SIGINFO;
sigaction(SIGUSR1, &act, NULL);
for (...) {
pthread_mutex_lock(&iomutex);
// do some calculations here...
struct aiocb *cblist[];
int cbno;
// set up the aio request list - omitted
struct sigevent sev;
memset(&sev, 0, sizeof(struct sigevent));
sev.sigev_notify = SIGEV_SIGNAL;
sev.sigev_signo = SIGUSR1;
sev.sigev_value.sival_ptr = &iomutex;
lio_listio(LIO_NOWAIT, cblist, cbno, &sev);
}
// ensure that the last queued operation completes
// before this function returns
pthread_mutex_lock(&iomutex);
pthread_mutex_unlock(&iomutex);
}
通知関数を使用したコード例 - 余分なスレッドが作成されるため、効率が低下する可能性があります。
void output() {
pthread_mutex_t iomutex = PTHREAD_MUTEX_INITIALIZER;
for (...) {
pthread_mutex_lock(&iomutex);
// do some calculations here...
struct aiocb *cblist[];
int cbno;
// set up the aio request list - omitted
struct sigevent sev;
memset(&sev, 0, sizeof(struct sigevent));
sev.sigev_notify = SIGEV_THREAD;
sev_sigev_notify_function = &pthread_mutex_unlock;
sev.sigev_value.sival_ptr = &iomutex;
lio_listio(LIO_NOWAIT, cblist, cbno, &sev);
}
// ensure that the last queued operation completes
// before this function returns
pthread_mutex_lock(&iomutex);
pthread_mutex_unlock(&iomutex);
}