void CoroutineManager::runCorEvent(VarisEvent* event){ size_t workerNumber = event->getCoroutine()->getId(); Coroutine* coroutine = &(coroutines_[workerNumber]); lastCoroutine_ = curCoroutine_ ; curCoroutine_ = coroutine->getId(); event->callback(); }
int64_t CoroutinePool::go(Coroutine::PFN_COROUTINE_TASK pfn, Object* arg, int64_t& cr_id){ if(m_cleaning){ WARN("coroutine pool go failed, cleaning"); return -ErrorCode::SYSTEM_ERROR; } if(!pfn){ return -ErrorCode::INVALID_ARG; } // prepare Coroutine* cr =_prepare_coroutine(pfn, arg); const int64_t result =_resume(cr, 0, 0); if(result == Coroutine::STATUS_WAITING){ cr_id =cr->getId(); } return result; }
bool CoroutineService::sleep(const int64_t secs){ Coroutine* cr =Coroutine::Running(); if(!cr){ WARN("service %s(%lld) fail to sleep, in main thread", name(), (long long)m_id); return false; } if(m_processing_command){ WARN("service %s(%lld) fail to sleep, in processing command", name(), (long long)m_id); return false; } const int64_t cr_id =cr->getId(); m_sleeper_table->set(cr_id, SafeNew<Int64>(DateTime::Now() + secs)); ASSERT(cr->yield(0, -1)); m_sleeper_table->remove(cr_id); return true; }
/** coroutine manager **/ void CoroutinePool::update(const int64_t now){ // process timeout if(m_active_coroutine_table && m_active_coroutine_table->size()>0){ // prepare Int64Array* ls =0; HashIterator* it =static_cast< HashIterator* >(m_active_coroutine_table->iterator()); while(it->next()){ Coroutine* cr =static_cast< Coroutine* >(it->getValue()); if(cr->isWaitingAndExpire(now)){ if(!ls){ ls =SafeNew<Int64Array>(); } ls->push_back(cr->getId()); } } // resume if(ls && ls->size()>0){ const int64_t n =ls->size(); for(int64_t i=0; i<n; ++i){ resume(ls->get(i), SafeNew<Error>(ErrorCode::TIMEOUT), 0); } } } }
void CoroutineManager::runCoroutine(size_t workerNumber){ Coroutine* coroutine = &(coroutines_[workerNumber]); lastCoroutine_ = curCoroutine_ ; curCoroutine_ = coroutine->getId(); coroutine->work(); }
/** rpc **/ Object* CoroutineService::rpc(const int64_t who, const int64_t to, const int64_t cmd, const int64_t res_proto_grp_id, Object* req_param){ if(to == getId()){ ERROR("service %s(%lld) can't request self", name(), (long long)m_id); return 0; } // prepare Coroutine* cr =Coroutine::Running(); if(!cr){ WARN("service %s(%lld) %lld fail to rpc to %lld, in main thread", name(), (long long)m_id, (long long)who, (long long)to); return 0; } ASSERT(cr->canYield()); const int64_t cr_id =cr->getId(); // set rpc info CoroutineRpcInfo* rpc_info =SafeNew<CoroutineRpcInfo>(res_proto_grp_id, cr_id); if(!set_rpc(rpc_info)){ return 0; } const int64_t rpc_id =rpc_info->getId(); // prepare packet PACKET packet; packet.from =getId(); packet.to =to; packet.who =who; packet.sn =rpc_id; packet.command =cmd; packet.option =0; // request if(!DispatcherManager::RequestByObject(this, packet, req_param)){ WARN("service %s(%lld) %lld fail to rpc to %lld, service not ready", name(), (long long)m_id, (long long)who, (long long)to); return 0; } rpc_info->set(rpc_id, this); ENSURE(cr->yield(0, rpc_id)); // process respond if(Command* respond =dynamic_cast< Command* >(cr->getResumeParam())){ // prepare const PACKET res_packet =respond->getPacket(); if(res_packet.sn != static_cast<uint64_t>(rpc_id)){ WARN("service %s(%lld) %lld fail to rpc to %lld, rpc id mismatch", name(), (long long)m_id, (long long)who, (long long)to); return 0; } // body is object pointer if(res_packet.option & OPT_BODY_IS_OBJECT_POINTER){ return respond; } // body is protocol if(res_proto_grp_id>0){ Bytes* res_bs =respond->getBody(); const int64_t res_cmd =static_cast<int64_t>(res_packet.command); const int64_t group_id =res_proto_grp_id; const int64_t protocol_id =res_cmd; ProtocolBase* res_proto = ProtocolManager::CreateProtocol(group_id, protocol_id); if(!res_proto){ ERROR("service %s(%lld) %lld fail to rpc to %lld, create protocol group %lld id %lld error", name(), (long long)m_id, (long long)who, (long long)to, (long long)group_id, (long long)protocol_id); return 0; } if(!res_proto->fromBytes(res_bs)){ ERROR("service %s(%lld) %lld fail to rpc to %lld, unmarshal protocol name %s group %lld id %lld error", name(), (long long)m_id, (long long)who, (long long)to, res_proto->name(), (long long)group_id, (long long)protocol_id); return 0; } respond->setRequest(res_proto); } // body is not special return respond; } else{ return cr->getResumeParam(); } }