/* execute the task callback function. */ static int task_func(void *argv) { struct kqueuemgr *mgr = (struct kqueuemgr *)argv; struct kevent *ev; struct socketer *sock; for (;;) { if (mgr->need_exit) return -1; ev = pop_event(mgr); if (!ev) return 0; assert(ev->udata != NULL); sock = (struct socketer *)ev->udata; /* error event. */ if (ev->flags & EV_EOF || ev->flags & EV_ERROR) { socketer_close(sock); continue; } if (ev->filter == EVFILT_READ) { /* can read event. */ if (catomic_compare_set(&sock->recvlock, 0, 1)) { catomic_inc(&sock->ref); } socketer_on_recv(sock, 0); } else if (ev->filter == EVFILT_WRITE) { /* can write event. */ if (catomic_compare_set(&sock->sendlock, 0, 1)) { catomic_inc(&sock->ref); } socketer_on_send(sock, 0); } } }
static void th_pro_func(cthread *th) { int cinfo_id = 0; struct cthread_info *cinfo = (struct cthread_info *)cthread_get_udata(th); struct cthread_pool *mgr = cinfo->mgr; /* first suspend. */ cthread_suspend(cthread_info_get_handle_ptr(cinfo)); /* check need run. */ if (catomic_read(&mgr->run) == 0) return; cinfo_id = (int)cthread_info_get_id(cinfo); (void)cinfo_id; cthread_info_state_to_activity(cinfo); catomic_inc(&mgr->resume_num); catomic_inc(&mgr->activity_num); catomic_inc(&mgr->need_exit_num); /* wait all run to here. */ while (catomic_read(&mgr->need_exit_num) != (int64)mgr->thread_num) { cthread_self_sleep(0); } thread_pool_debuglog("func:[%s][start thread] id:%d", __FUNCTION__, cthread_info_get_id(cinfo)); while (catomic_read(&mgr->run) != 0) { if (cthread_info_is_header(cinfo)) { /* * do leader function, * if return value less than 0, then exit. * if return value greater than 0, then is need resume thread num. */ int resume_num = mgr->func_leader(mgr->udata); if (resume_num > 0) { int real_resume_num = (int)min(resume_num, catomic_read(&mgr->need_exit_num)); thread_pool_debuglog("func:[%s][leader func return] leader thread id:%d, " "resume_num:%d, activity num:%d, exit num:%d, has_leader:%d", __FUNCTION__, cthread_info_get_id(cinfo), resume_num, (int)catomic_read(&mgr->activity_num), (int)catomic_read(&mgr->exit_num), (int)catomic_read(&mgr->has_leader)); cthread_info_change_to_henchman(cinfo); catomic_set(&mgr->has_leader, 0); catomic_set(&mgr->resume_num, real_resume_num); cthread_pool_resume_some_thread(mgr, real_resume_num - 1, cinfo); } else if (resume_num < 0) { break; } } else { /* * do task function, * the return value is not equal to 0, then exit. */ if (mgr->func_task(mgr->udata) != 0) break; /* If own is the last activity of the followers, set own to leader. */ if (catomic_dec(&mgr->resume_num) == 0) { assert(catomic_read(&mgr->activity_num) >= 1); assert(catomic_read(&mgr->has_leader) == 0); /* competition leader. */ if (catomic_compare_set(&mgr->has_leader, 0, 1)) { /* change own to leader. */ cthread_info_change_to_header(cinfo); thread_pool_debuglog("func:[%s][change to leader] task thread id:%d, " "activity num:%d, exit num:%d, has_leader:%d", __FUNCTION__, cthread_info_get_id(cinfo), (int)catomic_read(&mgr->activity_num), (int)catomic_read(&mgr->exit_num), (int)catomic_read(&mgr->has_leader)); continue; } assert(false && "is last activity thread, but not change to leader, error!"); log_error("is last activity thread, but not change to leader, error!"); } /* suspend. */ cthread_info_state_to_suspend(cinfo); catomic_dec(&mgr->activity_num); catomic_inc(&mgr->suspend_num); thread_pool_debuglog("func:[%s][suspend thread] thread id:%d, activity num:%d, " "exit num:%d, has_leader:%d", __FUNCTION__, cthread_info_get_id(cinfo), (int)catomic_read(&mgr->activity_num), (int)catomic_read(&mgr->exit_num), (int)catomic_read(&mgr->has_leader)); /* real do suspend. */ cthread_suspend(cthread_info_get_handle_ptr(cinfo)); /* from resume. */ cthread_info_state_to_activity(cinfo); catomic_dec(&mgr->suspend_num); catomic_inc(&mgr->activity_num); thread_pool_debuglog("func:[%s][thread for resume] thread id:%d, activity num:%d, " "exit num:%d, has_leader:%d", __FUNCTION__, cthread_info_get_id(cinfo), (int)catomic_read(&mgr->activity_num), (int)catomic_read(&mgr->exit_num), (int)catomic_read(&mgr->has_leader)); } } cthread_pool_do_thread_exit(cinfo); }