static void DaoCallServer_AddThread( DThreadTask func, void *param ) { DaoCallThread *calth; DaoCallServer_TryInit( mainVmSpace ); calth = DaoCallThread_New( func, param ); DMutex_Lock( & daoCallServer->mutex ); daoCallServer->total += 1; DArray_Append( daoCallServer->threads, calth ); DMutex_Unlock( & daoCallServer->mutex ); DThread_Start( & calth->thread, (DThreadTask) DaoCallThread_Run, calth ); }
void DaoCallServer_AddWait( DaoProcess *wait, DaoFuture *pre, double timeout ) { DaoTaskEvent *event; DaoCallServer *server = DaoCallServer_TryInit( mainVmSpace );; DaoFuture *future = DaoProcess_GetInitFuture( wait ); GC_Assign( & future->precond, pre ); future->state = DAO_CALL_PAUSED; event = DaoCallServer_MakeEvent(); DaoTaskEvent_Init( event, DAO_EVENT_WAIT_TASKLET, DAO_EVENT_WAIT, future, NULL ); DaoCallServer_AddTimedWait( wait, event, timeout ); }
void DaoCallServer_AddThread( DThreadTask func, void *param ) { DaoCallThread *calth; DaoCallServer_TryInit( mainVmSpace ); calth = DaoCallThread_New( func, param ); DMutex_Lock( & daoCallServer->mutex ); daoCallServer->total += 1; DList_Append( daoCallServer->threads, calth ); DMutex_Unlock( & daoCallServer->mutex ); if( DThread_Start( & calth->thread, (DThreadTask) DaoCallThread_Run, calth ) == 0 ){ if( func != NULL || daoCallServer->total == 0 ){ dao_abort( "failed to create a task thread" ); } } }
static void CHANNEL_New( DaoProcess *proc, DaoValue *par[], int N ) { DaoType *retype = DaoProcess_GetReturnType( proc ); DaoChannel *self = DaoChannel_New( retype, 0 ); CHANNEL_SetCap( self, par[0], proc ); if( DaoType_CheckPrimitiveType( retype->nested->items.pType[0] ) == 0 ){ DString *s = DString_New(); DString_AppendChars( s, "data type " ); DString_Append( s, retype->nested->items.pType[0]->name ); DString_AppendChars( s, " is not supported for channel" ); DaoProcess_RaiseError( proc, NULL, s->chars ); DString_Delete( s ); } DaoProcess_PutValue( proc, (DaoValue*) self ); DaoCallServer_TryInit( mainVmSpace ); }
void DaoCallServer_AddTask( DThreadTask func, void *param, int now ) { int scheduled = 0; DaoCallServer *server = DaoCallServer_TryInit( mainVmSpace ); DMutex_Lock( & server->mutex ); if( server->idle > server->parameters->size || now == 0 ){ scheduled = 1; DList_Append( server->functions, func ); DList_Append( server->parameters, param ); DMap_Insert( server->pending, param, NULL ); DCondVar_Signal( & server->condv ); } DMutex_Unlock( & server->mutex ); if( scheduled ){ if( now == 0 ) DaoCallServer_TryAddThread( NULL, NULL, server->parameters->size ); }else{ DaoCallServer_AddThread( func, param ); } }
void DaoCallServer_AddCall( DaoProcess *caller ) { DaoTaskEvent *event; DaoProcess *callee = DaoVmSpace_AcquireProcess( caller->vmSpace ); DaoStackFrame *frame = caller->topFrame; DaoType *type = (DaoType*) frame->routine->routType->aux; DaoFuture *future = DaoFuture_New( type, 1 ); DaoValue **params = caller->stackValues + caller->topFrame->stackBase; int i, count = caller->topFrame->parCount; future->state = DAO_CALL_PAUSED; future->actor = caller->topFrame->object; GC_IncRC( future->actor ); GC_ShiftRC( future, callee->future ); callee->future = future; future->process = callee; GC_IncRC( future->process ); callee->parCount = count; for(i=0; i<count; ++i) DaoValue_Copy( params[i], & callee->paramValues[i] ); if( caller->topFrame->routine->body ){ DaoProcess_PushRoutine( callee, caller->topFrame->routine, future->actor ); }else{ DaoProcess_PushFunction( callee, caller->topFrame->routine ); } DaoCallServer_TryInit( mainVmSpace );; event = DaoCallServer_MakeEvent(); DaoTaskEvent_Init( event, DAO_EVENT_RESUME_TASKLET, DAO_EVENT_RESUME, future, NULL ); DaoProcess_PopFrame( caller ); DaoProcess_PutValue( caller, (DaoValue*) future ); DaoCallServer_Add( event ); }
void DaoCallServer_AddCall( DaoProcess *caller ) { DaoFuture *future; DaoTaskEvent *event; DaoProcess *callee = DaoVmSpace_AcquireProcess( caller->vmSpace ); DaoStackFrame *frame = caller->topFrame; DaoRoutine *routine = frame->routine; DaoType *type = (DaoType*) routine->routType->aux; DaoValue **params = caller->stackValues + caller->topFrame->stackBase; int i, count = caller->topFrame->parCount; if( caller->activeCode->b & DAO_CALL_BLOCK ){ DaoValue **calleeValues, **callerValues = caller->activeValues; DaoStackFrame *sectFrame = DaoProcess_FindSectionFrame( caller ); DaoStackFrame *callerFrame = caller->topFrame->prev; DaoVmCode *vmc, *end, *sect; if( sectFrame != callerFrame ){ DaoVmSpace_ReleaseProcess( caller->vmSpace, callee ); DaoProcess_RaiseError( caller, NULL, "Invalid code section" ); return; } if( routine->body ){ DaoProcess_PushRoutine( callee, callerFrame->routine, callerFrame->object ); callerValues = caller->stackValues + callerFrame->stackBase; }else{ DaoProcess_PushRoutine( callee, caller->activeRoutine, caller->activeObject ); } DaoProcess_SetActiveFrame( callee, callee->topFrame ); calleeValues = callee->stackValues + callee->topFrame->stackBase; callee->activeCode = caller->activeCode; vmc = callerFrame->routine->body->vmCodes->data.codes + callerFrame->entry; end = callerFrame->routine->body->vmCodes->data.codes + vmc->b; sect = vmc + 1; for(vmc=sect; vmc!=end; vmc++){ int i = -1, code = vmc->code; if( code == DVM_GETVH || (code >= DVM_GETVH_I && code <= DVM_GETVH_C) ){ i = vmc->b; }else if( code == DVM_SETVH || (code >= DVM_SETVH_II && code <= DVM_SETVH_CC) ){ i = vmc->b; } if( i >= 0 ) DaoValue_Move( callerValues[i], & calleeValues[i], NULL ); } } future = DaoFuture_New( type, 1 ); future->state = DAO_CALL_PAUSED; future->actor = caller->topFrame->object; GC_IncRC( future->actor ); GC_Assign( & future->process, callee ); GC_Assign( & callee->future, future ); callee->parCount = count; /* Use routine->parCount instead of caller->topFrame->parCount, for default parameters: */ for(i=0; i<routine->parCount; ++i) DaoValue_Copy( params[i], & callee->paramValues[i] ); if( routine->body ){ DaoProcess_PushRoutine( callee, routine, future->actor ); }else{ DaoProcess_PushFunction( callee, routine ); callee->activeNamespace = caller->activeNamespace; } if( caller->activeCode->b & DAO_CALL_BLOCK ){ callee->topFrame->host = callee->topFrame; callee->topFrame->retmode = DVM_RET_PROCESS; callee->topFrame->returning = 0; } #ifdef DAO_WITH_CONCURRENT DaoCallServer_TryInit( mainVmSpace ); event = DaoCallServer_MakeEvent(); DaoTaskEvent_Init( event, DAO_EVENT_RESUME_TASKLET, DAO_EVENT_RESUME, future, NULL ); DaoProcess_PopFrame( caller ); DaoProcess_PutValue( caller, (DaoValue*) future ); DaoCallServer_Add( event ); #else DaoProcess_PopFrame( caller ); DaoProcess_PutValue( caller, (DaoValue*) future ); DaoProcess_InterceptReturnValue( callee ); DaoProcess_Execute( callee ); DaoProcess_ReturnFutureValue( callee, future ); DaoVmSpace_ReleaseProcess( caller->vmSpace, callee ); #endif }
int DaoCallServer_GetThreadCount() { DaoCallServer_TryInit( mainVmSpace ); return daoCallServer->total; }