营销型网站建设的关键特点,app001推广平台官网,印象笔记 wordpress,常用的网络营销方法及效果在开发Linux网络程序时#xff0c;通常需要维护多个定时器#xff0c;如维护客户端心跳时间、检查多个数据包的超时重传等。如果采用Linux的SIGALARM信号实现#xff0c;则会带来较大的系统开销#xff0c;且不便于管理。 本文在应用层实现了一个基于时间堆的高性能定时器通常需要维护多个定时器如维护客户端心跳时间、检查多个数据包的超时重传等。如果采用Linux的SIGALARM信号实现则会带来较大的系统开销且不便于管理。 本文在应用层实现了一个基于时间堆的高性能定时器同时考虑到定时的粒度问题由于通过alarm系统调用设置的SIGALARM信号只能以秒为单位触发因此需要采用其它手段实现更细粒度的定时操作当然这里不考虑使用多线程sleep的实现方法理由性能太低。 通常的做法还有采用基于升序的时间链表但升序时间链表的插入操作效率较低需要遍历链表。因此本实现方案使用最小堆来维护多个定时器插入O(logn)、删除O(1)、查找O(1)的效率较高。 首先是每个定时器的定义 class heap_timer { public: heap_timer( int ms_delay ) { gettimeofday( expire, NULL ); expire.tv_usec ms_delay * 1000; if ( expire.tv_usec 1000000 ) { expire.tv_sec expire.tv_usec / 1000000; expire.tv_usec % 1000000; } } public: struct timeval expire; void (*cb_func)( client_data* ); client_data* user_data; ~heap_timer() { delete user_data; } }; 包括一个超时时间expire、超时回调函数cb_func以及一个user_data变量user_data用于存储与定时器相关的用户数据用户数据可以根据不同的应用场合进行修改这里实现的是一个智能博物馆的网关网关接收来自zigbee协调器的用户数据并为每个用户维护一段等待时间T在T到来之前同一个用户的所有数据都存放到user_data的target_list中当T到来时根据target_list列表选择一个适当的target并发送到ip_address同时删除定时器有点扯远了。。总之要实现的功能就是给每个用户维护一个定时器定时值到来时做一些操作。 class client_data { public: client_data(char *address):target_count(0) { strcpy(ip_address,address); } private: char ip_address[32]; target target_list[64]; int target_count; ...... }; 以下是时间堆的类定义包括了一些基本的堆操作插入、删除、扩容还包括了定时器溢出时的操作函数tick() class time_heap { public: time_heap( int cap 1) throw ( std::exception ) : capacity( cap ), cur_size( 0 ) { array new heap_timer* [capacity]; if ( ! array ) { throw std::exception(); } for( int i 0; i capacity; i ) { array[i] NULL; } } ~time_heap() { for ( int i 0; i cur_size; i ) { delete array[i]; } delete [] array; } public: int get_cursize() { return cur_size; } void add_timer( heap_timer* timer ) throw ( std::exception ) { if( !timer ) { return; } if( cur_size capacity ) { resize(); } int hole cur_size; int parent 0; for( ; hole 0; holeparent ) { parent (hole-1)/2; if ( timercmp( (array[parent]-expire), (timer-expire), ) ) { break; } array[hole] array[parent]; } array[hole] timer; } void del_timer( heap_timer* timer ) { if( !timer ) { return; } // lazy delelte timer-cb_func NULL; } int top(struct timeval time_top) const { if ( empty() ) { return 0; } time_top array[0]-expire; return 1; } void pop_timer() { if( empty() ) { return; } if( array[0] ) { delete array[0]; array[0] array[--cur_size]; percolate_down( 0 ); } } void tick() { heap_timer* tmp array[0]; struct timeval cur; gettimeofday( cur, NULL ); while( !empty() ) { if( !tmp ) { break; } if( timercmp( cur, (tmp-expire), ) ) { break; } if( array[0]-cb_func ) { array[0]-cb_func( array[0]-user_data ); } pop_timer(); tmp array[0]; } } bool empty() const { return cur_size 0; } heap_timer** get_heap_array() { return array; } private: void percolate_down( int hole ) { heap_timer* temp array[hole]; int child 0; for ( ; ((hole*21) (cur_size-1)); holechild ) { child hole*21; if ( (child (cur_size-1)) timercmp( (array[child1]-expire), (array[child]-expire), ) ) { child; } if ( timercmp( (array[child]-expire), (temp-expire), ) ) { array[hole] array[child]; } else { break; } } array[hole] temp; } void resize() throw ( std::exception ) { heap_timer** temp new heap_timer* [2*capacity]; for( int i 0; i 2*capacity; i ) { temp[i] NULL; } if ( ! temp ) { throw std::exception(); } capacity 2*capacity; for ( int i 0; i cur_size; i ) { temp[i] array[i]; } delete [] array; array temp; } private: heap_timer** array; int capacity; int cur_size; };