DaoConstant* DaoConstant_New( DaoValue *value ) { DaoConstant *self = (DaoConstant*) dao_calloc( 1, sizeof(DaoConstant) ); DaoValue_Init( self, DAO_CONSTANT ); DaoValue_Copy( value, & self->value ); return self; }
void DaoClass_SetConst( DaoClass *self, int id, DaoValue *data ) { id = LOOKUP_ID( id ); if( id >= self->constants->size ) return; DaoValue_Copy( data, & self->constants->items.pConst[id]->value ); DaoValue_MarkConst( self->constants->items.pConst[id]->value ); }
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 ); }
DaoState* DaoState_New( DaoType *type, DaoValue *state ) { DaoState *res = dao_malloc( sizeof(DaoState) ); DaoCstruct_Init( (DaoCstruct*)res, type ); DaoValue_Copy( state, &res->state ); res->lock = DaoMutex_New(); res->defmtx = DaoMutex_New(); res->demands = DaoMap_New( 0 ); DaoGC_IncRC( (DaoValue*)res->lock ); DaoGC_IncRC( (DaoValue*)res->defmtx ); DaoGC_IncRC( (DaoValue*)res->demands ); return res; }
void DaoValue_MoveCinValue( DaoCinValue *S, DaoValue **D ) { DaoValue *D2 = *D; if( D2 == (DaoValue*) S ) return; if( D2 == NULL || D2->type != DAO_CINVALUE || D2->xCinValue.refCount > 1 ){ S = DaoCinValue_Copy( S ); DaoGC_Assign( D, (DaoValue*) S ); return; } if( D2->xCinValue.cintype != S->cintype ){ GC_Assign( & D2->xCinValue.cintype, S->cintype ); } DaoValue_Copy( S->value, & D2->xCinValue.value ); }
static void DaoState_Set( DaoProcess *proc, DaoValue *p[], int N ) { DaoState *self = (DaoState*)DaoValue_CastCstruct( p[0], NULL ); DNode *node; DaoMutex_Lock( self->lock ); DaoValue_Copy( p[1], &self->state ); node = DaoMap_First( self->demands ); while( node && DaoValue_Compare( DNode_Key( node ), self->state ) ) node = DaoMap_Next( self->demands, node ); if( node ){ DaoCondVar_BroadCast( (DaoCondVar*)DNode_Value( node ) ); DaoMap_Erase( self->demands, DNode_Key( node ) ); } DaoMutex_Unlock( self->lock ); }
void DaoObject_Init( DaoObject *self, DaoObject *that, int offset ) { DaoClass *klass = self->defClass; daoint i; if( that ){ GC_ShiftRC( that, self->rootObject ); self->rootObject = that; self->objValues = that->objValues + offset; }else if( self->rootObject == NULL ){ GC_ShiftRC( self, self->rootObject ); self->rootObject = self; if( self->isNull ){ /* no value space is allocated for null object yet! */ self->valueCount = klass->objDataName->size; self->objValues = (DaoValue**) dao_calloc( self->valueCount, sizeof(DaoValue*) ); } } offset += self->defClass->objDefCount; if( klass->parent != NULL && klass->parent->type == DAO_CLASS ){ DaoObject *sup = NULL; if( self->isNull ){ sup = & klass->parent->xClass.objType->value->xObject; }else{ sup = DaoObject_Allocate( (DaoClass*) klass->parent, 0 ); sup->isRoot = 0; DaoObject_Init( sup, self->rootObject, offset ); } GC_ShiftRC( sup, self->parent ); self->parent = (DaoValue*)sup; } GC_ShiftRC( self, self->objValues[0] ); self->objValues[0] = (DaoValue*) self; if( self->isRoot == 0 ) return; for(i=1; i<klass->instvars->size; i++){ DaoVariable *var = klass->instvars->items.pVar[i]; DaoValue **value = self->objValues + i; /* for data type such as list/map/array, * its .ctype may need to be set properaly */ if( var->value ){ DaoValue_Move( var->value, value, var->dtype ); continue; }else if( *value == NULL && var->dtype && var->dtype->value ){ DaoValue_Copy( var->dtype->value, value ); } } }
static void DaoState_TestSet( DaoProcess *proc, DaoValue *p[], int N ) { DaoState *self = (DaoState*)DaoValue_CastCstruct( p[0], NULL ); int set = 0; DNode *node; DaoMutex_Lock( self->lock ); if( !DaoValue_Compare( self->state, p[1] ) ){ DaoValue_Copy( p[2], &self->state ); set = 1; node = DaoMap_First( self->demands ); while( node && DaoValue_Compare( DNode_Key( node ), self->state ) ) node = DaoMap_Next( self->demands, node ); if( node ) DaoCondVar_BroadCast( (DaoCondVar*)DNode_Value( node ) ); } DaoMutex_Unlock( self->lock ); DaoProcess_PutInteger( proc, set ); }
static void DaoQueue_Push( DaoProcess *proc, DaoValue *p[], int N ) { DaoQueue *self = (DaoQueue*)DaoValue_CastCstruct( p[0], NULL ); QueueItem *item = (QueueItem*)dao_malloc( sizeof(QueueItem) ); item->value = NULL; DaoValue_Copy( p[1], &item->value ); item->next = NULL; DaoMutex_Lock( self->mtx ); while( self->capacity && self->size == self->capacity ) DaoCondVar_Wait( self->pushvar, self->mtx ); item->previous = self->tail; if( self->tail ) self->tail->next = item; else{ self->head = item; DaoCondVar_Signal( self->popvar ); } self->tail = item; self->size++; DaoMutex_Unlock( self->mtx ); }
DaoxDataFrame* DaoProcess_MakeReturnDataFrame( DaoProcess *self ) { DaoVmCode *vmc = self->activeCode; DaoValue *dC = self->activeValues[ vmc->c ]; DaoxDataFrame *df = (DaoxDataFrame*) DaoValue_CastCstruct( dC, daox_type_dataframe ); if( df != NULL ){ DaoVmCode *vmc2 = vmc + 1; int reuse = 0; if( df->refCount == 1 ) reuse = 1; if( df->refCount == 2 && (vmc2->code == DVM_MOVE || vmc2->code == DVM_MOVE_PP) && vmc2->a != vmc2->c ){ if( self->activeValues[vmc2->c] == (DaoValue*) df ) reuse = 1; } if( reuse ){ DaoxDataFrame_Reset( df ); return df; } } df = DaoxDataFrame_New(); DaoValue_Copy( (DaoValue*) df, & self->activeValues[ vmc->c ] ); return df; }
static void DaoQueue_TryPush( DaoProcess *proc, DaoValue *p[], int N ) { DaoQueue *self = (DaoQueue*)DaoValue_CastCstruct( p[0], NULL ); QueueItem *item = (QueueItem*)dao_malloc( sizeof(QueueItem) ); float timeout = DaoValue_TryGetFloat( p[2] ); int pushable = 0, timed = 0; item->value = NULL; DaoValue_Copy( p[1], &item->value ); item->next = NULL; DaoMutex_Lock( self->mtx ); if( timeout == 0 ) pushable = ( !self->capacity || self->size < self->capacity ); else if( timeout < 0 ){ while( self->capacity && self->size == self->capacity ) DaoCondVar_Wait( self->pushvar, self->mtx ); pushable = 1; } else{ while( !timed && self->capacity && self->size == self->capacity ) timed = DaoCondVar_TimedWait( self->pushvar, self->mtx, timeout ); pushable = !timed; } if( pushable ){ item->previous = self->tail; if( self->tail ) self->tail->next = item; else{ self->head = item; DaoCondVar_Signal( self->popvar ); } self->tail = item; self->size++; } DaoMutex_Unlock( self->mtx ); if( !pushable ){ DaoGC_DecRC( item->value ); dao_free( item ); } DaoProcess_PutInteger( proc, pushable ); }
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 }
void DaoConstant_Set( DaoConstant *self, DaoValue *value ) { DaoValue_Copy( value, & self->value ); }
/* // Note: reference count is handled for "value2"! // // Item of list/tuple etc. can be directly passed as parameter "value2", // to avoid creating unnecessary intermediate objects. */ static int DaoParser_Deserialize( DaoParser *self, int start, int end, DaoValue **value2, DArray *types, DaoNamespace *ns, DaoProcess *proc, DMap *omap ) { DaoToken **tokens = self->tokens->items.pToken; DaoType *it1 = NULL, *it2 = NULL, *type = NULL; DaoValue *value = *value2; DaoValue *tmp = NULL; DaoValue *tmp2 = NULL; DaoObject *object; DaoCdata *cdata; DaoArray *array; DaoTuple *tuple; DaoList *list; DaoMap *map; DArray *dims; DNode *node; void *key = NULL; char *str; int i, j, k, n; int minus = 0; int next = start + 1; int tok2 = start < end ? tokens[start+1]->type : 0; int maybetype = tok2 == DTOK_COLON2 || tok2 == DTOK_LT || tok2 == DTOK_LCB; if( tokens[start]->type == DTOK_AT && tok2 == DTOK_LCB ){ int rb = DaoParser_FindPairToken( self, DTOK_LCB, DTOK_RCB, start, end ); if( rb < 0 ) return next; sscanf( tokens[start+2]->string.mbs, "%p", & key ); node = DMap_Find( omap, key ); if( node ) DaoValue_Copy( node->value.pValue, value2 ); return rb + 1; } if( tokens[start]->name == DTOK_ID_SYMBOL ){ DString *mbs = DString_New(1); while( tokens[start]->name == DTOK_ID_SYMBOL ){ DString_Append( mbs, & tokens[start]->string ); start += 1; } type = DaoNamespace_MakeType( ns, mbs->mbs, DAO_ENUM, NULL, NULL, 0 ); DString_Delete( mbs ); if( type == NULL ) return start; if( tokens[start]->name != DTOK_LCB ) return start; end = DaoParser_FindPairToken( self, DTOK_LCB, DTOK_RCB, start, end ); if( end < 0 ) return start; next = end + 1; start += 1; end -= 1; }else if( tokens[start]->type == DTOK_IDENTIFIER && maybetype ){ type = DaoParser_ParseType( self, start, end, & start, NULL ); if( type == NULL ) return next; if( tokens[start]->name != DTOK_LCB ) return start; end = DaoParser_FindPairToken( self, DTOK_LCB, DTOK_RCB, start, end ); if( end < 0 ) return start; next = end + 1; start += 1; end -= 1; } if( type == NULL ){ type = types->items.pType[0]; if( type && type->tid >= DAO_ARRAY ){ if( tokens[start]->name != DTOK_LCB ) return start; end = DaoParser_FindPairToken( self, DTOK_LCB, DTOK_RCB, start, end ); if( end < 0 ) return start; next = end + 1; start += 1; end -= 1; } } if( type == NULL ) return next; DaoValue_Copy( type->value, value2 ); if( start > end ) return next; if( tokens[start]->name == DTOK_SUB ){ minus = 1; start += 1; if( start > end ) return next; } if( type->nested && type->nested->size >0 ) it1 = type->nested->items.pType[0]; if( type->nested && type->nested->size >1 ) it2 = type->nested->items.pType[1]; if( tokens[start]->name == DTOK_LB ){ int rb = DaoParser_FindPairToken( self, DTOK_LB, DTOK_RB, start, end ); if( rb < 0 ) return next; sscanf( tokens[start+1]->string.mbs, "%p", & key ); DMap_Insert( omap, key, *value2 ); start = rb + 1; } str = tokens[start]->string.mbs; #if 0 printf( "type: %s %s\n", type->name->mbs, str ); for(i=start; i<=end; i++) printf( "%s ", tokens[i]->string.mbs ); printf( "\n" ); #endif value = *value2; switch( type->tid ){ case DAO_NONE : break; case DAO_INTEGER : value->xInteger.value = DaoDecodeInteger( str ); if( minus ) value->xInteger.value = - value->xInteger.value; break; case DAO_FLOAT : value->xFloat.value = DaoDecodeDouble( str ); if( minus ) value->xFloat.value = - value->xFloat.value; break; case DAO_DOUBLE : value->xDouble.value = DaoDecodeDouble( str ); if( minus ) value->xDouble.value = - value->xDouble.value; break; case DAO_COMPLEX : value->xComplex.value.real = DaoDecodeDouble( str ); if( minus ) value->xComplex.value.real = - value->xComplex.value.real; if( start + 1 > end ) return start+1; minus = 0; if( tokens[start + 1]->name == DTOK_SUB ){ minus = 1; start += 1; if( start + 1 > end ) return start+1; } value->xComplex.value.imag = DaoDecodeDouble( tokens[start+1]->string.mbs ); if( minus ) value->xComplex.value.imag = - value->xComplex.value.imag; next = start + 2; break; #ifdef DAO_WITH_LONGINT case DAO_LONG : value->xLong.value->base = DaoDecodeInteger( str ); start += 1; if( tokens[start]->name == DTOK_ADD ){ value->xLong.value->sign = 1; start += 1; }else if( tokens[start]->name == DTOK_SUB ){ value->xLong.value->sign = -1; start += 1; } for(i=start; i<=end; i++){ if( tokens[i]->name == DTOK_COMMA ) continue; DLong_PushBack( value->xLong.value, DaoDecodeInteger( tokens[i]->string.mbs ) ); } break; #endif case DAO_STRING : n = tokens[start]->string.size - 1; for(i=1; i<n; i++){ char c1 = str[i]; char c2 = str[i+1]; if( c1 < 'A' || c1 > 'P' ) continue; DString_AppendChar( value->xString.data, (char)((c1-'A')*16 + (c2-'A')) ); i += 1; } if( str[0] == '\"' ) DString_ToWCS( value->xString.data ); break; case DAO_ENUM : value->xEnum.value = DaoDecodeInteger( str ); break; case DAO_ARRAY : #ifdef DAO_WITH_NUMARRAY if( tokens[start]->name != DTOK_LSB ) return next; k = DaoParser_FindPairToken( self, DTOK_LSB, DTOK_RSB, start, end ); if( k < 0 ) return next; n = 1; for(i=start+1; i<k; i++){ if( tokens[i]->name == DTOK_COMMA ) continue; n *= strtol( tokens[i]->string.mbs, 0, 0 ); } if( n < 0 ) return next; if( it1 == NULL || it1->tid == 0 || it1->tid > DAO_COMPLEX ) return next; array = & value->xArray; dims = DArray_New(0); for(i=start+1; i<k; i++){ if( tokens[i]->name == DTOK_COMMA ) continue; j = strtol( tokens[i]->string.mbs, 0, 0 ); DArray_Append( dims, (size_t) j ); } n = dims->size; DaoArray_ResizeArray( array, dims->items.pInt, n ); DArray_PushFront( types, it1 ); DArray_Delete( dims ); n = 0; for(i=k+1; i<=end; i++){ j = i + 1; while( j <= end && tokens[j]->name != DTOK_COMMA ) j += 1; DaoParser_Deserialize( self, i, j-1, & tmp, types, ns, proc, omap ); switch( it1->tid ){ case DAO_INTEGER : array->data.i[n] = tmp->xInteger.value; break; case DAO_FLOAT : array->data.f[n] = tmp->xFloat.value; break; case DAO_DOUBLE : array->data.d[n] = tmp->xDouble.value; break; } i = j; n += 1; } DArray_PopFront( types ); #endif break; case DAO_LIST : list = & value->xList; DArray_PushFront( types, it1 ); n = 0; for(i=start; i<=end; i++){ if( tokens[i]->name == DTOK_COMMA ) continue; DArray_Append( & list->items, NULL ); k = DaoParser_Deserialize( self, i, end, list->items.items.pValue + n, types, ns, proc, omap ); i = k - 1; n += 1; } DArray_PopFront( types ); break; case DAO_MAP : map = & value->xMap; n = 0; for(i=start; i<=end; i++){ if( tokens[i]->name == DTOK_COMMA ) continue; DaoValue_Clear( & tmp ); DaoValue_Clear( & tmp2 ); DArray_PushFront( types, it1 ); i = DaoParser_Deserialize( self, i, end, &tmp, types, ns, proc, omap ); DArray_PopFront( types ); if( tokens[i]->name == DTOK_COMMA ) continue; if( map->items->size == 0 ){ if( tokens[i]->name == DTOK_COLON ){ DMap_Delete( map->items ); map->items = DHash_New( D_VALUE, D_VALUE ); } } if( tokens[i]->name == DTOK_COLON || tokens[i]->name == DTOK_FIELD ) i += 1; DArray_PushFront( types, it2 ); i = DaoParser_Deserialize( self, i, end, &tmp2, types, ns, proc, omap ); DArray_PopFront( types ); node = DMap_Insert( map->items, (void*) tmp, (void*) tmp2 ); i -= 1; n += 1; } break; case DAO_TUPLE : tuple = & value->xTuple; n = 0; for(i=start; i<=end; i++){ if( tokens[i]->name == DTOK_COMMA ) continue; it1 = NULL; if( type->nested && type->nested->size > n ){ it1 = type->nested->items.pType[n]; if( it1 && it1->tid == DAO_PAR_NAMED ) it1 = & it1->aux->xType; } DArray_PushFront( types, it1 ); i = DaoParser_Deserialize( self, i, end, tuple->items + n, types, ns, proc, omap ); DArray_PopFront( types ); i -= 1; n += 1; } break; case DAO_OBJECT : DArray_PushFront( types, NULL ); DaoParser_Deserialize( self, start, end, & tmp, types, ns, proc, omap ); DArray_PopFront( types ); if( tmp == NULL ) break; object = DaoClass_MakeObject( & type->aux->xClass, tmp, proc ); if( object ) DaoValue_Copy( (DaoValue*) object, value2 ); break; case DAO_CDATA : case DAO_CSTRUCT : DArray_PushFront( types, NULL ); DaoParser_Deserialize( self, start, end, & tmp, types, ns, proc, omap ); DArray_PopFront( types ); if( tmp == NULL ) break; cdata = DaoCdata_MakeObject( & type->aux->xCdata, tmp, proc ); if( cdata ) DaoValue_Copy( (DaoValue*) cdata, value2 ); break; } DaoValue_Clear( & tmp ); DaoValue_Clear( & tmp2 ); return next; }