static void CHANNEL_Send( DaoProcess *proc, DaoValue *par[], int N ) { DaoValue *data; DaoFuture *future = DaoProcess_GetInitFuture( proc ); DaoChannel *self = (DaoChannel*) par[0]; float timeout = par[2]->xFloat.value; DaoProcess_PutBoolean( proc, 1 ); if( self->cap <= 0 ){ DaoProcess_RaiseError( proc, "Param", "channel is closed" ); return; } data = DaoValue_DeepCopy( par[1] ); if( data == NULL ){ DaoProcess_RaiseError( proc, "Param", "invalid data for the channel" ); return; } //printf( "CHANNEL_Send: %p\n", event ); DaoChannel_Send( self, data ); if( self->buffer->size >= self->cap ){ DaoTaskEvent *event = DaoCallServer_MakeEvent(); DaoTaskEvent_Init( event, DAO_EVENT_WAIT_SENDING, DAO_EVENT_WAIT, future, self ); proc->status = DAO_PROCESS_SUSPENDED; proc->pauseType = DAO_PAUSE_CHANNEL_SEND; DaoCallServer_AddTimedWait( proc, event, timeout ); } }
void DaoMT_Select( DaoProcess *proc, DaoValue *par[], int n ) { DNode *it; DaoTaskEvent *event = NULL; DaoFuture *future = DaoProcess_GetInitFuture( proc ); DaoMap *selects = (DaoMap*) par[0]; float timeout = par[1]->xFloat.value; for(it=DaoMap_First(selects); it; it=DaoMap_Next(selects,it)){ DaoValue *value = it->key.pValue; int isfut = DaoValue_CheckCtype( value, dao_type_future ); int ischan = DaoValue_CheckCtype( value, dao_type_channel ); if( isfut == 0 && ischan == 0 ){ DaoProcess_RaiseError( proc, "Param", "invalid type selection" ); return; } } event = DaoCallServer_MakeEvent(); DaoTaskEvent_Init( event, DAO_EVENT_WAIT_SELECT, DAO_EVENT_WAIT, future, NULL ); GC_Assign( & event->selects, selects ); proc->status = DAO_PROCESS_SUSPENDED; proc->pauseType = DAO_PAUSE_CHANFUT_SELECT; DaoCallServer_AddTimedWait( proc, event, timeout ); /* Message may have been sent before this call: */ DMutex_Lock( & daoCallServer->mutex ); DaoChannel_ActivateEvent( NULL, DAO_EVENT_WAIT_SELECT ); DCondVar_Signal( & daoCallServer->condv ); DMutex_Unlock( & daoCallServer->mutex ); }
static void CHANNEL_Send( DaoProcess *proc, DaoValue *par[], int N ) { DaoValue *data; DaoFuture *future = DaoProcess_GetInitFuture( proc ); DaoChannel *self = (DaoChannel*) par[0]; float timeout = par[2]->xFloat.value; if( DaoProcess_CheckCB( proc, "cannot send/block inside code section method" ) ) return; if( self->cap <= 0 ){ DaoProcess_RaiseException( proc, DAO_ERROR_PARAM, "channel is closed" ); return; } data = DaoValue_DeepCopy( par[1] ); if( data == NULL ){ DaoProcess_RaiseException( proc, DAO_ERROR_PARAM, "invalid data for the channel" ); return; } //printf( "CHANNEL_Send: %p\n", event ); DMutex_Lock( & daoCallServer->mutex ); DArray_Append( self->buffer, data ); DaoChannel_ActivateEvent( self, DAO_EVENT_WAIT_RECEIVING ); DaoChannel_ActivateEvent( self, DAO_EVENT_WAIT_SELECT ); DCondVar_Signal( & daoCallServer->condv ); DMutex_Unlock( & daoCallServer->mutex ); if( self->buffer->size >= self->cap ){ DaoTaskEvent *event = DaoCallServer_MakeEvent(); DaoTaskEvent_Init( event, DAO_EVENT_WAIT_SENDING, DAO_EVENT_WAIT, future, self ); proc->status = DAO_PROCESS_SUSPENDED; proc->pauseType = DAO_PAUSE_CHANNEL_SEND; DaoCallServer_AddTimedWait( proc, event, timeout ); } }
void CHANNEL_Select( DaoProcess *proc, DaoValue *par[], int n ) { DaoTaskEvent *event = NULL; DaoFuture *future = DaoProcess_GetInitFuture( proc ); DaoList *channels = (DaoList*) par[0]; float timeout = par[1]->xFloat.value; daoint i, size = DaoList_Size( channels ); for(i=0; i<size; ++i){ DaoValue *value = DaoList_GetItem( channels, i ); if( DaoValue_CheckCtype( value, dao_type_channel ) == 0 ){ DaoProcess_RaiseException( proc, DAO_ERROR_PARAM, "invalid type selection" ); return; } } event = DaoCallServer_MakeEvent(); DaoTaskEvent_Init( event, DAO_EVENT_WAIT_SELECT, DAO_EVENT_WAIT, future, NULL ); event->channels = DArray_Copy( & channels->items ); proc->status = DAO_PROCESS_SUSPENDED; proc->pauseType = DAO_PAUSE_CHANFUT_SELECT; DaoCallServer_AddTimedWait( proc, event, timeout ); /* Message may have been sent before this call: */ DMutex_Lock( & daoCallServer->mutex ); DaoChannel_ActivateEvent( NULL, DAO_EVENT_WAIT_SELECT ); DCondVar_Signal( & daoCallServer->condv ); DMutex_Unlock( & daoCallServer->mutex ); }
void DaoCallServer_AddCall( DaoProcess *caller ) { DaoProcess *callee = DaoVmSpace_AcquireProcess( caller->vmSpace ); DaoStackFrame *frame = caller->topFrame; DaoTaskEvent *event = DaoCallServer_MakeEvent(); 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] ); DaoProcess_PushRoutine( callee, caller->topFrame->routine, future->actor ); 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_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_AddWait( DaoProcess *wait, DaoFuture *pre, double timeout ) { DaoFuture *future; DaoTaskEvent *event; DaoCallServer *server; if( daoCallServer == NULL ) DaoCallServer_Init( mainVmSpace ); server = daoCallServer; future = DaoProcess_GetInitFuture( wait ); GC_ShiftRC( pre, future->precond ); 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 ); }
static void CHANNEL_Receive( DaoProcess *proc, DaoValue *par[], int N ) { DaoTaskEvent *event = NULL; DaoFuture *future = DaoProcess_GetInitFuture( proc ); DaoChannel *self = (DaoChannel*) par[0]; float timeout = par[1]->xFloat.value; event = DaoCallServer_MakeEvent(); DaoTaskEvent_Init( event, DAO_EVENT_WAIT_RECEIVING, DAO_EVENT_WAIT, future, self ); proc->status = DAO_PROCESS_SUSPENDED; proc->pauseType = DAO_PAUSE_CHANNEL_RECEIVE; DaoCallServer_AddTimedWait( proc, event, timeout ); /* Message may have been sent before this call: */ if( self->buffer->size ){ DMutex_Lock( & daoCallServer->mutex ); DaoChannel_ActivateEvent( self, DAO_EVENT_WAIT_RECEIVING ); DCondVar_Signal( & daoCallServer->condv ); DMutex_Unlock( & daoCallServer->mutex ); } }
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 }