清单 7. pthread_cond_timedwait() 函数定义
int pthread_cond_timedwait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex, const struct timespec *restrict abstime);
参数 abstime 在这里用来表示和超时时间相关的一个参数,但是需要注意的是它所表示的是一个绝对时间,而不是一个时间间隔数值,只有当系统的当前时间达到或者超过 abstime 所表示的时间时,才会触发超时事件。这对于拥有 Windows 平台线程开发经验的人来说可能尤为困惑。因为 Windows 平台下所有的 API 等待参数(如 SignalObjectAndWait,等)都是相对时间,
假设我们指定相对的超时时间参数如 dwMilliseconds (单位毫秒)来调用和超时相关的函数,这样就需要将 dwMilliseconds 转化为 Linux 下的绝对时间参数 abstime 使用。常用的转换方法如清单 8 所示:
清单 8. 相对时间到绝对时间转换实例
struct timeval now;
/* get the current time */
gettimeofday(&now, NULL); /* add the offset to get timeout value */
ts.tv_nsec = now.tv_usec * 1000 + (millisesecond % 1000) * 1000000;
ts.tv_sec = now.tv_sec + millisesecond / 1000;
int pthread_cond_timedwait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex, const struct timespec *restrict abstime);
参数 abstime 在这里用来表示和超时时间相关的一个参数,但是需要注意的是它所表示的是一个绝对时间,而不是一个时间间隔数值,只有当系统的当前时间达到或者超过 abstime 所表示的时间时,才会触发超时事件。这对于拥有 Windows 平台线程开发经验的人来说可能尤为困惑。因为 Windows 平台下所有的 API 等待参数(如 SignalObjectAndWait,等)都是相对时间,
假设我们指定相对的超时时间参数如 dwMilliseconds (单位毫秒)来调用和超时相关的函数,这样就需要将 dwMilliseconds 转化为 Linux 下的绝对时间参数 abstime 使用。常用的转换方法如清单 8 所示:
清单 8. 相对时间到绝对时间转换实例
struct timeval now;
/* get the current time */
gettimeofday(&now, NULL); /* add the offset to get timeout value */
ts.tv_nsec = now.tv_usec * 1000 + (millisesecond % 1000) * 1000000;
ts.tv_sec = now.tv_sec + millisesecond / 1000;
Linux 的绝对时间看似简单明了,却是开发中一个非常隐晦的陷阱。而且一旦你忘了时间转换,可以想象,等待你的错误将是多么的令人头疼:如果忘了把相对时间转换成绝对时间,相当于你告诉系统你所等待的超时时间是过去式的 1970 年 1 月 1 号某个时间段,于是操作系统毫不犹豫马上送给你一个 timeout 的返回值,然后你会举着拳头抱怨为什么另外一个同步线程耗时居然如此之久,并一头扎进寻找耗时原因的深渊里。
转自 http://blog.youkuaiyun.com/lllxy/article/details/3874415
附 win32 实现 gettimeofday
#include <time.h>
#ifdef WIN32
# include <windows.h>
#else
# include <sys/time.h>
#endif
#ifdef WIN32
int
gettimeofday(struct timeval *tp, void *tzp)
{
time_t clock;
struct tm mytm;
SYSTEMTIME wtm;
GetLocalTime(&wtm);
mytm.tm_year = wtm.wYear - 1900;
mytm.tm_mon = wtm.wMonth - 1;
mytm.tm_mday = wtm.wDay;
mytm.tm_hour = wtm.wHour;
mytm.tm_min = wtm.wMinute;
mytm.tm_sec = wtm.wSecond;
mytm. tm_isdst = -1;
clock = mktime(&mytm);
tp->tv_sec = clock;
tp->tv_usec = wtm.wMilliseconds * 1000;
return (0);
}
#endif