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 ); } }
static void DaoIO_Read( DaoProcess *proc, DaoValue *p[], int N ) { DaoStream *self = proc->stdioStream; DString *ds = DaoProcess_PutChars( proc, "" ); int ch, size, amount = -1; /* amount=-2: all; amount=-1: line; amount>=0: bytes; */ char buf[IO_BUF_SIZE]; if( self == NULL ) self = proc->vmSpace->stdioStream; if( N > 0 ){ self = (DaoStream*) p[0]; amount = -2; } if( DaoIO_CheckMode( self, proc, DAO_STREAM_READABLE ) == 0 ) return; if( N > 1 ){ if( p[1]->type == DAO_INTEGER ){ amount = p[1]->xInteger.value; if( amount < 0 ){ DaoProcess_RaiseError( proc, NULL, "cannot read negative amount!" ); return; } }else{ amount = - 1 - p[1]->xEnum.value; } } DString_Reset( ds, 0 ); self->Read( self, ds, amount ); if( self->mode & DAO_STREAM_AUTOCONV ) DString_ToUTF8( ds ); }
static void TEST_Assert( DaoProcess *proc, DaoValue* p[], int N ) { if ( !p[0]->xBoolean.value ){ DString *msg = p[1]->xString.value; DaoProcess_RaiseError( proc, "Test::Assert", msg->size? msg->chars : "assertion failed" ); } }
static void CHANNEL_SetCap( DaoChannel *self, DaoValue *value, DaoProcess *proc ) { self->cap = value->xInteger.value; if( self->cap > 0 ) return; self->cap = 1; DaoProcess_RaiseError( proc, "Param", "channel capacity must be greater than 0" ); }
static int DaoObject_DoSetField( DaoValue *self, DaoString *name, DaoValue *value, DaoProcess *proc ) { DaoObject *object = (DaoObject*) self; DaoObject *host = proc->activeObject; DaoClass *hostClass = host ? host->defClass : NULL; int ec = DaoObject_SetData( object, name->value, value, host ); if( ec != DAO_OK ){ DString *field = proc->string; DaoRoutine *rout; DString_SetChars( field, "." ); DString_Append( field, name->value ); DString_AppendChars( field, "=" ); rout = DaoClass_FindMethod( object->defClass, field->chars, hostClass ); if( rout != NULL ){ ec = DaoProcess_PushCall( proc, rout, self, & value, 1 ); }else{ DaoValue *args[2]; args[0] = (DaoValue*) name; args[1] = value; rout = DaoClass_FindMethod( object->defClass, ".=", hostClass ); if( rout == NULL ) return DAO_ERROR_FIELD_ABSENT; ec = DaoProcess_PushCall( proc, rout, self, args, 2 ); } if( rout == NULL ) return DAO_ERROR_FIELD_ABSENT; } if( ec ) DaoProcess_RaiseError( proc, daoExceptionNames[ec], name->value->chars ); return ec; }
static DaoValue* DaoObject_DoGetField( DaoValue *self, DaoString *name, DaoProcess *proc ) { DaoObject *object = (DaoObject*) self; DaoObject *host = proc->activeObject; DaoClass *hostClass = host ? host->defClass : NULL; DaoValue *value = NULL; int rc = DaoObject_GetData( object, name->value, & value, host ); if( rc ){ DaoRoutine *rout; DString *field = proc->string; DString_SetChars( field, "." ); DString_Append( field, name->value ); rout = DaoClass_FindMethod( object->defClass, field->chars, hostClass ); if( rout != NULL ){ rc = DaoProcess_PushCall( proc, rout, self, NULL, 0 ); }else{ DaoValue *arg = (DaoValue*) name; rout = DaoClass_FindMethod( object->defClass, ".", hostClass ); if( rout != NULL ) rc = DaoProcess_PushCall( proc, rout, self, & arg, 1 ); } if( rout == NULL ) return NULL; }else{ DaoProcess_PutValue( proc, value ); } if( rc ) DaoProcess_RaiseError( proc, daoExceptionNames[rc], name->value->chars ); return NULL; }
int DaoProcess_Resume( DaoProcess *self, DaoValue *par[], int N, DaoProcess *ret ) { DaoType *tp; DaoVmCode *vmc; DaoTuple *tuple; if( self->status != DAO_PROCESS_SUSPENDED ) return 0; if( self->activeCode && self->activeCode->code == DVM_MCALL ){ tp = self->activeTypes[ self->activeCode->c ]; if( N == 1 ){ DaoProcess_PutValue( self, par[0] ); }else if( N ){ /* TODO */ tuple = DaoTuple_New( N ); tuple->ctype = tp; GC_IncRC( tuple->ctype ); DaoProcess_MakeTuple( self, tuple, par, N ); DaoProcess_PutValue( self, (DaoValue*) tuple ); } }else if( N ){ /* TODO */ DaoRoutine *rout = self->topFrame->routine; self->paramValues = self->stackValues + self->topFrame->stackBase; if( rout ) rout = DaoProcess_PassParams( self, rout, NULL, NULL, par, NULL, N, DVM_CALL ); self->paramValues = self->stackValues + 1; if( rout == NULL ){ DaoProcess_RaiseError( ret, NULL, "invalid parameters." ); return 0; } } DaoProcess_Start( self ); DaoProcess_PutValue( ret, self->stackValues[0] ); return 1; }
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 TEST_AssertError( DaoProcess *proc, DaoValue* p[], int N ) { DString *expected = p[0]->xString.value; DString *actual = NULL; DList *errors = proc->exceptions; DaoVmCode *sect = DaoProcess_InitCodeSection( proc, 0 ); int catched = 0; int size = errors->size; if( sect == NULL ) return; DaoProcess_Execute( proc ); if ( proc->status == DAO_PROCESS_ABORTED && errors->size > size ){ DaoException *e = (DaoException*)&errors->items.pValue[errors->size - 1]->xCdata; if ( DString_Compare( expected, e->ctype->name ) != 0 ) actual = DString_Copy( e->ctype->name ); else catched = 1; DList_Clear( errors ); } DaoProcess_PopFrame( proc ); if ( !catched ){ char buf[512]; if ( actual ){ snprintf( buf, sizeof(buf), "expected %s error, intercepted %s", expected->chars, actual->chars ); DString_Delete( actual ); } else snprintf( buf, sizeof(buf), "expected %s error, intercepted nothing", expected->chars ); DaoProcess_RaiseError( proc, "Test::AssertError", buf ); } }
static void TEST_Run( DaoProcess *proc, DaoValue* p[], int N ) { DString *prefix = p[0]->xString.value; DList *funcs = proc->activeNamespace->definedRoutines; DaoStream *out = DaoVmSpace_StdioStream( proc->vmSpace ); daoint i; char buf[100]; for ( i = 0; i < funcs->size; ++i ){ DaoRoutine *rout = funcs->items.pRoutine[i]; // find global routines matching prefix if ( strncmp( rout->routName->chars, prefix->chars, prefix->size ) == 0 ){ // ignore 'main()' if ( strcmp( rout->routName->chars, "main" ) == 0 ) continue; // run if ( !( rout->attribs & DAO_ROUT_DECORATOR ) && rout->parCount == 0 ){ if ( DaoProcess_Call( proc, rout, NULL, NULL, 0 ) == DAO_ERROR ){ // failed char buf[512]; snprintf( buf, sizeof(buf), "unexpected error running '%s'", rout->routName->chars ); DaoProcess_RaiseError( proc, "Error::Test", buf ); return; } } } } DMutex_Lock( &test_mtx ); snprintf( buf, sizeof(buf), "Summary: %i tests, %i passed, %i failed, %i skipped\n", test_count, pass_count, fail_count, skip_count ); DaoStream_WriteChars( out, buf ); test_count = pass_count = fail_count = skip_count = 0; DMutex_Unlock( &test_mtx ); }
static void DaoIO_Open( DaoProcess *proc, DaoValue *p[], int N ) { DaoFileStream *self = NULL; char *mode; self = DaoFileStream_New(); DaoProcess_PutValue( proc, (DaoValue*)self ); if( N == 0 ){ do self->file = tmpfile(); while ( !self->file && errno == EINTR ); self->base.Read = DaoFileStream_Read; self->base.Write = DaoFileStream_Write; self->base.AtEnd = DaoFileStream_AtEnd; self->base.Flush = DaoFileStream_Flush; self->base.mode |= DAO_STREAM_WRITABLE | DAO_STREAM_READABLE; if( !self->file ){ char errbuf[512]; GetErrorMessage( errno, errbuf, sizeof(errbuf) ); DaoProcess_RaiseError( proc, "Stream", errbuf ); return; } }else{ mode = DString_GetData( p[1]->xString.value ); if( p[0]->type == DAO_INTEGER ){ self->file = fdopen( p[0]->xInteger.value, mode ); if( self->file == NULL ){ char errbuf[512]; GetErrorMessage( errno, errbuf, sizeof(errbuf) ); DaoProcess_RaiseError( proc, "Stream", errbuf ); return; } }else{ self->file = DaoIO_OpenFile( proc, p[0]->xString.value, mode, 0 ); } if( strstr( mode, "+" ) ){ self->base.mode |= DAO_STREAM_WRITABLE | DAO_STREAM_READABLE; }else{ if( strstr( mode, "r" ) ){ self->base.mode |= DAO_STREAM_READABLE; } if( strstr( mode, "w" ) || strstr( mode, "a" ) ){ self->base.mode |= DAO_STREAM_WRITABLE; } } DaoFileStream_InitCallbacks( self ); } }
static void DaoxUserType_SetItem( DaoValue *self, DaoProcess *proc, DaoValue *ids[], int N, DaoValue *value ) { switch( N ){ case 0 : DaoxUserType_SetItem1( self, proc, dao_none_value, value ); break; case 1 : DaoxUserType_SetItem1( self, proc, ids[0], value ); break; default : DaoProcess_RaiseError( proc, "Index", "not supported" ); } }
static DaoValue* DaoObject_DoGetItem( DaoValue *self, DaoValue *index[], int N, DaoProcess *proc ) { DaoObject *object = (DaoObject*) self; DaoClass *host = proc->activeObject ? proc->activeObject->defClass : NULL; DaoRoutine *rout = DaoClass_FindMethod( object->defClass, "[]", host ); int rc = DaoProcess_PushCall( proc, rout, self, index, N ); if( rc ) DaoProcess_RaiseError( proc, daoExceptionNames[rc], NULL ); return NULL; }
static void PIPE_Close( DaoProcess *proc, DaoValue *p[], int N ) { DaoPipeStream *stream = (DaoPipeStream*) p[0]; if ( stream->file ){ DaoProcess_PutInteger( proc, DaoPipeStream_Close( stream ) ); } else { DaoProcess_RaiseError( proc, "Param", "Stream not open" ); } }
static int DaoIO_CheckMode( DaoStream *self, DaoProcess *proc, int what ) { if( DaoStream_IsOpen( self ) == 0 ){ DaoProcess_RaiseError( proc, NULL, "stream is not open!" ); return 0; } if( what == DAO_STREAM_READABLE && DaoStream_EndOfStream( self ) == 1 ){ DaoProcess_RaiseError( proc, NULL, "stream reached the end!" ); return 0; } if( what == DAO_STREAM_READABLE && DaoStream_IsReadable( self ) == 0 ){ DaoProcess_RaiseError( proc, NULL, "stream is not readable!" ); return 0; } if( what == DAO_STREAM_WRITABLE && DaoStream_IsWritable( self ) == 0 ){ DaoProcess_RaiseError( proc, NULL, "stream is not writable!" ); return 0; } return 1; }
static void COROUT_Resume( DaoProcess *proc, DaoValue *p[], int N ) { DaoxCoroutine *self = (DaoxCoroutine*) p[0]; DaoProcess *sp = self->process; if( self->process == proc ){ DaoProcess_RaiseError( proc, NULL, "coroutine can only resume in alien process." ); return; } if( sp->status != DAO_PROCESS_SUSPENDED || sp->pauseType != DAO_PAUSE_COROUTINE_YIELD ){ DaoProcess_RaiseError( proc, NULL, "coroutine cannot be resumed." ); return; } DaoProcess_Resume( self->process, p+1, N-1, proc ); if( sp->status == DAO_PROCESS_SUSPENDED && sp->pauseType != DAO_PAUSE_COROUTINE_YIELD ){ DaoProcess_RaiseError( proc, NULL, "coroutine is not suspended properly." ); return; } if( self->process->status == DAO_PROCESS_ABORTED ) DaoProcess_RaiseError( proc, NULL, "coroutine execution is aborted." ); }
static void COROUT_Suspend( DaoProcess *proc, DaoValue *p[], int N ) { DaoxCoroutine *self = (DaoxCoroutine*) p[0]; DaoValue *value = N > 1 ? p[1] : DaoValue_MakeNone(); if( self->process != proc ){ DaoProcess_RaiseError( proc, NULL, "coroutine cannot suspend in alien process." ); return; } GC_Assign( & proc->stackValues[0], value ); proc->status = DAO_PROCESS_SUSPENDED; proc->pauseType = DAO_PAUSE_COROUTINE_YIELD; }
static void COROUT_Start( DaoProcess *proc, DaoValue *par[], int N ) { DaoxCoroutine *self = (DaoxCoroutine*) par[0]; DaoValue *params[DAO_MAX_PARAM]; DaoValue *val = par[1]; DaoProcess *vmProc; DaoRoutine *rout; int i, passed = 0; if( val == NULL || val->type != DAO_ROUTINE ){ DaoProcess_RaiseError( proc, "Type", NULL ); return; } params[0] = par[0]; memcpy( params + 1, par + 2, (N-2)*sizeof(DaoValue*) ); rout = DaoRoutine_Resolve( (DaoRoutine*)val, NULL, NULL, params, NULL, N-1, DVM_CALL ); if( rout ) rout = DaoProcess_PassParams( proc, rout, NULL, NULL, params, NULL, N-1, DVM_CALL ); if( rout == NULL || rout->body == NULL ){ DaoProcess_RaiseError( proc, "Param", "not matched" ); return; } if( self->process == NULL ){ self->process = DaoProcess_New( proc->vmSpace ); GC_IncRC( self->process ); } vmProc = self->process; DaoProcess_PushRoutine( vmProc, rout, NULL ); vmProc->activeValues = vmProc->stackValues + vmProc->topFrame->stackBase; for(i=0; i<rout->parCount; i++){ vmProc->activeValues[i] = proc->paramValues[i]; GC_IncRC( vmProc->activeValues[i] ); } vmProc->status = DAO_PROCESS_SUSPENDED; vmProc->pauseType = DAO_PAUSE_COROUTINE_YIELD; DaoProcess_Start( vmProc ); DaoProcess_PutValue( proc, vmProc->stackValues[0] ); if( vmProc->status == DAO_PROCESS_ABORTED ) DaoProcess_RaiseError( proc, NULL, "coroutine execution is aborted." ); }
static void FUTURE_Wait( DaoProcess *proc, DaoValue *par[], int N ) { DaoFuture *self = (DaoFuture*) par[0]; float timeout = par[1]->xFloat.value; DaoProcess_PutBoolean( proc, self->state == DAO_CALL_FINISHED ); if( self->state == DAO_CALL_FINISHED || timeout == 0 ) return; #ifdef DAO_WITH_CONCURRENT proc->status = DAO_PROCESS_SUSPENDED; proc->pauseType = DAO_PAUSE_FUTURE_WAIT; DaoCallServer_AddWait( proc, self, timeout ); #else DaoProcess_RaiseError( proc, NULL, "Invalid future value" ); #endif }
static void DaoSTD_Resource( DaoProcess *proc, DaoValue *p[], int N ) { FILE *fin; DString *file = DString_Copy( p[0]->xString.value ); if( DaoVmSpace_SearchResource( proc->vmSpace, file, proc->activeNamespace->path ) == 0 ){ DString_InsertChars( file, "resource file not found: ", 0, 0, -1 ); DaoProcess_RaiseError( proc, NULL, file->chars ); DString_Delete( file ); return; } DaoVmSpace_ReadFile( proc->vmSpace, file, file ); DaoProcess_PutString( proc, file ); DString_Delete( file ); }
static void PIPE_New( DaoProcess *proc, DaoValue *p[], int N ) { DaoPipeStream *stream = NULL; DString *fname = p[0]->xString.value; char *mode; stream = DaoPipeStream_New(); DaoProcess_PutValue( proc, (DaoValue*)stream ); if( DString_Size( fname ) == 0 ){ DaoProcess_RaiseError( proc, "Param", "Empty command" ); return; } mode = DString_GetData( p[1]->xString.value ); stream->file = popen( DString_GetData( fname ), mode ); if( stream->file == NULL ){ char errbuf[512]; GetErrorMessage( errno, errbuf, sizeof(errbuf) ); DaoProcess_RaiseError( proc, "Stream", errbuf ); return; } if( strstr( mode, "r" ) ) stream->base.mode |= DAO_STREAM_READABLE; if( strstr( mode, "w" ) ) stream->base.mode |= DAO_STREAM_WRITABLE; DaoFileStream_InitCallbacks( stream ); }
static void FUTURE_Value( DaoProcess *proc, DaoValue *par[], int N ) { DaoFuture *self = (DaoFuture*) par[0]; if( self->state == DAO_CALL_FINISHED ){ DaoProcess_PutValue( proc, self->value ); return; } #ifdef DAO_WITH_CONCURRENT proc->status = DAO_PROCESS_SUSPENDED; proc->pauseType = DAO_PAUSE_FUTURE_VALUE; DaoCallServer_AddWait( proc, self, -1 ); #else DaoProcess_RaiseError( proc, NULL, "Invalid future value" ); #endif }
static FILE* DaoIO_OpenFile( DaoProcess *proc, DString *name, const char *mode, int silent ) { DString *fname = DString_Copy( name ); char buf[200]; FILE *fin; DaoIO_MakePath( proc, fname ); fin = Dao_OpenFile( fname->chars, mode ); DString_Delete( fname ); if( fin == NULL && silent == 0 ){ snprintf( buf, sizeof(buf), "error opening file: %s", DString_GetData( name ) ); DaoProcess_RaiseError( proc, "Stream", buf ); return NULL; } return fin; }
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 ); }
static void DaoSTD_Load( DaoProcess *proc, DaoValue *p[], int N ) { DaoNamespace *ns; DaoVmSpace *vms = proc->vmSpace; DString *name = p[0]->xString.value; int import = p[1]->xInteger.value; int runim = p[2]->xInteger.value; int res = 0; DList_PushFront( vms->pathLoading, proc->activeNamespace->path ); ns = DaoVmSpace_LoadEx( vms, DString_GetData( name ), runim ); DaoProcess_PutValue( proc, (DaoValue*) ns ); if( ns == NULL ) DaoProcess_RaiseError( proc, NULL, "loading failed" ); DList_PopFront( vms->pathLoading ); if( import && ns ) DaoNamespace_AddParent( proc->activeNamespace, ns ); }
static void WIN_New( DaoProcess *proc, DaoValue *p[], int N ) { DaoxWindow *self = DaoxWindow_New(); DString_Assign( self->title, p[2]->xString.value ); self->width = self->context->deviceWidth = p[0]->xInteger.value; self->height = self->context->deviceHeight = p[1]->xInteger.value; self->handle = glfwCreateWindow( self->width, self->height, self->title->chars, NULL, NULL); if( self->handle == NULL ){ DaoProcess_RaiseError( proc, NULL, "Failed to create window" ); return; } glfwSetWindowUserPointer( self->handle, self ); glfwSetWindowCloseCallback( self->handle, DaoxWindow_CloseCallback ); glfwHideWindow( self->handle ); glfwMakeContextCurrent( self->handle ); DaoProcess_PutValue( proc, (DaoValue*) self ); }
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 DaoxGraphData_IsAssociated( DaoxGraphData *self, DaoxGraph *graph, DaoProcess *proc ) { if( self->graph == graph ) return 1; DaoProcess_RaiseError( proc, NULL, "graph is not associated with the algorithm data!" ); return 0; }
static void TEST_SkipTest( DaoProcess *proc, DaoValue* p[], int N ) { DaoProcess_RaiseError( proc, "Test::Skip", p[0]->xString.value->chars ); }
static void DaoMT_Functional( DaoProcess *proc, DaoValue *P[], int N, int F ) { DMutex mutex; DCondVar condv; DaoTaskData *tasks; DaoValue *param = P[0]; DaoValue *result = NULL; DaoList *list = NULL; DaoArray *array = NULL; DaoVmCode *sect = NULL; DaoStackFrame *frame = DaoProcess_FindSectionFrame( proc ); int i, entry, threads = P[1]->xInteger.value; daoint index = -1, status = 0, joined = 0; DNode *node = NULL; switch( F ){ case DVM_FUNCT_MAP : if( param->type == DAO_ARRAY ){ array = DaoProcess_PutArray( proc ); result = (DaoValue*) array; }else{ list = DaoProcess_PutList( proc ); result = (DaoValue*) list; } break; case DVM_FUNCT_FIND : DaoProcess_PutValue( proc, dao_none_value ); break; } if( threads <= 0 ) threads = 2; if( frame != proc->topFrame->prev ){ DaoProcess_RaiseError( proc, NULL, "Invalid code section from non-immediate caller" ); return; } sect = DaoProcess_InitCodeSection( proc, 0 ); if( sect == NULL ) return; if( list ){ DList_Clear( list->value ); if( param->type == DAO_LIST ) DList_Resize( list->value, param->xList.value->size, NULL ); if( param->type == DAO_MAP ) DList_Resize( list->value, param->xMap.value->size, NULL ); #ifdef DAO_WITH_NUMARRAY }else if( array && F == DVM_FUNCT_MAP ){ DaoArray_GetSliceShape( (DaoArray*) param, & array->dims, & array->ndim ); DaoArray_ResizeArray( array, array->dims, array->ndim ); #endif } DMutex_Init( & mutex ); DCondVar_Init( & condv ); entry = proc->topFrame->entry; tasks = (DaoTaskData*) dao_calloc( threads, sizeof(DaoTaskData) ); DaoProcess_PopFrame( proc ); for(i=0; i<threads; i++){ DaoTaskData *task = tasks + i; task->param = param; task->result = result; task->proto = proc; task->sect = sect; task->funct = F; task->entry = entry; task->first = i; task->step = threads; task->index = & index; task->node = & node; task->joined = & joined; task->condv = & condv; task->mutex = & mutex; task->clone = DaoVmSpace_AcquireProcess( proc->vmSpace ); if( i ) DaoCallServer_AddTask( DaoMT_RunFunctional, task, task->clone ); } DaoMT_RunFunctional( tasks ); DMutex_Lock( & mutex ); while( joined < threads ) DCondVar_TimedWait( & condv, & mutex, 0.01 ); DMutex_Unlock( & mutex ); for(i=0; i<threads; i++){ DaoTaskData *task = tasks + i; DaoVmSpace_ReleaseProcess( proc->vmSpace, task->clone ); status |= task->status; } if( F == DVM_FUNCT_FIND ){ DaoTuple *tuple = DaoProcess_PutTuple( proc, 2 ); if( param->type == DAO_LIST && index != -1 ){ DaoValue **items = param->xList.value->items.pValue; GC_Assign( & tuple->values[1], items[index] ); tuple->values[0]->xInteger.value = index; }else if( param->type == DAO_MAP && node ){ GC_Assign( & tuple->values[0], node->key.pValue ); GC_Assign( & tuple->values[1], node->value.pValue ); } } if( status ) DaoProcess_RaiseError( proc, NULL, "code section execution failed!" ); DMutex_Destroy( & mutex ); DCondVar_Destroy( & condv ); dao_free( tasks ); }