Exemple #1
0
/* remove send event. */
void eventmgr_remove_socket_send_event(struct socketer *self) {
	struct kevent ev;

	assert(catomic_read(&self->sendlock) == 1);
	if (catomic_read(&self->sendlock) != 1) {
		log_error("%x socket recvlock:%d, sendlock:%d, fd:%d, ref:%d, thread_id:%d", 
				self, (int)catomic_read(&self->recvlock), (int)catomic_read(&self->sendlock), 
				self->sockfd, (int)catomic_read(&self->ref), cthread_self_id());
	}

	EV_SET(&ev, self->sockfd, EVFILT_WRITE, EV_DISABLE, 0, 0, self);
	if (kevent(s_mgr->kqueue_fd, &ev, 1, NULL, 0, NULL) == -1) {
		/*log_error("kqueue, remove send event from kqueue set on fd %d error!, errno:%d", self->sockfd, NET_GetLastError());*/
		socketer_close(self);
	}
	debuglog("remove send event from eventmgr.");
}
Exemple #2
0
/*
 * create a thread pool, that has thread_num threads.
 * @param {int} thread_num			thread num.
 * @param {void *} udata			user data pointer.
 * @param {function} func_leader	leader function, need the one param.
 *										return need to resume threads num, if less than 0, then exit.
 * @param {function} func_task		task function, need the one param.
 *										return 0 then not task to do. or else is to exit.
 */
struct cthread_pool *cthread_pool_create(int thread_num, void *udata, 
		int (*func_leader)(void *), int (*func_task)(void *)) {

	struct cthread_pool *self;
	assert(thread_num > 0 && func_leader != NULL && func_task != NULL);
	if (thread_num <= 0 || !func_leader || !func_task)
		return NULL;

	self = (struct cthread_pool *)malloc(sizeof(struct cthread_pool));
	if (!self)
		return NULL;

	cthread_list_init(&self->all_list);
	catomic_set(&self->run, 0);
	catomic_set(&self->resume_num, 0);
	catomic_set(&self->suspend_num, 0);
	catomic_set(&self->activity_num, 0);
	catomic_set(&self->need_exit_num, 0);
	catomic_set(&self->exit_num, 0);
	catomic_set(&self->has_leader, 0);

	self->thread_num = thread_num;
	self->udata = udata;
	self->func_leader = func_leader;
	self->func_task = func_task;

	while (thread_num > 0) {
		struct cthread_info *cinfo = cthread_info_create(self, th_pro_func);
		if (!cinfo)
			goto err_do;

		cthread_list_push_back(&self->all_list, cinfo);

		thread_num--;
	}

	catomic_set(&self->run, 1);

	thread_pool_debuglog("func[%s] mgr:%p", __FUNCTION__, self);

	/* resume all. */
	cthread_pool_resume_some_thread(self, self->thread_num, NULL);

	/* wait thread run. */
	while (catomic_read(&self->need_exit_num) != (int64)self->thread_num) {
		cthread_self_sleep(0);
	}

	return self;

err_do:
	if (self) {
		cthread_list_destroy(&self->all_list);
		free(self);
	}

	return NULL;
}
Exemple #3
0
void cthread_pool_release(struct cthread_pool *self) {
	if (!self)
		return;

	thread_pool_debuglog("func[%s] mgr:%p", __FUNCTION__, self);

	catomic_set(&self->run, 0);

	while (catomic_read(&self->exit_num) != catomic_read(&self->need_exit_num)) {

		cthread_pool_resume_some_thread(self, self->thread_num, NULL);

		/* sleep 1 ms. */
		cthread_self_sleep(1);
	}

	assert(catomic_read(&self->suspend_num) == 0);
	assert(catomic_read(&self->activity_num) == 0);
	assert(catomic_read(&self->need_exit_num) == catomic_read(&self->exit_num));
	assert(catomic_read(&self->need_exit_num) <= self->thread_num);

	cthread_list_destroy(&self->all_list);

	free(self);
}
Exemple #4
0
static void cthread_pool_do_thread_exit(struct cthread_info *th) {
	catomic_dec(&th->mgr->activity_num);

	if (cthread_info_is_header(th)) {

		thread_pool_debuglog("func:[%s][leader as exit] thread id:%d", 
				__FUNCTION__, cthread_info_get_id(th));

		cthread_pool_resume_some_thread(th->mgr, th->mgr->thread_num, NULL);
	}

	cthread_info_state_to_exit(th);
	catomic_inc(&th->mgr->exit_num);

	thread_pool_debuglog("func:[%s] thread id:%d, activity num:%d, exit num:%d, has_leader:%d",
			__FUNCTION__, cthread_info_get_id(th),
			(int)catomic_read(&th->mgr->activity_num), (int)catomic_read(&th->mgr->exit_num), 
			(int)catomic_read(&th->mgr->has_leader));
}
Exemple #5
0
/* set send event. */
void eventmgr_setup_socket_send_event(struct socketer *self) {
	struct kevent ev;

	assert(catomic_read(&self->sendlock) == 1);
	if (catomic_read(&self->sendlock) != 1) {
		log_error("%x socket recvlock:%d, sendlock:%d, fd:%d, ref:%d, thread_id:%d", 
				self, (int)catomic_read(&self->recvlock), (int)catomic_read(&self->sendlock), 
				self->sockfd, (int)catomic_read(&self->ref), cthread_self_id());
	}

	EV_SET(&ev, self->sockfd, EVFILT_WRITE, EV_ENABLE, 0, 0, self);
	if (kevent(s_mgr->kqueue_fd, &ev, 1, NULL, 0, NULL) == -1) {
		/*log_error("kqueue, setup send event to kqueue set on fd %d error!, errno:%d", self->sockfd, NET_GetLastError());*/
		socketer_close(self);
		if (catomic_dec(&self->ref) < 1) {
			log_error("%x socket recvlock:%d, sendlock:%d, fd:%d, ref:%d, thread_id:%d, connect:%d, deleted:%d", 
					self, (int)catomic_read(&self->recvlock), (int)catomic_read(&self->sendlock), self->sockfd, 
					(int)catomic_read(&self->ref), cthread_self_id(), self->connected, self->deleted);
		}
	}
	debuglog("setup send event to eventmgr.");
}
Exemple #6
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);
}