Beispiel #1
0
void CoroutineManager::runCorEvent(VarisEvent* event){
	size_t workerNumber = event->getCoroutine()->getId();
	Coroutine* coroutine = &(coroutines_[workerNumber]);
	lastCoroutine_ = curCoroutine_ ;
	curCoroutine_ = coroutine->getId();
	event->callback();
}
Beispiel #2
0
bool CoroutineManager::doWork(VarisEvent* event){
		Coroutine* cor;
		if((cor = event->getCoroutine())!=NULL &&( event->getListenEventType()&T_COROUTINE)){
			cor->setStatus(BUSY);
			runCorEvent(event);
			return true;
		}
		//no coroutine free
		if(freeCoroutine_.empty()){
			return false;
		}
	if(!(event->getListenEventType()&T_COROUTINE)){
			int tmpCoroutine = freeCoroutine_.top();
			freeCoroutine_.pop();
			ucontext_t* context = coroutines_[tmpCoroutine].getContext();
			context->uc_link = coroutines_[0].getContext();
			Coroutine* coroutine = &(coroutines_[tmpCoroutine]);
			coroutine->setStatus(READY);
			event->setCoroutine(coroutine);
			makecontext(context,(corfunc)(VarisEvent::handle),1,event);
			runCoroutine(tmpCoroutine);
			return true;
	}
	return false;

}
Beispiel #3
0
void XsimCore::startSim() {

    while (!futureEvents.isEmpty()) {
        TimeSliceEvent* event = futureEvents.getNextEvent();
        time = event->getTime();
        std::cout << "Time: " << time << std::endl;

        while (!event->isEmpty()) {
            // Execute coroutines
            while (!event->isCoroutinesEmpty()) {
                Coroutine* coroutine = event->popNextCoroutine();
                // Execute coroutine if it is not already running.
                if (coroutine->isFinished()) {
                    coroutine->reset();
                }
                coroutine->start();
            }

            // Execute functions
            while (!event->isFunctionsEmpty()) {
                FunctionPtr function = event->popNextFunction();
                // Execute function
                function(functionUserData[function]);
            }
        }

        futureEvents.removeFirstEvent();
    }

}
Beispiel #4
0
//notice
void CoroutineManager::onCoroutineFinished(CoroutineManager* th){
	while(true){
		Coroutine cor = th->coroutines_[th->curCoroutine_];
		cor.setStatus(FREE);
		th->freeCoroutine_.push(th->curCoroutine_);
		th->curCoroutine_ = 0;
		th->runCoroutine(1);
	}
}
Beispiel #5
0
static void CALLBACK coroutine_trampoline(void *co_)
{
    Coroutine *co = co_;

    while (true) {
        co->entry(co->entry_arg);
        qemu_coroutine_switch(co, co->caller, COROUTINE_TERMINATE);
    }
}
Beispiel #6
0
void Detach() {
    Coroutine *Next = Current->Caller;
    if (Next)  
        Current->Caller = Next->Callee = 0;
    else {
        Next = &Main; 
        while (Next->Callee)
            Next = Next->Callee;
    }
    Next->Enter(); 
}
Beispiel #7
0
// virtual
void Subroutine::Invoke( string& funcName ){
	assert( this->m_freeList.size() > 0 );
	Coroutine* c = this->m_freeList.back();
	m_freeList.pop_back();
	assert( c );
	this->m_activeList.push_back( c );
	c->executeFunction( funcName );
	if( c->m_state == STATE_IDLE ){
		this->m_activeList.remove( c );
		this->m_freeList.push_back( c );
	}
}
Beispiel #8
0
void tst_basic::smallStack()
{
    using namespace StackTests;

    Coroutine *c = Coroutine::build(&simpleCoroutine);
    c->createStack(1000);
    counter = 0;
    QCOMPARE(c->cont(), true);
    QCOMPARE(counter, 1);
    QCOMPARE(c->cont(), true);
    QCOMPARE(counter, 2);
    delete c;
}
Beispiel #9
0
// virtual
void Subroutine::OnUpdate(){
	list<Coroutine*>::iterator iter = this->m_activeList.begin();
	while( iter != this->m_activeList.end() ){
		Coroutine* c = *iter;
		c->execute();
		if( c->m_state == STATE_IDLE ){
			iter++;
			this->m_activeList.remove( c );
			this->m_freeList.push_back( c );
			continue;
		}
		iter++;
	}
}
Beispiel #10
0
	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;
	}
Beispiel #11
0
	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;
	}
Beispiel #12
0
	/** helper **/
	Coroutine* CoroutinePool::_prepare_coroutine(Coroutine::PFN_COROUTINE_TASK pfn, Object* arg){
		// prepare coroutine
		GENERATE_ID(m_coroutine_id);
		Coroutine* cr =0;
		if(m_idle_coroutine_list->size() > 0){
			cr =dynamic_cast< Coroutine* >(m_idle_coroutine_list->back());
			m_active_coroutine_table->set(m_coroutine_id, cr);
			m_idle_coroutine_list->pop_back();
		}
		else{
			cr =SafeNew<Coroutine>(this);
			m_active_coroutine_table->set(m_coroutine_id, cr);
		}
		// set status
		cr->setId(m_coroutine_id);
		cr->setTask(pfn, arg);
		return cr;
	}
Beispiel #13
0
void ServletManager::execute(unsigned servlet_id, unsigned seq, unsigned size, Peer *peer) noexcept {
    if (servlet_id == GX_KEEPALIVE_SERVLET) {
        if (seq || size) {
            peer->close();
            return;
        }
        return;
    }

    auto it = _map.find(servlet_id);
    if (it == _map.end()) {
        log_debug("servlet 0x%x not registered.", servlet_id);
        peer->close();
        return;
    }

    ServletBase *servlet = it->second;

    Coroutine *co;
    bool use_co = servlet->use_coroutine();
    if (use_co) {
        co = Coroutine::spawn(routine, peer);
    }
    else {
        co = Coroutine::self();
    }

    if (!co) {
        log_debug("no coroutine available.");
        peer->input().read(nullptr, size);
        return;
    }

    co->context()->_servlet = servlet;
    co->context()->_seq = seq;
    co->context()->_size = size;

    if (use_co) {
        co->resume();
    }
    else {
        routine(peer);
    }
}
static void coroutine_trampoline(int i0, int i1)
{
    union cc_arg arg;
    CoroutineUContext *self;
    Coroutine *co;

    arg.i[0] = i0;
    arg.i[1] = i1;
    self = arg.p;
    co = &self->base;

    /* Initialize longjmp environment and switch back the caller */
    if (!sigsetjmp(self->env, 0)) {
        siglongjmp(*(sigjmp_buf *)co->entry_arg, 1);
    }

    while (true) {
        co->entry(co->entry_arg);
        qemu_coroutine_switch(co, co->caller, COROUTINE_TERMINATE);
    }
}
Beispiel #15
0
static void readScript(Coroutine<const char*>& self)
{
    LineEditor* console = LineEditor::Get();
    console->Open();
    std::string line;
    do {
        line = console->Prompt("> ");
        if (line.empty())
            continue;
        self.yield(line.c_str());
    } while (true);
}
Beispiel #16
0
	void CoroutinePool::finalize(){
		m_cleaning =true;

		// clean idle list
		for(int64_t i=0; i<m_idle_coroutine_list->size(); ++i){
			Coroutine* cr =static_cast< Coroutine* >(m_idle_coroutine_list->get(i));
			cr->resume(SafeNew<Error>(ErrorCode::COROUTINE_CLEAN), 0);
			ASSERT(cr->getStatus() == Coroutine::STATUS_DEAD);
		}
		CLEAN_POINTER(m_idle_coroutine_list);

		// clean active table
		Hash* active_cr_tb =m_active_coroutine_table;
		m_active_coroutine_table =0;
		HashIterator* it =static_cast< HashIterator* >(active_cr_tb->iterator());
		while(it->next()){
			Coroutine* cr =static_cast< Coroutine* >(it->getValue());
			cr->resume(SafeNew<Error>(ErrorCode::COROUTINE_CLEAN), 0);
			ASSERT(cr->getStatus() == Coroutine::STATUS_DEAD);
		}
		CLEAN_POINTER(active_cr_tb);

		// super
		Super::finalize();
	}
Beispiel #17
0
	/** entry **/
	void Coroutine::_entry(){
		// prepare
		Coroutine* self =Running();
		ASSERT(self);
		self->retain();

		// loop
		while(1){
			// check break
			if(Error* err= dynamic_cast< Error* >(self->m_resume_param)){
				if(err->getCode() == ErrorCode::COROUTINE_CLEAN){
					break;
				}
			}
			// run task
			try{
				if(self->m_task){
					self->m_task(self->m_arg);
					self->m_task =0;
					CLEAN_POINTER(self->m_arg);
				}
			}
			catch(...){
				ERROR("coroutine exec task occurs exception, perhaps coroutine is cleaned");
				break;
			}
			// yield
			self->_yield(0, STATUS_IDLE);
		}

		// clean
		INFO("coroutine %lld exit", (long long)self->m_id);
		self->m_status =STATUS_DEAD;
		g_running =0;
		self->release();
	}
Beispiel #18
0
	/** 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);
				}
			}
		}
	}
Beispiel #19
0
PRIVATE void __sched(Coroutine coro) {

	long ret;
	void* para = regsw(coro->env, NULL);
MAIN_RUN:
	para = coro->main(coro, para);
	coro->state = CORO_END;
END_AGAIN:
	ret = (long)regsw(coro->env, para);
	switch(ret) {
		case CORO_PROMPT_RESET:
			para = regsw(coro->env, NULL);
			goto MAIN_RUN;
		default:
	/* can not resume coroutine whose state is C_END */
	/* this situation can be seen as a kind of error */
			para = NULL;
			goto END_AGAIN;
	}
}
Beispiel #20
0
void CoroutineManager::runCoroutine(size_t workerNumber){
	Coroutine* coroutine = &(coroutines_[workerNumber]);
	lastCoroutine_ = curCoroutine_ ;
	curCoroutine_ = coroutine->getId();
	coroutine->work();
}
Beispiel #21
0
void Coroutine::setupEntry()
{
  Coroutine *current = (Coroutine *)sys().getContextOfCoroutine(sys().activeCoroutine());
  current->entry();
}
Beispiel #22
0
	/** 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();
		}
	}