/*与void mq_push(mq_t m,struct list_node *msg) * 的区别,无论如何也不会调用mq_sync_push */ struct per_thread_struct* mq_push_local(mq_t m,struct list_node *msg) { struct per_thread_struct *pts = (struct per_thread_struct*)pthread_getspecific(m->t_key); if(!pts) { pts = per_thread_create(); LINK_LIST_PUSH_BACK(m->local_lists,pts); pthread_setspecific(m->t_key,(void*)pts); } if(0 == pts->is_associate) { struct thread_associate_mqs *tmq = (struct thread_associate_mqs*)pthread_getspecific(g_mq_system->t_key); if(!tmq) { tmq = (struct thread_associate_mqs*)calloc(1,sizeof(tmq)); tmq->mqs = LINK_LIST_CREATE(); mutex_lock(g_mq_system->mtx); LINK_LIST_PUSH_BACK(g_mq_system->thread_mqs,tmq); mutex_unlock(g_mq_system->mtx); pthread_setspecific(g_mq_system->t_key,(void*)tmq); } struct thread_mq_element *ele = calloc(1,sizeof(*ele)); ele->_mq = m; LINK_LIST_PUSH_BACK(tmq->mqs,ele); pts->is_associate = 1; } LINK_LIST_PUSH_BACK(pts->local_push_q,msg); return pts; }
void check_time_out(sche_t s,uint32_t now) { coro_t co; for( ; ;) { struct heapele *ele = minheap_min(s->_minheap); if(!ele) break; co = (coro_t)((int8_t*)ele - sizeof(co->next)); if(co->timeout < now) break; minheap_popmin(s->_minheap); if(co->status != CORO_ACTIVE) { co->status = CORO_ACTIVE; LINK_LIST_PUSH_BACK(s->active_list_1,co); }else if(co->status == CORO_DIE) { coro_destroy(&co); if(--s->coro_size == 0) s->stop = 1; //printf("a coro destroy\n"); } } s->next_check_timeout = now + 200;//check every 200 ms }
static inline coro_t _sche_next(sche_t s,coro_t co) { coro_t next = NULL; coro_t coro_goback = co->_goback; if(NULL == coro_goback) { next = LINK_LIST_POP(coro_t,s->active_list_1); if(!next) next = LINK_LIST_POP(coro_t,s->active_list_2); if(!next) next = s->co; } else { next = coro_goback; co->_goback = NULL; } if(co->status == CORO_YIELD) { co->status = CORO_ACTIVE; LINK_LIST_PUSH_BACK(s->active_list_2,co); } assert(co != next); set_current_coro(next); return (coro_t)uthread_switch(co->ut,next->ut,co); }
void connection_push_packet(struct connection *c,wpacket_t w,packet_send_finish callback) { if(w) { w->_packet_send_finish = callback; LINK_LIST_PUSH_BACK(c->send_list,w); } }
void* coro_fun(void *arg) { //printf("a coro start\n"); coro_t co = (coro_t)arg; LINK_LIST_PUSH_BACK(co->_sche->active_list_2,co); co->status = CORO_ACTIVE; uthread_switch(co->ut,co->_sche->co->ut,co); void *ret = co->fun(co->arg); co->status = CORO_DIE; uthread_switch(co->ut,co->_sche->co->ut,co); return NULL; }
void mq_push_list(mq_t m,struct link_list *l,uint32_t timeout) { struct per_thread_struct *pts = (struct per_thread_struct*)pthread_getspecific(m->t_key); if(!pts) { pts = per_thread_create(); LINK_LIST_PUSH_BACK(m->local_lists,pts); pthread_setspecific(m->t_key,(void*)pts); } if(link_list_is_empty(pts->local_pop_q)) mq_sync_pop(m,pts,timeout); link_list_swap(l,pts->local_pop_q); }
static void write_to_file(log_t l,int32_t is_close) { mutex_lock(l->mtx); if(!list_is_empty(l->log_queue)) link_list_swap(l->pending_log,l->log_queue); mutex_unlock(l->mtx); if(is_close) { //日志系统关闭,写入关闭消息 char buf[4096]; time_t t = time(NULL); struct tm re; struct tm *_tm = localtime_r(&t,&re); snprintf(buf,4096,"[%d-%d-%d %d:%d:%d]close log sucessful\n",_tm->tm_year+1900,_tm->tm_mon+1,_tm->tm_mday,_tm->tm_hour,_tm->tm_min,_tm->tm_sec); int32_t str_len = strlen(buf); wpacket_t w = wpacket_create(0,NULL,str_len,1); wpacket_write_binary(w,buf,str_len); LINK_LIST_PUSH_BACK(l->pending_log,w); } while(!list_is_empty(l->pending_log)) { int32_t wbuf_count = prepare_write(l); int32_t bytetransfer = TEMP_FAILURE_RETRY(writev(l->file_descriptor,l->wbuf,wbuf_count)); if(bytetransfer > 0) { l->file_size += bytetransfer; on_write_finish(l,bytetransfer); g_log_system->bytes += bytetransfer; } if(bytetransfer <= 0) { printf("errno: %d wbuf_count: %d\n",errno,wbuf_count); } if(last_tick +1000 <= GetSystemMs()) { printf("log/ms:%u\n",log_count); last_tick = GetSystemMs(); log_count = 0; } } if(!is_close) { /* * if(l->file_size > max_log_filse_size) * 文件超过一定大小,将原文件重命名,开一个新的文件 */ } }
int32_t epoll_loop(engine_t n,int32_t timeout) { assert(n); uint32_t ms; uint32_t tick = GetSystemMs(); uint32_t _timeout = tick + timeout; do{ while(!LINK_LIST_IS_EMPTY(n->actived)) { socket_t s = LINK_LIST_POP(socket_t,n->actived); s->isactived = 0; if(Process(s) && s->isactived == 0) { s->isactived = 1; LINK_LIST_PUSH_BACK(n->actived,s); } } ms = _timeout - tick; int32_t nfds = TEMP_FAILURE_RETRY(epoll_wait(n->poller_fd,n->events,MAX_SOCKET,ms)); if(nfds < 0) return -1; int32_t i; for(i = 0 ; i < nfds ; ++i) { socket_t sock = (socket_t)n->events[i].data.ptr; if(sock) { //套接口可读 if(n->events[i].events & EPOLLIN) { on_read_active(sock); } //套接口可写 if(n->events[i].events & EPOLLOUT) on_write_active(sock); if(n->events[i].events & EPOLLERR) { //套接口异常 } } } tick = GetSystemMs(); }while(tick < _timeout); return 0; }
int32_t connector_connect(connector_t c,const char *ip,uint32_t port,on_connect call_back,void *ud,uint32_t ms) { struct sockaddr_in remote; HANDLE sock; struct pending_connect *pc; sock = OpenSocket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if(sock < 0) return -1; remote.sin_family = AF_INET; remote.sin_port = htons(port); if(inet_pton(INET,ip,&remote.sin_addr) < 0) { printf("%s\n",strerror(errno)); return -1; } if(ms>0) { if(setNonblock(sock)!=0) return -1; } if(Connect(sock, (struct sockaddr *)&remote, sizeof(remote)) == 0) { //连接成功,无需要后续处理了,直接调用回调函数 call_back(sock,ip,port,ud); return 0; } socket_t s = GetSocketByHandle(sock); pc = malloc(sizeof(*pc)); pc->lnode.next = NULL; pc->sock = sock; pc->ip = ip; pc->port = port; pc->call_back = call_back; pc->timeout = GetSystemMs() + ms; pc->ud = ud; pc->real_fd = s->fd; mutex_lock(c->lock); LINK_LIST_PUSH_BACK(c->extern_pending_connect,pc); mutex_unlock(c->lock); return 0; }
int32_t log_write(log_t l,const char *content,int32_t level) { if(g_log_system->is_close) return -1; char buf[4096]; time_t t = time(NULL); struct tm re; struct tm *_tm = localtime_r(&t,&re); snprintf(buf,4096,"[%d-%d-%d %d:%d:%d]%s\n",_tm->tm_year+1900,_tm->tm_mon+1,_tm->tm_mday,_tm->tm_hour,_tm->tm_min,_tm->tm_sec,content); //snprintf(buf,4096,"%s\n",content); int32_t str_len = strlen(buf); wpacket_t w = wpacket_create(0,NULL,str_len,1); wpacket_write_binary(w,buf,str_len); mutex_lock(l->mtx); LINK_LIST_PUSH_BACK(l->log_queue,w); mutex_unlock(l->mtx); return 0; }
int32_t connection_send(struct connection *c,wpacket_t w,packet_send_finish callback) { int32_t bytestransfer = 0; uint32_t err_code = 0; st_io *O; int32_t ret = 1; if(w) { w->_packet_send_finish = callback; LINK_LIST_PUSH_BACK(c->send_list,w); } if(!c->send_overlap.isUsed) { c->send_overlap.isUsed = 1; O = prepare_send(c); return WSASend(c->socket,O,0,&err_code); } }
int32_t connection_send(struct connection *c,wpacket_t w,packet_send_finish callback) { st_io *O; if(w) { w->send_tick = GetCurrentMs(); w->_packet_send_finish = callback; LINK_LIST_PUSH_BACK(c->send_list,w); } if(!c->send_overlap.isUsed) { O = prepare_send(c); if(O) { c->send_overlap.isUsed = 1; return Post_Send(c->socket,O); } } return 0; }
/* * next选择方案,如果有goback优先选择goback作为下一个被运行的coro, * 否则取active_list_1首元素作为下一个被运行的coro,如果active_list_1 * 为空则直接返回. */ coro_t _sche_next_1(sche_t s,coro_t co) { coro_t next = NULL; coro_t coro_goback = co->_goback; if(NULL == coro_goback) { coro_t next = LINK_LIST_POP(coro_t,s->active_list_1); if(!next) return NULL; } else { next = coro_goback; co->_goback = NULL; } LINK_LIST_PUSH_BACK(s->active_list_2,co); assert(co != next); set_current_coro(next); return (coro_t)uthread_switch(co->ut,next->ut,co); }
log_t create_log(const char *path) { log_t l = calloc(1,sizeof(*l)); l->file_descriptor = open(path,O_RDWR|O_CREAT,S_IWUSR|S_IRUSR); if(l->file_descriptor < 0) { free(l); l = 0; } else { l->file_size = 0; l->mtx = mutex_create(); l->log_queue = create_link_list(); l->pending_log = create_link_list(); //add to log system mutex_lock(g_log_system->mtx); LINK_LIST_PUSH_BACK(g_log_system->log_files,l); mutex_unlock(g_log_system->mtx); log_write(l,"open log file",1); } return l; }
void rem_listener(acceptor_t a,SOCK l) { if(a) { struct epoll_event ev;int32_t ret; TEMP_FAILURE_RETRY(ret = epoll_ctl(a->poller_fd,EPOLL_CTL_DEL,GetSocketByHandle(l)->fd,&ev)); if(ret == 0) { int32_t count = link_list_size(a->st_listens); while(count>0) { struct st_listen *_st = LINK_LIST_POP(struct st_listen *,a->st_listens); if(_st->sock == l) { ReleaseSocket(l); free(_st); break; } else LINK_LIST_PUSH_BACK(a->st_listens,_st); --count; }; } }
SOCK add_listener(acceptor_t a,const char *ip,uint32_t port,on_accept call_back,void *ud) { if(!a) return INVALID_SOCK; SOCK ListenSocket; struct sockaddr_in servaddr; ListenSocket = Tcp_Listen(ip,port,&servaddr,256); if(ListenSocket != INVALID_SOCK) { struct st_listen *_st = (struct st_listen *)calloc(1,sizeof(*_st)); _st->accept_callback = call_back; _st->ud = ud; _st->sock = ListenSocket; _st->real_fd = GetSocketByHandle(ListenSocket)->fd; int32_t ret = -1; struct epoll_event ev; ev.data.ptr = _st; ev.events = EV_IN; TEMP_FAILURE_RETRY(ret = epoll_ctl(a->poller_fd,EPOLL_CTL_ADD,_st->real_fd,&ev)); if(ret == -1) { ReleaseSocket(ListenSocket); printf("listen %s:%d error\n",ip,port); return INVALID_SOCK; } LINK_LIST_PUSH_BACK(a->st_listens,_st); return ListenSocket; } else { ReleaseSocket(ListenSocket); printf("listen %s:%d error\n",ip,port); return INVALID_SOCK; } }
void coro_wakeup(coro_t co) { if(co->status == CORO_BLOCK) LINK_LIST_PUSH_BACK(co->_sche->active_list_1,co); }
void connector_run(connector_t c,uint32_t ms) { int32_t i = 0; uint32_t tick,_timeout,_ms; int32_t size; int32_t total; struct pending_connect *pc; struct timeval timeout; tick = GetSystemMs(); _timeout = tick + ms; struct link_list *_l = LINK_LIST_CREATE(); mutex_lock(c->lock); link_list_swap(_l,c->extern_pending_connect); mutex_unlock(c->lock); while(pc = LINK_LIST_POP(struct pending_connect*,_l)) { if(c->fd_seisize >= FD_SETSIZE) { pc->call_back(-1,pc->ip,pc->port,pc->ud); free(pc); } else { FD_SET(pc->real_fd,&c->Set); LINK_LIST_PUSH_BACK(c->_pending_connect,pc); ++c->fd_seisize; } } LINK_LIST_DESTROY(&_l); do{ _ms = _timeout - tick; timeout.tv_sec = 0; timeout.tv_usec = 1000*_ms; size = list_size(c->_pending_connect); if(size == 0) return; if((total = select(1024,0,&c->Set,0, &timeout)) >0 ) { for(; i < size; ++i) { pc = LINK_LIST_POP(struct pending_connect*,c->_pending_connect); if(pc) { if(FD_ISSET(pc->real_fd, &c->Set)) { pc->call_back(pc->sock,pc->ip,pc->port,pc->ud); free(pc); --c->fd_seisize; } else LINK_LIST_PUSH_BACK(c->_pending_connect,pc); } } } FD_ZERO(&c->Set); tick = GetSystemMs(); size = list_size(c->_pending_connect); i = 0; for(; i < (int32_t)size; ++i) { pc = LINK_LIST_POP(struct pending_connect*,c->_pending_connect); if(tick >= pc->timeout) { pc->call_back(-1,pc->ip,pc->port,pc->ud); free(pc); --c->fd_seisize; } else { LINK_LIST_PUSH_BACK(c->_pending_connect,pc); FD_SET(pc->real_fd,&c->Set); } } tick = GetSystemMs(); }while(tick < _timeout); }