是否存在可移植的pthread_sleep函数?

问题描述

我正在编写将同时在Linux和Windows上构建的ANSI C应用程序。

我为Windows构建了pthread 2.9.1库,并且一切正常。

问题是我找不到函数:pthread_sleep()

我也四处寻找该功能,但似乎不存在。

没有该功能,我的代码将不得不在Windows上调用Sleep()并在Linux上调用sleep(),但这正是我所不想要的。

谢谢, 恩里科·米格里尔(Enrico Migliore)

解决方法

问题是我找不到函数:pthread_sleep()

不,您不会,因为pthreads不提供此类功能。为什么呢? pthreads API没有使线程休眠专用,并且真正的POSIX平台都具有多种其他机制,包括sleep(),可以使线程休眠。无论如何,要使多线程程序的线程处于休眠状态(与 block 相对)并不是一件好事或合理的事情。

没有该功能,我的代码将不得不在Windows上调用Sleep()并在Linux上调用sleep(),但这正是我所不想要的。

我倾向于认为您也不想调用与平台无关的替代方法。但是,使用各种特定于平台的功能来实现一个共同目标来处理此类问题的传统方法是使用条件定义的宏或具有条件定义的实现的包装函数来隐藏平台特定的位。例如,

#if defined(_MSC_VER)
// Sleep() expects an argument in milliseconds
#define SLEEP(time) Sleep((time) * 1000)
#else
// sleep() expects an argument in seconds
#define SLEEP(time) sleep(time)
#endif

但是,对于您的特定情况,也可能会调用一个用户期望的超时的函数,而您希望该超时总是终止。 Pthreads确实提供了您可以使用的功能,例如pthread_cond_timedwait()。您可以使用该函数编写sleep函数,而无需任何条件编译。例如,

int my_sleep(long milliseconds) {
    static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
    static pthread_cond_t cv = PTHREAD_COND_INITIALIZER;
    int rval = 0;

    if (milliseconds > 0) {
        struct timespec time;

        rval = timespec_get(&time,TIME_UTC);
        // ... handle any error ...
        time.tv_nsec += (milliseconds % 1000) * 1000000;
        time.tv_sec += milliseconds / 1000 + time.tv_nsec / 1000000;
        time.tv_nsec %= 1000000;

        rval = pthread_mutex_lock(&mutex);
        if (rval != 0) {
            // handle error ...
        } else {
            // The loop handles spurrious wakepups
            do {
                rval = pthread_cond_timedwait(&cond,&mutex,&time);  // expects ETIMEDOUT
            } while (rval == 0);
            if (rval != ETIMEDOUT) {
                // handle error ...
            }
            rval = pthread_mutex_unlock(&mutex);  // THIS MUST NOT BE SKIPPED
            // ... handle any error ...
        }
    }

    return rval;
}