時間堆實現定時器

2021-08-01 03:46:54 字數 3368 閱讀 7418

時間堆:將所有定時器中超時最小的乙個作為心搏間隔,這樣,一旦心搏函式tick被呼叫,超時時間最小的乙個定時器必然到期,我們就可以在tick函式裡處理該定時器,這樣就實現了較為精確的定時.

最小堆很適合這種方案,最小堆的堆頂永遠為最小的元素,這樣每次只要將堆頂的定時器處理,並將下乙個堆頂元素的超時時間作為下一次心搏間隔即可實現上述方案

#ifndef _min_heap_h

#define _min_heap_h

#include

#include

#include

using std::exception;

#define buffer_size 64

class heap_timer;

class client_data

;class heap_timer

time_t expire;

void (*cb_func)(client_data*);

client_data *user_data;

};class time_heap

for(int i = 0;i=0;--i)}}

~time_heap()

int hole = cur_size++;

int parent = 0;

for(; hole > 0;hole = parent)

array[hole] = array[parent];

}array[hole] = timer;

}void del_timer(heap_timer* timer)

timer->cb_func = null;//延遲銷毀

}heap_timer* top()const

return array[0];

}void pop_timer()

if(array[0])

}void tick()

if(tmp->expire > cur)

if(array[0]->cb_func)

pop_timer();

tmp = array[0];}}

bool empty()const

private:

void percolate_down(int hole)

if( array[child]->expire < temp->expire)

else

}array[hole] = temp;

}void resize()throw(std::exception)

if(!temp)

capacity = 2*capacity;

for(int i=0;iexpire-time(null)));//將定時器中最小超時時間(即堆頂計時器的超時時間)作為下一次心搏時間,這樣可以減少tick函式被呼叫的次數,保證每次呼叫必然都有超時事件發生

else

alarm(timeslot);

}void addsig(int sig)

void cb_func(client_data* user_data)

int main(int argc,char *argv)

const char *ip = argv[1];

int port = atoi(argv[2]);

struct sockaddr_in address;

bzero(&address,sizeof(address));

address.sin_family = af_inet;

address.sin_port = htons(port);

inet_pton(af_inet,ip,&address.sin_addr);

int sock = socket(af_inet,sock_stream,0);

assert(sock>=0);

int ret = bind(sock,(struct sockaddr*)&address,sizeof(address));

assert(ret!=-1);

ret = listen(sock,5);

assert(ret!=-1);

epoll_event events[max_event_number];

int epollfd = epoll_create(5);

assert(epollfd!=-1);

addfd(epollfd,sock);

ret = socketpair(pf_unix,sock_stream,0,pipefd);

if(ret == -1)

setnonblocking(pipefd[1]);

addfd(epollfd,pipefd[0]);

addsig(sigterm);

addsig(sigalrm);

int stop_sever = 0;

client_data* users = new client_data[max_event_number];

int timeout = 0;

alarm(timeslot);

while(!stop_sever)

else

}int i=0;

for(;iuser_data = &users[connfd];

timer->cb_func = cb_func;

time_t cur = time(null);

timer->expire = cur +3*timeslot;

users[connfd].timer = timer;

th.add_timer(timer);

}else if((sockfd == pipefd[0])&&(events[i].events & epollin))

else if(ret == 0)

else}}

else

}if(timeout)

}close(sock);

close(pipefd[0]);

close(pipefd[1]);

delete users;//???

return 0;

}cli.c:

#include"./utili1.h"

int main(int argc,char *argv)

/*        ret = recv(sock,buf,38,msg_dontwait );

if(ret!=0)

*/    }/*

while(1)

else

printf("get %d bytes :  %s\n",(int)strlen(buf),buf);}*/

close(sock);

}tianxintong@txt:~/sigalarm/time_heap_sigalarm$

php實現毫秒定時器(時間堆)

最近研究workerman原始碼,學習了定時器部分,從裡面抄了乙個定時器出來,單獨出來,有利於理解定時器原理。下面是 呼叫方式跟workerman一樣,都是新增定時事件進去,可以使延時呼叫一次,也可以是定時呼叫,間隔一段事件就執行一次。測試執行,在命令列裡面,執行php timer.php即可。可以...

高效能定時器 時間堆

時間堆 時間輪給我們的感覺依舊不夠精細,因為它是按照時間間隔來執行定時器的。時間堆的設計思路是 將所有定時器中超時時間最小的定時器的超時值作為心博間隔。一旦心博函式被呼叫,超時時間最小的定時器必然到期,我們就可以準確的處理它。然後,再從剩餘的定時器中找出超時時間最小的那個,作為下一次心博時間,這樣,...

定時器 時間配置

cron表示式是乙個字串,字串以5或6個空格隔開,分為6或7個域,每乙個域代表乙個含義,cron有如下兩種語法格式 seconds minutes hours dayofmonth month dayofweek year或 seconds minutes hours dayofmonth mont...