int32_t evtimer_clean( struct evtimer * self ) { int32_t i = 0, rc = 0; for ( i = 0; i < self->bucket_count; ++i ) { struct event * ev = NULL; struct event_list * head = &( self->bucket_array[i] ); for ( ev = TAILQ_FIRST(head); ev; ) { struct event * next = TAILQ_NEXT( ev, timerlink ); evsets_del( event_get_sets((event_t)ev), (event_t)ev ); ++rc; ev = next; --self->event_count; } } self->dispatch_refer = 0; return rc; }
void ev_timer_callback( int32_t fd, int16_t ev, void * arg ) { event_t e = (event_t)arg; evsets_t sets = event_get_sets( e ); printf("ev_timer_callback(handler=%p, fd=%d, ev=%d) : %d \n", e, fd, ev, time(NULL) ); evsets_add( sets, e, 2*1000 ); }
void echoserver_process_message( int32_t fd, int16_t ev, void * arg ) { struct session * s = (struct session *)arg; if ( ev & EV_READ ) { char buf[16384]; int32_t readn = -1; readn = read( fd, buf, 16384 ); if ( readn <= 0 ) { #if __DEBUG printf( "Client[%ld, %d] is closed, BYTES:%d, TIME:%lld .\n", s->sid, s->fd, s->iobytes, mtime() ); #endif //evsets_del( event_get_sets(s->evread), s->evread ); event_destroy( s->evread ); close( s->fd ); free( s ); goto PROCESS_END; } else { #if __DEBUG printf("echoserver_process_message(ev:%d) : TIME:%lld .\n", ev, mtime() ); #endif readn = write( fd, buf, readn ); s->iobytes += readn; } #if USE_LIBEVENT { struct timeval tv = {TIMEOUT_MSECS/1000, 0}; event_add( s->evread, &tv ); } #else evsets_add( event_get_sets(s->evread), s->evread, TIMEOUT_MSECS ); #endif } else { #if __DEBUG printf("echoserver_process_message(ev:%d) : TIME:%lld .\n", ev, mtime() ); #endif } PROCESS_END : return; }
void echoserver_process_message( int32_t fd, int16_t ev, void * arg ) { struct session * s = (struct session *)arg; if ( ev & EV_READ ) { char buf[16384]; int32_t readn = -1; readn = read( fd, buf, 16384 ); if ( readn <= 0 ) { #if __DEBUG printf( "Client[%ld, %d] is closed, BYTES:%d, TIME:%lld .\n", s->sid, s->fd, s->iobytes, milliseconds() ); #endif //evsets_del( event_get_sets(s->evread), s->evread ); event_destroy( s->evread ); close( s->fd ); free( s ); goto PROCESS_END; } else { #if __DEBUG printf("echoserver_process_message(ev:%d) : TIME:%lld .\n", ev, milliseconds() ); #endif readn = write( fd, buf, readn ); s->iobytes += readn; } #if USE_LIBEVENT { struct timeval tv = {TIMEOUT_MSECS/1000, 0}; event_add( s->evread, &tv ); } #else evsets_add( event_get_sets(s->evread), s->evread, TIMEOUT_MSECS ); #endif } else { #if __DEBUG printf("echoserver_process_message(ev:%d) : TIME:%lld .\n", ev, milliseconds() ); #endif } PROCESS_END : } void accept_new_session( int32_t fd, int16_t ev, void * arg ) { struct iothread * thr = (struct iothread *)arg; struct acceptor * a = thr->core_acceptor; if ( ev & EV_READ ) { // // 接收新连接完毕后 // char srchost[20]; char dsthost[20]; uint16_t dstport = 0; int32_t newfd = tcp_accept( fd, srchost, dsthost, &dstport ); if ( newfd > 0 ) { uint64_t sid = 0; struct session * newsession = NULL; set_fd_nonblock( newfd ); newsession = (struct session *)malloc( sizeof(struct session) ); if ( newsession == NULL ) { printf("Out of memory, allocate for 'newsession' failed .\n"); goto ACCEPT_END; } newsession->evread = event_create(); if ( newsession->evread == NULL ) { printf("Out of memory, allocate for 'newsession->evread' failed .\n"); goto ACCEPT_END; } newsession->iobytes = 0; newsession->fd = newfd; sid = thr->key; sid <<= 32; sid += thr->index++; newsession->sid = sid; #if USE_LIBEVENT { struct timeval tv = {TIMEOUT_MSECS/1000, 0}; event_set( newsession->evread, newsession->fd, EV_READ, echoserver_process_message, newsession ); event_base_set( thr->core_sets, newsession->evread ); event_add( newsession->evread, &tv ); } #else event_set( newsession->evread, newsession->fd, EV_READ ); event_set_callback( newsession->evread, echoserver_process_message, newsession ); evsets_add( thr->core_sets, newsession->evread, TIMEOUT_MSECS ); #endif #if __DEBUG printf( "Thread[%d] accept a new Client[%lld, fd:%d, '%s':%d] .\n", thr->key, newsession->sid, newsession->fd, dsthost, dstport ); #endif } a->holding = 0; pthread_mutex_unlock( &(a->lock) ); } ACCEPT_END : } void trylock_accept_mutex( struct iothread * thr ) { struct acceptor * a = thr->core_acceptor; if ( pthread_mutex_trylock(&(a->lock)) == 0 ) { if ( a->holding == 0 ) { #if USE_LIBEVENT event_set( a->ev_accept, a->socketfd, EV_READ, accept_new_session, thr ); event_base_set( thr->core_sets, a->ev_accept ); event_add( a->ev_accept, 0 ); #else event_set( a->ev_accept, a->socketfd, EV_READ ); event_set_callback( a->ev_accept, accept_new_session, thr ); evsets_add(thr->core_sets, a->ev_accept, 0 ); #endif a->holding = 1; } //pthread_mutex_unlock( &(a->lock) ); } } void acceptor_destroy( struct acceptor * self ) { pthread_mutex_destroy( &(self->lock) ); if ( self->socketfd > 0 ) { close( self->socketfd ); } if ( self->ev_accept != NULL ) { event_destroy( self->ev_accept ); } free( self ); } struct acceptor * acceptor_create( const char * host, uint16_t port ) { struct acceptor * a = NULL; a = (struct acceptor *)malloc( sizeof(struct acceptor) ); if ( a ) { a->holding = 0; a->socketfd = 0; a->ev_accept = NULL; pthread_mutex_init( &(a->lock), NULL ); a->socketfd = tcp_listen( host, port ); if ( a->socketfd < 0 ) { acceptor_destroy( a ); return NULL; } set_fd_nonblock( a->socketfd ); a->ev_accept = event_create(); if ( a->ev_accept == NULL ) { acceptor_destroy( a ); return NULL; } } return a; } void * iothread_main( void * arg ) { struct iothread * thr = (struct iothread *)arg; thr->running = 1; while ( thr->running ) { // // 尝试加锁 // trylock_accept_mutex( thr ); // // 分发IO事件 // evsets_dispatch( thr->core_sets ); } return (void *)0; } struct iothread * iothread_create( uint8_t key, struct acceptor * a ) { pthread_t tid; struct iothread * thr = NULL; thr = (struct iothread *)malloc( sizeof(struct iothread) ); if ( thr ) { thr->key = key; thr->index = 0; thr->core_acceptor = a; thr->core_sets = evsets_create(); if ( thr->core_sets == NULL ) { #if __DEBUG printf( "out of memory, allocate for 'thr->core_sets' failed, Thread[%d] .\n", key ); #endif return NULL; } pthread_create( &tid, NULL, iothread_main, thr ); } return thr; }
int32_t evtimer_dispatch( struct evtimer * self ) { int32_t rc = 0; int32_t done = 0, index = 0; struct event * laster = NULL; struct event_list * head = NULL; index = EVTIMER_INDEX(self, self->dispatch_refer); ++self->dispatch_refer; head = &( self->bucket_array[index] ); // // 该桶中没有定时的事件 // if ( TAILQ_EMPTY(head) ) { return 0; } // // 遍历超时事件链表 // laster = TAILQ_LAST( head, event_list ); while ( !done ) { struct event * ev = TAILQ_FIRST(head); // // 由于某些事件的超时时间过长 // 所以还是需要继续添加到事件链表中的 // 必须判断当前节点是否是链表的尾部元素 // if ( ev == laster ) { done = 1; } --ev->timer_stepcnt; if ( ev->timer_stepcnt > 0 ) { // // 未超时 // TAILQ_REMOVE( head, ev, timerlink ); TAILQ_INSERT_TAIL( head, ev, timerlink ); } else if ( ev->timer_stepcnt == 0 ) { // // 超时了 // 从队列中删除, 并添加到激活队列中 // ++rc; evsets_del( event_get_sets((event_t)ev), (event_t)ev ); event_active( ev, EV_TIMEOUT ); } else { // // 出错了 // evsets_del( event_get_sets((event_t)ev), (event_t)ev ); } } return rc; }