message tasklet_service::recv(tasklet& recver) { if(_stop) { throw stop_exception(); } bool switched = false; while (_channel_manager.empty(recver._channel)) { park(recver); if (empty_runnables()) { switch_tasklet(recver); } else { switch_tasklet(recver, pop_runnable()); } switched = true; } if (!switched) { yield(recver); } return _channel_manager.fetch(recver._channel); }
void tasklet_service::before_start_tasklet(tasklet& tasklet_) { if(_stop) { throw stop_exception(); } }
message tasklet_service::recv(tasklet& recver, double timeout) { if(_stop) { throw stop_exception(); } if (timeout == infinity) { return recv(recver); } bool switched = false; unsigned long long wake_ = now()+(int)(timeout*10); while (_channel_manager.empty(recver._channel)) { recver._state = timeout_waitting; recver._wake = wake_; _sleepers.insert(&recver); if (empty_runnables()) { switch_tasklet(recver); } else { switch_tasklet(recver, pop_runnable()); } switched = true; } if (!switched) { yield(recver); } return _channel_manager.fetch(recver._channel); }
void simple_socket_stoppable::wait_for_read () { if (fd_to_monitor == INVALID_SOCKET) return; fd_set select_fds; FD_ZERO(&select_fds); FD_SET(sock, &select_fds); FD_SET(fd_to_monitor, &select_fds); timeval timeout_copy = *timeout; // For Linux timeval* select_tm = (timeout_action == timeout_act::NO_TIMEOUT) ? NULL : &timeout_copy; int selcode = select(((fd_to_monitor > sock) ? fd_to_monitor : sock), &select_fds, NULL, NULL, select_tm); if (selcode == SOCKET_ERROR) throw other_error("select() error in stoppable socket"); if (selcode) { if (FD_ISSET(sock, &select_fds)) return; else throw stop_exception(context, fd_to_monitor); } else { if (timeout_action == timeout_act::RAISE_STOP) throw stop_exception(context, fd_to_monitor); else throw io_error(io_error::READ); } }
void tasklet_service::send(tasklet& target, tasklet& sender, const message& msg) { if(_stop) { throw stop_exception(); } _channel_manager.dispatch(target._channel, msg); yield(sender); }
void tasklet_service::yield(tasklet& tasklet_) { if(_stop) { throw stop_exception(); } if (empty_runnables()) { return; } push_runnable(tasklet_); assert(!empty_runnables()); tasklet& next = pop_runnable(); switch_tasklet(tasklet_, next); }
void threadlet::loop() { if (_plast_finished_tasklet != NULL) { delete _plast_finished_tasklet; _plast_finished_tasklet = NULL; } threadlet_lock lock(this); _pcurrent_tasklet = &_ptasklet_service->pop_tasklet(); if (_stop) { lock.unlock(); assert(_pcurrent_tasklet != NULL); delete _pcurrent_tasklet; throw stop_exception(); } switch_tasklet(*_pcurrent_tasklet); }
void tasklet_service::sleep(tasklet& tasklet_, double timeout) { if(_stop) { throw stop_exception(); } tasklet_._state = sleeping; tasklet_._wake = now()+(int)(timeout*10); _sleepers.insert(&tasklet_); if (empty_runnables()) { switch_tasklet(tasklet_); } else { tasklet& next_tasklet = pop_runnable(); switch_tasklet(tasklet_, next_tasklet); } }
tasklet& tasklet_service::pop_tasklet() { tasklet* ptasklet = NULL; while (!ptasklet && !_stop) { if (empty_runnables()) { //这里本来可能引发因为_condition.wait释放_mutex导致的线程安全问题 //但是很幸运的是,pop_tasklet只被threadlet::loop调用,这样就正好不会引发线程安全问题了 _condition.wait(); } else { assert(!empty_runnables()); ptasklet = &pop_runnable(); } } if (_stop && !ptasklet) { throw stop_exception(); } return *ptasklet; }