lio_listio:如何等待所有请求完成?

时间:2013-02-08 16:41:40

标签: linux posix aio

在我的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 = &notify;
    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);
}

0 个答案:

没有答案