因为timer_create在mac os x下边并没有实现,所以
void ErrorManager::threadFun()
{
HANDLE hTimer;
LARGE_INTEGER li;
hTimer = CreateWaitableTimer(NULL, FALSE, NULL);
const int nTimerUnitsPerSecond = 10000000;
li.QuadPart = -(5 * nTimerUnitsPerSecond);
HANDLE handles[] = { hTimer, hQuitEvent_ };
while (!quit_) {
SetWaitableTimer(hTimer, &li, 0,
NULL, NULL, FALSE);
auto result = WaitForMultipleObjects(2, handles, FALSE, INFINITE);
if (result == WAIT_OBJECT_0) {
client_->queueCheckTimeoutTask();
} else if (result == WAIT_OBJECT_0 + 1) {
break;
}
}
CloseHandle(hTimer);
}
void ErrorManager::quit()
{
quit_ = true;
SetEvent(hQuitEvent_);
}
像以上这种windows下的timer代码并不是很容易实现,虽然我们都知道一般os kernel都会有原生的timer list,在rtc中断时候内核会处理,比如讲linux内核实现的posix timer就是这么处理的,但是freebsd/mac os x是没有的,相同的功能最后还是需要kqueue这种看上去比较重量级的东西来实现。
#include <stdio.h>
#include <sys/types.h>
#include <sys/event.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <unistd.h>
#include <fcntl.h>
static void output_time()
{
time_t tick = time(NULL);
struct tm atm;
localtime_r(&tick, &atm);
printf("current time %02d:%02d:%02d\n", atm.tm_hour, atm.tm_min, atm.tm_sec);
}
int main()
{
int kq = kqueue();
if (kq < 0) {
perror("create kqueue failed");
return -1;
}
umask(0);
if (mknod("keke", S_IFIFO | 0666, 0) < 0) {
perror("create named pipe failed");
return -1;
}
puts("mknod succeeded");
int fp = open("keke", O_RDONLY | O_NONBLOCK);
if (fp < 0) {
perror("failed to open named pipe\n");
return -1;
}
struct kevent ev;
puts("start to set event");
EV_SET(&ev, fp, EVFILT_READ, EV_ADD, 0, 0, 0);
if (kevent(kq, &ev, 1, NULL, 0, NULL) < 0) {
perror("failed add pipe read event");
return -1;
}
puts("after to set event");
output_time();
EV_SET(&ev, 1, EVFILT_TIMER, EV_ADD, NOTE_SECONDS, 5, 0);
if (kevent(kq, &ev, 1, NULL, 0, NULL) < 0) {
perror("failed add timer event");
return -1;
}
while (true) {
struct kevent events[2];
int count =kevent(kq, NULL, 0, events, 2, NULL);
if (count > 0) {
for (int i = 0; i < count; ++i) {
if (events[i].filter == EVFILT_TIMER) {
output_time();
} else if (events[i].filter == EVFILT_READ) {
puts("break on write event");
goto done;
}
}
}
}
done:
close(fp);
return 0;
}
这个例子可以随时可以使用pipe来中断,
#include <stdio.h>
int main()
{
FILE* fp = fopen("keke", "w");
if (fp == NULL) {
perror("failed to open named pipe");
return -1;
}
fputs("keke", fp);
fclose(fp);
return 1;
}
输出如下:
jcyangzh@fakecoder:~/src/unix/timer$ ./kq
mknod succeeded
start to set event
after to set event
current time 04:34:41
current time 04:34:46
break on write event
jcyangzh@fakecoder:~/src/unix/timer$
refer:http://www.progtown.com/post953316.html#p953316