在我的C ++程序中,我使用lio_listio
调用一次发送多个(最多几百个)写请求。之后,我做了一些计算,当我完成后,我需要等待所有未完成的请求完成,然后才能提交下一批请求。我怎么能这样做?
现在,我只是在循环中调用aio_suspend
,每次调用一个请求,但这看起来很难看。看起来我应该使用struct sigevent *sevp
参数lio_listio
。我目前的猜测是我应该这样做:
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);
}