这个是接我之前写的C日志代码(http://www.cnblogs.com/prophet-ss/p/8025825.html)的一个功能函数,这里单独拿出来说下。下面这个代码是之前写的,在windows/linux可以通用。最新linux下增加了一个单线程下可以去除锁的控制宏,一个rdtsc汇编指令宏可以获取程序运行时钟周期(比一般类似clock()函数快至少一个数量级)。如有需要可以在上面链接内取(time.c和time.h)。
简单说下设计思想,首先这里用的是临界区而不是互斥锁,主要因为临界区操作更快对计时影响小。另外一个问题就是计时器数组初始化问题,如何保证多个线程同时运行只初始化一次,这块我使用InterlockedIncrement原子加简单的解决了这一问题。由于注释写的已经很详细,具体接口功能就不再赘述,下面直接上源码:
1 #ifndef _PRO_TIME_H_ 2 #define _PRO_TIME_H_ 3 4 /* 计时器可使用最大个数 */ 5 #define TIMEKEEPER_NUM 100 6 7 #ifdef __cplusplus 8 extern "C" { 9 #endif 10 11 /* 手动计时器设置n - [0,TIMEKEEPER_NUM-1] */ 12 int timekeeper_start_man(int n); 13 14 /* 自动选取一个空闲计时器,返回值(>0)为输入thnd */ 15 int timekeeper_start_auto(); 16 17 /* 获取时间,若手动设置thnd为输入参数n,若自动设置则为 18 ** 其返回值(>0。time为输出参数为距上次经过时间,单位s */ 19 int timekeeper_pause(int thnd, double* time); 20 21 /* 获取时间,与pause不同的是获取完会清除释放计时 22 ** 器,下次无法使用 */ 23 int timekeeper_shutoff(int thnd, double* time); 24 25 /* 全部销毁,谨慎使用 */ 26 void timekeeper_destory(); 27 28 #ifdef __cplusplus 29 } 30 #endif 31 32 #endif /* !_PRO_TIME_H_ */
1 #include <time.h> 2 #if defined(_WIN32) || defined(_WIN64) 3 #include <Windows.h> 4 #else 5 #include <pthread.h> 6 #include <unistd.h> 7 #endif /* _WIN32 || _WIN64 */ 8 #include <string.h> 9 #include "pro_time.h" 10 11 struct safe_timespec 12 { 13 struct timespec spec; 14 /* 0-未被使用,1-已被占用 */ 15 long is_ref; 16 }; 17 18 #define NSEC_PER_SEC 1000000000 19 20 /*计时器临界区*/ 21 #if defined(_WIN32) || defined(_WIN64) 22 #define sleep(x) Sleep(x) 23 static CRITICAL_SECTION _timekeeper_mutex; 24 #else 25 #define atomic_inc(x) __sync_add_and_fetch((x),1) 26 static pthread_mutex_t _timekeeper_mutex = PTHREAD_MUTEX_INITIALIZER; 27 #endif /* _WIN32 || _WIN64 */ 28 29 30 /*计时器数组*/ 31 static struct safe_timespec _ptimekeeper[TIMEKEEPER_NUM] = { 0 }; 32 33 /* 多线程初始化标记,防止多次初始化 */ 34 static volatile long _timekeeper_sync = 0; 35 36 /* 初始化标志 */ 37 static volatile int _is_initialized = 0; 38 39 static void _timekeeper_initialize(void) 40 { 41 if (!_is_initialized) 42 { 43 /* 原子操作加1,如果结果为1当前只有本线程调用可以初始化,不为1(>1) 44 ** 说明有其他线程调用等待其他线程初始化完毕即可 */ 45 #if defined(_WIN32) || defined(_WIN64) 46 if (InterlockedIncrement(&_timekeeper_sync) == 1) 47 #else 48 if (atomic_inc(&_timekeeper_sync) == 1) 49 #endif /* _WIN32 || _WIN64 */ 50 { 51 /* 初始化 */ 52 #if defined(_WIN32) || defined(_WIN64) 53 InitializeCriticalSection(&_timekeeper_mutex); 54 #endif /* _WIN32 || _WIN64 */ 55 memset(_ptimekeeper, 0, TIMEKEEPER_NUM * sizeof(struct safe_timespec)); 56 _is_initialized = 1; 57 } 58 else 59 { 60 /* 等待其他线程初始化完毕 */ 61 while (!_is_initialized) sleep(0); 62 } 63 } 64 } 65 66 static void _timekeeper_lock(void) 67 { 68 _timekeeper_initialize(); 69 70 #if defined(_WIN32) || defined(_WIN64) 71 EnterCriticalSection(&_timekeeper_mutex); 72 #else 73 pthread_mutex_lock(&_timekeeper_mutex); 74 #endif /* _WIN32 || _WIN64 */ 75 76 } 77 78 static void _timekeeper_unlock(void) 79 { 80 #if defined(_WIN32) || defined(_WIN64) 81 LeaveCriticalSection(&_timekeeper_mutex); 82 #else 83 pthread_mutex_unlock(&_timekeeper_mutex); 84 #endif /* _WIN32 || _WIN64 */ 85 } 86 87 static int _timekeeper_get(int n) 88 { 89 _timekeeper_lock(); 90 91 if (_ptimekeeper[n].is_ref != 0) 92 { 93 _timekeeper_unlock(); 94 return -2; 95 } 96 timespec_get(&(_ptimekeeper[n].spec), TIME_UTC); 97 _ptimekeeper[n].is_ref = 1; 98 99 _timekeeper_unlock(); 100 return 0; 101 } 102 103 int timekeeper_start_man(int n) 104 { 105 return _timekeeper_get(n); 106 } 107 108 int timekeeper_start_auto() 109 { 110 for (int i = 0; i < TIMEKEEPER_NUM; i++) 111 { 112 if (0 == _timekeeper_get(i)) 113 return i; 114 } 115 return -1; 116 } 117 118 int timekeeper_pause(int thnd, double* time) 119 { 120 struct timespec tk; 121 if (timespec_get(&tk, TIME_UTC) != 0) 122 *time = tk.tv_sec - (_ptimekeeper[thnd].spec).tv_sec + 123 (double)(tk.tv_nsec - (_ptimekeeper[thnd].spec).tv_nsec) / NSEC_PER_SEC; 124 else 125 return -4; 126 127 return 0; 128 } 129 130 int timekeeper_shutoff(int thnd, double* time) 131 { 132 int ret; 133 if ((ret = timekeeper_pause(thnd, time)) != 0) 134 return ret; 135 136 _timekeeper_lock(); 137 _ptimekeeper[thnd].is_ref = 0; 138 _timekeeper_unlock(); 139 140 return 0; 141 } 142 143 void timekeeper_destory() 144 { 145 _timekeeper_lock(); 146 _is_initialized = 0; 147 _timekeeper_unlock(); 148 }
1 #if defined(_WIN32) || defined(_WIN64) 2 #include <Windows.h> 3 #else 4 #include <pthread.h> 5 #endif /* _WIN32 || _WIN64 */ 6 #include <stdio.h> 7 #include "pro_time.h" 8 9 10 void* test(void *arg) 11 { 12 int i; 13 int t = *(int*)arg; 14 for (i = 0; i < 11; i++) 15 { 16 int n = timekeeper_start_auto(); 17 printf("thread%d,i=%d,", t, n); 18 double tm; 19 timekeeper_pause(n, &tm); 20 printf("%f\n", tm); 21 } 22 } 23 24 int main() 25 { 26 pthread_t tpid[10]; 27 int i; 28 for (i = 0; i < 10; i++) 29 { 30 #if defined(_WIN32) || defined(_WIN64) 31 _beginthread(fun, 0, &i); 32 #else 33 pthread_create(&tpid[i], NULL, &test, &i); 34 #endif /* _WIN32 || _WIN64 */ 35 } 36 }
=======================================================================================
2018-03-11 23:40:53更新:增加linux和C++的使用
=======================================================================================
2018-07-03 21:26:34更新:linux添加rdtsc指令宏和多线程控制宏