void DaoValue_Update( DaoValue **self, DaoNamespace *ns, DMap *deftypes ) { DaoValue *value = *self; DaoType *tp, *tp2; if( value == NULL || value->type < DAO_ENUM ) return; tp = DaoNamespace_GetType( ns, value ); /* DaoType_DefineTypes() will make proper specialization of template-like type: */ tp2 = DaoType_DefineTypes( tp, ns, deftypes ); if( tp == tp2 ) return; if( tp2->tid == DAO_OBJECT && value->type == DAO_OBJECT && value->xObject.isDefault ){ /* "self" is supposed to be a constant, so it has to be a default instance: */ GC_ShiftRC( tp2->value, value ); /* default instance of specialized Dao class; */ *self = tp2->value; return; }else if( tp2->tid == DAO_CLASS && value->type == DAO_CLASS ){ GC_ShiftRC( tp2->aux, value ); /* specialized Dao class; */ *self = tp2->aux; return; }else if( tp2->tid == DAO_CTYPE && value->type == DAO_CTYPE ){ GC_ShiftRC( tp2->aux, value ); /* specialized C type; */ *self = tp2->aux; return; }else if( tp2->tid == DAO_CDATA && value->type == DAO_CDATA ){ GC_ShiftRC( tp2->value, value ); /* default instance of specialized C type; */ *self = tp2->value; return; }else if( tp2->tid == DAO_CSTRUCT && value->type == DAO_CSTRUCT ){ GC_ShiftRC( tp2->value, value ); /* default instance of specialized C type; */ *self = tp2->value; return; } DaoValue_Move( value, self, tp2 ); }
void DaoTaskEvent_Init( DaoTaskEvent *self, int T, int S, DaoFuture *F, DaoChannel *C ) { GC_ShiftRC( F, self->future ); GC_ShiftRC( C, self->channel ); self->type = T; self->state = S; self->future = F; self->channel = C; }
void DaoClass_MakeInterface( DaoClass *self ) { daoint i, j; DaoType *tp; DaoRoutine *meth; DaoInterface *inter = self->inter; DMap *deftypes = DHash_New(0,0); DArray_Clear( self->inter->supers ); DMap_Clear( self->inter->methods ); if( self->parent && self->parent->type == DAO_CLASS ) DArray_Append( inter->supers, self->parent->xClass.inter ); for(i=0; i<self->cstDataName->size; ++i){ DString *name = self->cstDataName->items.pString[i]; DaoValue *value = self->constants->items.pConst[i]->value; DaoRoutine *rout = (DaoRoutine*) value; DNode *it; if( value->type != DAO_ROUTINE ) continue; if( value->xRoutine.attribs & DAO_ROUT_DECORATOR ) continue; it = MAP_Find( self->lookupTable, rout->routName ); if( it == NULL || LOOKUP_PM( it->value.pInt ) != DAO_DATA_PUBLIC ) continue; DMap_Reset( deftypes ); DMap_Insert( deftypes, rout->routHost, inter->abtype ); if( rout->overloads == NULL ){ tp = DaoType_DefineTypes( rout->routType, rout->nameSpace, deftypes ); if( tp == NULL ) continue; /* TODO: handle error; */ meth = DaoRoutine_New( rout->nameSpace, inter->abtype, 0 ); meth->attribs = rout->attribs; DString_Assign( meth->routName, rout->routName ); GC_ShiftRC( tp, meth->routType ); meth->routType = tp; DaoMethods_Insert( inter->methods, meth, meth->nameSpace, meth->routHost ); }else{ for(j=0; j<rout->overloads->routines->size; ++j){ DaoRoutine *rout2 = rout->overloads->routines->items.pRoutine[j]; if( rout2->attribs & DAO_ROUT_DECORATOR ) continue; tp = DaoType_DefineTypes( rout2->routType, rout2->nameSpace, deftypes ); if( tp == NULL ) continue; /* TODO: handle error; */ meth = DaoRoutine_New( rout2->nameSpace, inter->abtype, 0 ); meth->attribs = rout2->attribs; DString_Assign( meth->routName, rout->routName ); GC_ShiftRC( tp, meth->routType ); meth->routType = tp; DaoMethods_Insert( inter->methods, meth, meth->nameSpace, meth->routHost ); } } } DMap_Delete( deftypes ); }
void DaoValue_SetType( DaoValue *to, DaoType *tp ) { DaoType *tp2; DNode *it; if( to->type != tp->tid && tp->tid != DAO_ANY ) return; if( tp->attrib & DAO_TYPE_SPEC ) return; switch( to->type ){ #ifdef DAO_WITH_NUMARRAY case DAO_ARRAY : if( to->xArray.size ) return; if( tp->tid != DAO_ARRAY || tp->nested == NULL || tp->nested->size == 0 ) break; tp = tp->nested->items.pType[0]; if( tp->tid == DAO_NONE || tp->tid > DAO_COMPLEX ) break; DaoArray_SetNumType( (DaoArray*) to, tp->tid ); break; #endif case DAO_LIST : /* v : any = {}, v->unitype should be list<any> */ if( tp->tid == DAO_ANY ) tp = dao_list_any; if( to->xList.unitype && !(to->xList.unitype->attrib & DAO_TYPE_UNDEF) ) break; GC_ShiftRC( tp, to->xList.unitype ); to->xList.unitype = tp; break; case DAO_MAP : if( tp->tid == DAO_ANY ) tp = dao_map_any; if( to->xMap.unitype && !(to->xMap.unitype->attrib & DAO_TYPE_UNDEF) ) break; GC_ShiftRC( tp, to->xMap.unitype ); to->xMap.unitype = tp; break; case DAO_TUPLE : tp2 = to->xTuple.unitype; if( tp->tid == DAO_ANY ) break; if( tp->nested->size ==0 ) break; /* not to the generic tuple type */ if( tp2 == NULL || tp2->mapNames == NULL || tp2->mapNames->size ==0 ){ GC_ShiftRC( tp, to->xTuple.unitype ); to->xTuple.unitype = tp; break; } if( tp->mapNames == NULL || tp->mapNames->size ) break; for(it=DMap_First(tp2->mapNames); it!=NULL; it=DMap_Next(tp2->mapNames, it)){ if( DMap_Find( tp->mapNames, it->key.pVoid ) == NULL ) break; } if( it ) break; GC_ShiftRC( tp, to->xTuple.unitype ); to->xTuple.unitype = tp; break; default : break; } }
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 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; if( DaoProcess_CheckCB( proc, "cannot select/block inside code section method" ) ) return; 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_RaiseException( proc, DAO_ERROR_PARAM, "invalid type selection" ); return; } } event = DaoCallServer_MakeEvent(); DaoTaskEvent_Init( event, DAO_EVENT_WAIT_SELECT, DAO_EVENT_WAIT, future, NULL ); GC_ShiftRC( selects, event->selects ); 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 ); }
void DaoxDataColumn_SetCell( DaoxDataColumn *self, daoint i, DaoValue *value ) { if( value == NULL ){ complex16 zero = {0.0,0.0}; switch( self->type->tid ){ default : GC_DecRC( self->cells->data.values[i] ); self->cells->data.values[i] = value; break; case DAO_INTEGER : self->cells->data.daoints[i] = 0; break; case DAO_FLOAT : self->cells->data.floats[i] = 0.0; break; case DAO_DOUBLE : self->cells->data.doubles[i] = 0.0; break; case DAO_COMPLEX : self->cells->data.complexes[i] = zero; break; case DAO_STRING : DString_Reset( & self->cells->data.strings[i], 0 ); break; } return; } switch( self->type->tid ){ default : GC_ShiftRC( value, self->cells->data.values[i] ); self->cells->data.values[i] = value; break; case DAO_INTEGER : self->cells->data.daoints[i] = DaoValue_GetInteger( value ); break; case DAO_FLOAT : self->cells->data.floats[i] = DaoValue_GetFloat( value ); break; case DAO_DOUBLE : self->cells->data.doubles[i] = DaoValue_GetDouble( value ); break; case DAO_COMPLEX : self->cells->data.complexes[i] = DaoValue_GetComplex( value ); break; case DAO_STRING : DaoValue_GetString( value, & self->cells->data.strings[i] ); break; } }
void DaoValue_CopyX( DaoValue *src, DaoValue **dest, DaoDataCache *cache ) { DaoValue *dest2 = *dest; if( src == dest2 ) return; if( dest2 && dest2->xBase.refCount >1 ){ GC_DecRC( dest2 ); *dest = dest2 = NULL; } if( dest2 == NULL ){ src = DaoValue_SimpleCopyWithTypeX( src, NULL, cache ); GC_IncRC( src ); *dest = src; return; } if( src->type != dest2->type || src->type > DAO_ENUM ){ src = DaoValue_SimpleCopyWithTypeX( src, NULL, cache ); GC_ShiftRC( src, dest2 ); *dest = src; return; } switch( src->type ){ case DAO_ENUM : DaoEnum_SetType( & dest2->xEnum, src->xEnum.etype ); DaoEnum_SetValue( & dest2->xEnum, & src->xEnum, NULL ); break; case DAO_INTEGER : dest2->xInteger.value = src->xInteger.value; break; case DAO_FLOAT : dest2->xFloat.value = src->xFloat.value; break; case DAO_DOUBLE : dest2->xDouble.value = src->xDouble.value; break; case DAO_COMPLEX : dest2->xComplex.value = src->xComplex.value; break; #ifdef DAO_WITH_LONGINT case DAO_LONG : DLong_Move( dest2->xLong.value, src->xLong.value ); break; #endif case DAO_STRING : DString_Assign( dest2->xString.data, src->xString.data ); break; } }
static void FRAME_GETMI( DaoProcess *proc, DaoValue *p[], int N ) { DaoxDataFrame *df, *self = (DaoxDataFrame*) p[0]; int singleIndex1 = DaoxDF_IsSingleIndex( p[1] ); int singleIndex2 = DaoxDF_IsSingleIndex( p[2] ); int singleIndex3 = DaoxDF_IsSingleIndex( p[3] ); DaoxDataFrame_Sliced( self ); if( singleIndex1 && singleIndex2 && (singleIndex3 || self->dims[2] == 1) ){ daoint i = DaoxDF_MakeIndex( self, DAOX_DF_ROW, p[1], proc ); daoint j = DaoxDF_MakeIndex( self, DAOX_DF_COL, p[2], proc ); daoint k = DaoxDF_MakeIndex( self, DAOX_DF_DEP, p[3], proc ); daoint ik = k * self->dims[0] + i; DaoValue value = {0}; if( i < 0 || j < 0 || k < 0 ) return; memset( & value, 0, sizeof(DaoValue) ); DaoxDataColumn_GetCell( (DaoxDataColumn*) self->columns->items.pVoid[j], ik, & value ); DaoProcess_PutValue( proc, & value ); }else{ df = DaoProcess_MakeReturnDataFrame( proc ); DaoxDataFrame_PrepareSlices( df ); DaoDataFrame_MakeSlice( self, proc, p+1, N-1, df->slices ); GC_ShiftRC( self, df->original ); df->original = self; DaoProcess_PutValue( proc, (DaoValue*) df ); } }
int DaoVariable_Set( DaoVariable *self, DaoValue *value, DaoType *type ) { if( type ){ GC_ShiftRC( type, self->dtype ); self->dtype = type; } return DaoValue_Move( value, & self->value, self->dtype ); }
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 DaoMT_Start( DaoProcess *proc, DaoValue *p[], int n ) { DaoProcess *clone; DaoVmCode *vmc, *end; DaoVmCode *sect = DaoGetSectionCode( proc->activeCode ); DaoType *type = DaoProcess_GetReturnType( proc ); DaoFuture *future = DaoFuture_New( type, 0 ); int entry, nop = proc->activeCode[1].code == DVM_NOP; DaoProcess_PutValue( proc, (DaoValue*) future ); if( sect == NULL || DaoMT_PushSectionFrame( proc ) == 0 ) return; entry = proc->topFrame->entry; end = proc->activeRoutine->body->vmCodes->data.codes + proc->activeCode[nop+1].b; clone = DaoVmSpace_AcquireProcess( proc->vmSpace ); DaoProcess_PopFrame( proc ); DaoProcess_SetActiveFrame( proc, proc->topFrame ); DaoMT_InitProcess( proc, clone ); clone->topFrame->entry = entry; /* // Use the cloned process instead of the parent process, in case that // the cloned process will not be joined by the parent process: */ clone->topFrame->outer = clone; future->process = clone; GC_IncRC( clone ); GC_ShiftRC( future, clone->future ); clone->future = future; future->state = DAO_CALL_RUNNING; 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 ){ /* These values should be shared with the parent thread: */ GC_ShiftRC( proc->activeValues[i], clone->activeValues[i] ); clone->activeValues[i] = proc->activeValues[i]; } } DaoCallServer_AddTask( DaoMT_Start0, clone, p[0]->xEnum.value ); }
static DaoValue* DaoValue_DeepCopy( DaoValue *self ) { DNode *it; daoint i; if( self == NULL ) return NULL; if( self->type <= DAO_ENUM ) return self; /* simple types will be copied at use; */ if( self->type == DAO_ARRAY ) return (DaoValue*) DaoArray_Copy( (DaoArray*) self ); if( self->type == DAO_LIST ){ DaoList *list = (DaoList*) self; DaoList *copy = DaoList_New(); GC_ShiftRC( list->unitype, copy->unitype ); copy->unitype = list->unitype; for(i=0; i<list->items.size; ++i){ DaoValue *value = DaoValue_DeepCopy( list->items.items.pValue[i] ); DaoList_Append( copy, value ); } return (DaoValue*) copy; }else if( self->type == DAO_MAP ){ DaoMap *map = (DaoMap*) self; DaoMap *copy = DaoMap_New( map->items->hashing ); GC_ShiftRC( map->unitype, copy->unitype ); copy->unitype = map->unitype; for(it=DMap_First(map->items); it; it=DMap_Next(map->items,it)){ DaoValue *key = DaoValue_DeepCopy( it->key.pValue ); DaoValue *value = DaoValue_DeepCopy( it->value.pValue ); DaoMap_Insert( copy, key, value ); } return (DaoValue*) copy; }else if( self->type == DAO_TUPLE ){ DaoTuple *tuple = (DaoTuple*) self; DaoTuple *copy = DaoTuple_New( tuple->size ); GC_ShiftRC( tuple->unitype, copy->unitype ); copy->unitype = tuple->unitype; for(i=0; i<tuple->size; ++i){ DaoValue *value = DaoValue_DeepCopy( tuple->items[i] ); DaoTuple_SetItem( copy, value, i ); } return (DaoValue*) copy; } return NULL; }
static DaoObject* DaoClass_MakeObject( DaoClass *self, DaoValue *param, DaoProcess *proc ) { DaoObject *object = DaoObject_New( self ); DaoProcess_CacheValue( proc, (DaoValue*) object ); if( DaoProcess_PushCallable( proc, self->classRoutines, (DaoValue*)object, & param, 1 ) ==0 ){ GC_ShiftRC( object, proc->topFrame->object ); proc->topFrame->object = object; proc->topFrame->returning = -1; if( DaoProcess_Execute( proc ) ) return object; } return NULL; }
void DaoCallServer_AddWait( DaoProcess *wait, DaoFuture *pre, double timeout ) { DaoTaskEvent *event; DaoCallServer *server = DaoCallServer_TryInit( mainVmSpace );; DaoFuture *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 STD_Eval( DaoProcess *proc, DaoValue *p[], int N ) { DaoVmSpace *vms = proc->vmSpace; DaoNamespace *ns = proc->activeNamespace; DaoStream *prevStream = proc->stdioStream; DaoStream *redirect = (DaoStream*) p[1]; char *source = DaoValue_TryGetMBString( p[0] ); int safe = p[2]->xInteger.value; int wasProt = 0; if( vms->options & DAO_OPTION_SAFE ) wasProt = 1; if( redirect != prevStream ){ GC_ShiftRC( redirect, proc->stdioStream ); proc->stdioStream = redirect; } if( safe ) vms->options |= DAO_OPTION_SAFE; DaoProcess_Eval( proc, ns, source ); DaoProcess_PutValue( proc, proc->stackValues[0] ); if( ! wasProt ) vms->options &= ~DAO_OPTION_SAFE; if( redirect != prevStream ){ GC_ShiftRC( prevStream, proc->stdioStream ); proc->stdioStream = prevStream; } }
void DaoxDataColumn_SetType( DaoxDataColumn *self, DaoType *type ) { int datatype, datasize; DaoxDataColumn_Reset( self, 0 ); if( type == NULL ) type = dao_type_any; datatype = DaoType_GetDataType( type ); datasize = DaoType_GetDataSize( type ); GC_ShiftRC( type, self->type ); self->type = type; self->cells->capacity = (self->cells->capacity * self->cells->stride) / datasize; self->cells->stride = datasize; self->cells->type = datatype; }
void DaoObject_SetParentCdata( DaoObject *self, DaoCdata *parent ) { DaoObject *child = NULL; DaoObject *obj = (DaoObject*) self->parent; DaoValue *sup = self->defClass->parent; if( parent == NULL ) return; if( sup == NULL ) return; if( obj && obj->type == DAO_OBJECT ){ DaoObject_SetParentCdata( obj, parent ); }else if( sup->type == DAO_CTYPE ){ DaoCdata *cdata = (DaoCdata*)sup; if( DaoType_ChildOf( cdata->ctype, parent->ctype ) ){ GC_ShiftRC( parent, self->parent ); self->parent = (DaoValue*) parent; } } }
static int DaoValue_TryCastTuple( DaoValue *src, DaoValue **dest, DaoType *tp ) { DaoTuple *tuple; DaoType **item_types = tp->nested->items.pType; DaoType *totype = src->xTuple.unitype; DaoValue **data = src->xTuple.items; DMap *names = totype ? totype->mapNames : NULL; DNode *node, *search; daoint i, T = tp->nested->size; int tm, eqs = 0; /* auto-cast tuple type, on the following conditions: * (1) the item values of "dest" must match exactly to the item types of "tp"; * (2) "tp->mapNames" must contain "(*dest)->xTuple.unitype->mapNames"; */ if( src->xTuple.unitype == NULL ){ GC_IncRC( tp ); src->xTuple.unitype = tp; return 1; } if( DaoType_MatchValue( tp, src, NULL ) < DAO_MT_SUB ) return 1; /* casting is not necessary if the tuple's field names are a superset of the * field names of the target type: */ if( tp->mapNames == NULL || tp->mapNames->size ==0 ) goto Finalize; if( names ){ daoint count = 0; for(node=DMap_First(names); node; node=DMap_Next(names,node)){ search = DMap_Find( tp->mapNames, node->key.pVoid ); if( search && node->value.pInt != search->value.pInt ) return 0; count += search != NULL; } /* be superset of the field names of the target type: */ if( count == tp->mapNames->size ) goto Finalize; } Finalize: tuple = DaoTuple_New( T ); for(i=0; i<T; i++){ DaoType *it = item_types[i]; if( it->tid == DAO_PAR_NAMED ) it = & it->aux->xType; DaoValue_Move( data[i], tuple->items+i, it ); } GC_IncRC( tp ); tuple->unitype = tp; GC_ShiftRC( tuple, *dest ); *dest = (DaoValue*) tuple; return 1; }
static DaoFuture* DaoCallServer_GetNextFuture() { DaoCallServer *server = daoCallServer; DaoFuture *first, *future, *precond; DArray *events = server->events; DMap *pending = server->pending; DMap *active = server->active; DNode *it; daoint i, j; for(i=0; i<events->size; i++){ DaoTaskEvent *event = (DaoTaskEvent*) events->items.pVoid[i]; DaoFuture *future = event->future; DaoObject *actor = future->actor; DaoChannel *channel = event->channel; DaoChannel *closed = NULL; DaoChannel *chselect = NULL; DaoFuture *futselect = NULL; DaoValue *selected = NULL; DaoValue *message = NULL; int type = event->type; if( event->state == DAO_EVENT_WAIT && future->precond != NULL ){ if( future->precond->state != DAO_CALL_FINISHED ) goto MoveToWaiting; } switch( event->type ){ case DAO_EVENT_WAIT_SENDING : if( channel->buffer->size >= channel->cap ){ if( event->state == DAO_EVENT_WAIT ){ DaoChannel_ActivateEvent( channel, DAO_EVENT_WAIT_RECEIVING ); DaoChannel_ActivateEvent( channel, DAO_EVENT_WAIT_SELECT ); goto MoveToWaiting; } } event->type = DAO_EVENT_RESUME_TASKLET; break; case DAO_EVENT_WAIT_RECEIVING : if( channel->buffer->size == 0 ){ if( channel->cap > 0 && event->state == DAO_EVENT_WAIT ){ DaoChannel_ActivateEvent( channel, DAO_EVENT_WAIT_SENDING ); goto MoveToWaiting; } message = dao_none_value; }else{ message = channel->buffer->items.pValue[0]; } GC_ShiftRC( message, event->message ); event->message = message; event->auxiliary = channel->cap <= 0 && channel->buffer->size == 0; event->type = DAO_EVENT_RESUME_TASKLET; DArray_PopFront( channel->buffer ); if( channel->buffer->size < channel->cap ) DaoChannel_ActivateEvent( channel, DAO_EVENT_WAIT_SENDING ); if( channel->buffer->size ) DaoChannel_ActivateEvent( channel, DAO_EVENT_WAIT_RECEIVING ); break; case DAO_EVENT_WAIT_SELECT : message = dao_none_value; for(it=DaoMap_First(event->selects); it; it=DaoMap_Next(event->selects,it)){ if( DaoValue_CheckCtype( it->key.pValue, dao_type_channel ) ){ DaoChannel *chan = (DaoChannel*) it->key.pValue; if( chan->buffer->size > 0 ){ chselect = chan; selected = it->key.pValue; message = chan->buffer->items.pValue[0]; closed = NULL; break; }else if( chan->cap == 0 ){ closed = chan; } }else{ DaoFuture *fut = (DaoFuture*) it->key.pValue; if( fut->state == DAO_CALL_FINISHED ){ futselect = fut; selected = it->key.pValue; message = fut->value; break; } } } if( selected == NULL ) selected = (DaoValue*) closed; if( event->state == DAO_EVENT_WAIT && event->selects->items->size ){ if( selected == NULL ) goto MoveToWaiting; } GC_ShiftRC( message, event->message ); GC_ShiftRC( selected, event->selected ); event->message = message; event->selected = selected; event->auxiliary = event->selects->items->size == 0; event->type = DAO_EVENT_RESUME_TASKLET; /* change status to not finished: */ if( chselect != NULL || futselect != NULL ) event->auxiliary = 0; if( chselect ){ DArray_PopFront( chselect->buffer ); if( chselect->buffer->size < chselect->cap ) DaoChannel_ActivateEvent( chselect, DAO_EVENT_WAIT_SENDING ); if( chselect->buffer->size ) DaoChannel_ActivateEvent( chselect, DAO_EVENT_WAIT_SELECT ); } if( futselect != NULL || closed != NULL ){ void *key = futselect ? (void*)futselect : (void*)closed; DMap_Erase( event->selects->items, key ); } break; default: break; } if( actor ){ DNode *it = DMap_Find( active, actor->rootObject ); if( actor->rootObject->isAsync ){ if( it && it->value.pVoid != (void*) future ) continue; }else if( it ){ continue; } } if( future->process && DMap_Find( active, future->process ) ) continue; DArray_Erase( events, i, 1 ); DMap_Erase( pending, event ); if( actor ){ void *value = actor->rootObject->isAsync ? future : NULL; DMap_Insert( active, actor->rootObject, value ); } if( future->process ){ DMap_Insert( active, future->process, NULL ); future->process->active = 1; } GC_ShiftRC( event->message, future->message ); GC_ShiftRC( event->selected, future->selected ); future->message = event->message; future->selected = event->selected; future->aux1 = event->auxiliary; future->timeout = event->timeout; GC_IncRC( future ); /* To be decreased at the end of tasklet; */ DaoCallServer_CacheEvent( event ); return future; MoveToWaiting: if( event->expiring >= 0.0 && event->expiring < MIN_TIME ) continue; if( event->expiring >= MIN_TIME ){ DaoComplex com = {DAO_COMPLEX,0,0,0,1,{0.0,0.0}}; com.value.real = event->expiring; DMap_Insert( server->waitings, & com, event ); DCondVar_Signal( & server->condv2 ); }else{ DArray_Append( server->events2, event ); } DArray_Erase( server->events, i, 1 ); i -= 1; } return NULL; }
int DaoClass_AddConst( DaoClass *self, DString *name, DaoValue *data, int s ) { int sto, pm, up, id; DNode *node = MAP_Find( self->lookupTable, name ); DaoNamespace *ns = self->classRoutine->nameSpace; DaoConstant *dest; DaoValue *value; assert( data != NULL ); if( node && LOOKUP_UP( node->value.pInt ) ){ /* inherited field: */ sto = LOOKUP_ST( node->value.pInt ); pm = LOOKUP_PM( node->value.pInt ); id = LOOKUP_ID( node->value.pInt ); if( sto != DAO_CLASS_CONSTANT ){ /* override inherited variable: */ DMap_EraseNode( self->lookupTable, node ); return DaoClass_AddConst( self, name, data, s ); } node->value.pInt = LOOKUP_BIND( sto, pm, 0, id ); dest = self->constants->items.pConst[id]; if( dest->value->type == DAO_ROUTINE && data->type == DAO_ROUTINE ){ /* Add the inherited routine(s) for overloading: */ DaoRoutine *routs = DaoRoutines_New( ns, self->objType, (DaoRoutine*) dest->value ); DaoConstant *cst = DaoConstant_New( (DaoValue*) routs ); GC_ShiftRC( cst, dest ); self->constants->items.pConst[id] = cst; return DaoClass_AddConst( self, name, data, s ); }else{ /* Add the new constant: */ DaoConstant *cst = DaoConstant_New( data ); GC_ShiftRC( cst, dest ); self->constants->items.pConst[id] = cst; return node->value.pInt; } }else if( node ){ sto = LOOKUP_ST( node->value.pInt ); pm = LOOKUP_PM( node->value.pInt ); id = LOOKUP_ID( node->value.pInt ); if( sto != DAO_CLASS_CONSTANT ) return -DAO_CTW_WAS_DEFINED; dest = self->constants->items.pConst[id]; value = dest->value; if( value->type != DAO_ROUTINE || data->type != DAO_ROUTINE ) return -DAO_CTW_WAS_DEFINED; if( s > pm ) node->value.pInt = LOOKUP_BIND( sto, s, 0, id ); if( value->xRoutine.overloads == NULL || value->xRoutine.routHost != self->objType ){ DaoRoutine *routs = DaoRoutines_New( ns, self->objType, (DaoRoutine*) value ); routs->trait |= DAO_VALUE_CONST; /* Add individual entry for the existing function: */ if( value->xRoutine.routHost == self->objType ) DaoClass_AddConst3( self, name, value ); GC_ShiftRC( routs, dest->value ); dest->value = (DaoValue*) routs; } if( data->xRoutine.overloads ){ DaoRoutines_Import( (DaoRoutine*) dest->value, data->xRoutine.overloads ); }else{ DaoRoutine *rout = (DaoRoutine*) data; DRoutines_Add( dest->value->xRoutine.overloads, rout ); if( self->vtable ) DaoRoutine_UpdateVtable( (DaoRoutine*)dest->value, rout, self->vtable ); /* Add individual entry for the new function: */ if( data->xRoutine.routHost == self->objType ) DaoClass_AddConst3( self, name, data ); } return node->value.pInt; } node = MAP_Find( self->lookupTable, name ); if( node && LOOKUP_UP( node->value.pInt ) ) return -DAO_CTW_WAS_DEFINED; return DaoClass_AddConst2( self, name, data, s ); }
static DaoFuture* DaoCallServer_GetNextFuture() { DaoCallServer *server = daoCallServer; DaoFuture *first, *future, *precond; DArray *events = server->events; DMap *pending = server->pending; DMap *active = server->active; daoint i, j; for(i=0; i<events->size; i++){ DaoTaskEvent *event = (DaoTaskEvent*) events->items.pVoid[i]; DaoFuture *future = event->future; DaoChannel *channel = event->channel; DaoChannel *selected = NULL; DaoValue *message = NULL; int closed = 0; switch( event->type ){ case DAO_EVENT_WAIT_SENDING : if( channel->buffer->size >= channel->cap ){ if( event->state == DAO_EVENT_WAIT ) goto MoveToWaiting; } break; case DAO_EVENT_WAIT_RECEIVING : if( channel->buffer->size == 0 ){ if( channel->cap > 0 && event->state == DAO_EVENT_WAIT ) goto MoveToWaiting; message = dao_none_value; }else{ message = channel->buffer->items.pValue[0]; } GC_ShiftRC( message, event->future->message ); event->future->message = message; event->future->aux1 = channel->cap <= 0 && channel->buffer->size == 0; DArray_PopFront( channel->buffer ); if( channel->buffer->size < channel->cap ) DaoChannel_ActivateEvent( channel, DAO_EVENT_WAIT_SENDING ); if( channel->buffer->size ) DaoChannel_ActivateEvent( channel, DAO_EVENT_WAIT_RECEIVING ); break; case DAO_EVENT_WAIT_SELECT : for(j=0; j<event->channels->size; ++j){ DaoChannel *chan = (DaoChannel*) event->channels->items.pValue[j]; if( chan->buffer->size > 0 ){ selected = chan; break; }else if( chan->cap <= 0 ){ closed += 1; } } if( selected == NULL && closed < event->channels->size ){ if( event->state == DAO_EVENT_WAIT ) goto MoveToWaiting; } if( selected == NULL || selected->buffer->size == 0 ){ if( event->state == DAO_EVENT_WAIT ) goto MoveToWaiting; message = dao_none_value; }else{ message = selected->buffer->items.pValue[0]; } GC_ShiftRC( message, event->future->message ); GC_ShiftRC( selected, event->future->selected ); event->future->message = message; event->future->selected = (DaoValue*) selected; event->future->aux1 = closed == event->channels->size; if( selected ){ DArray_PopFront( selected->buffer ); if( selected->buffer->size < selected->cap ) DaoChannel_ActivateEvent( selected, DAO_EVENT_WAIT_SENDING ); if( selected->buffer->size ) DaoChannel_ActivateEvent( selected, DAO_EVENT_WAIT_SELECT ); } break; default: break; } if( event->state == DAO_EVENT_WAIT && future->precond != NULL ){ if( future->precond->state != DAO_CALL_FINISHED ) goto MoveToWaiting; } if( future->actor && DMap_Find( active, future->actor->rootObject ) ) continue; if( future->process && DMap_Find( active, future->process ) ) continue; DArray_Erase( events, i, 1 ); DMap_Erase( pending, event ); if( future->actor ) DMap_Insert( active, future->actor->rootObject, NULL ); if( future->process ) DMap_Insert( active, future->process, NULL ); GC_IncRC( future ); /* To be decreased at the end of tasklet; */ future->timeout = event->timeout; DaoCallServer_CacheEvent( event ); return future; MoveToWaiting: if( event->expiring >= 0.0 && event->expiring < MIN_TIME ) continue; if( event->expiring >= MIN_TIME ){ DaoComplex com = {DAO_COMPLEX,0,0,0,1,{0.0,0.0}}; com.value.real = event->expiring; DMap_Insert( server->waitings, & com, event ); DCondVar_Signal( & server->condv2 ); }else{ DArray_Append( server->events2, event ); } DArray_Erase( server->events, i, 1 ); i -= 1; } return NULL; }
int DaoValue_Move4( DaoValue *S, DaoValue **D, DaoType *T, DMap *defs, DaoDataCache *cache ) { int tm = 1; switch( (T->tid << 8) | S->type ){ case (DAO_INTEGER << 8) | DAO_INTEGER : case (DAO_INTEGER << 8) | DAO_FLOAT : case (DAO_INTEGER << 8) | DAO_DOUBLE : case (DAO_FLOAT << 8) | DAO_INTEGER : case (DAO_FLOAT << 8) | DAO_FLOAT : case (DAO_FLOAT << 8) | DAO_DOUBLE : case (DAO_DOUBLE << 8) | DAO_INTEGER : case (DAO_DOUBLE << 8) | DAO_FLOAT : case (DAO_DOUBLE << 8) | DAO_DOUBLE : case (DAO_COMPLEX << 8) | DAO_COMPLEX : case (DAO_LONG << 8) | DAO_LONG : case (DAO_STRING << 8) | DAO_STRING : S = DaoValue_SimpleCopyWithTypeX( S, T, cache ); GC_ShiftRC( S, *D ); *D = S; return 1; } if( !(S->xTuple.trait & DAO_VALUE_CONST) ){ DaoType *ST = NULL; switch( (S->type << 8) | T->tid ){ case (DAO_TUPLE<<8)|DAO_TUPLE : ST = S->xTuple.unitype; break; case (DAO_ARRAY<<8)|DAO_ARRAY : ST = dao_array_types[ S->xArray.etype ]; break; case (DAO_LIST <<8)|DAO_LIST : ST = S->xList.unitype; break; case (DAO_MAP <<8)|DAO_MAP : ST = S->xMap.unitype; break; case (DAO_CDATA<<8)|DAO_CDATA : ST = S->xCdata.ctype; break; case (DAO_CSTRUCT<<8)|DAO_CSTRUCT : ST = S->xCstruct.ctype; break; case (DAO_OBJECT<<8)|DAO_OBJECT : ST = S->xObject.defClass->objType; break; } if( ST == T ){ DaoValue *D2 = *D; GC_ShiftRC( S, D2 ); *D = S; return 1; } } if( (T->tid == DAO_OBJECT || T->tid == DAO_CDATA || T->tid == DAO_CSTRUCT) && S->type == DAO_OBJECT ){ if( S->xObject.defClass != & T->aux->xClass ){ S = DaoObject_CastToBase( S->xObject.rootObject, T ); tm = (S != NULL); } }else if( (T->tid == DAO_CLASS || T->tid == DAO_CTYPE) && S->type == DAO_CLASS ){ if( S->xClass.clsType != T && T->aux != NULL ){ /* T->aux == NULL for "class"; */ S = DaoClass_CastToBase( (DaoClass*)S, T ); tm = (S != NULL); } }else if( T->tid == DAO_CTYPE && S->type == DAO_CTYPE ){ if( S->xCtype.ctype != T ){ S = DaoType_CastToParent( S, T ); tm = (S != NULL); } }else if( T->tid == DAO_ROUTINE && T->overloads == 0 && S->type == DAO_ROUTINE && S->xRoutine.overloads ){ DArray *routines = S->xRoutine.overloads->routines; int i, k, n; /* // Do not use DaoRoutine_ResolveByType( S, ... ) // "S" should match to "T", not the other way around! */ tm = 0; for(i=0,n=routines->size; i<n; i++){ DaoRoutine *rout = routines->items.pRoutine[i]; k = rout->routType == T ? DAO_MT_EQ : DaoType_MatchTo( rout->routType, T, defs ); if( k > tm ) tm = k; if( rout->routType == T ){ S = (DaoValue*) rout; break; } } }else{ tm = DaoType_MatchValue( T, S, defs ); } #if 0 if( tm ==0 ){ printf( "T = %p; S = %p, type = %i %i\n", T, S, S->type, DAO_ROUTINE ); printf( "T: %s %i %i\n", T->name->mbs, T->tid, tm ); if( S->type == DAO_LIST ) printf( "%s\n", S->xList.unitype->name->mbs ); if( S->type == DAO_TUPLE ) printf( "%p\n", S->xTuple.unitype ); } printf( "S->type = %p %s %i\n", S, T->name->mbs, tm ); #endif if( tm == 0 ) return 0; /* composite known types must match exactly. example, * where it will not work if composite types are allowed to match loosely. * d : list<list<int>> = {}; * e : list<float> = { 1.0 }; * d.append( e ); * * but if d is of type list<list<any>>, * the matching do not necessary to be exact. */ S = DaoValue_SimpleCopyWithTypeX( S, T, cache ); GC_ShiftRC( S, *D ); *D = S; if( S->type == DAO_TUPLE && S->xTuple.unitype != T && tm >= DAO_MT_SIM ){ return DaoValue_TryCastTuple( S, D, T ); }else if( T && T->tid == S->type && !(T->attrib & DAO_TYPE_SPEC) ){ DaoValue_SetType( S, T ); } return 1; }
int DaoClass_AddConst( DaoClass *self, DString *name, DaoValue *data, int s ) { int fromMixin = 0; int fromParent = 0; int sto, pm, up, id; DNode *node = MAP_Find( self->lookupTable, name ); DaoNamespace *ns = self->classRoutine->nameSpace; DaoConstant *dest; DaoValue *value; if( node ){ id = LOOKUP_ID( node->value.pInt ); fromParent = LOOKUP_UP( node->value.pInt ); /* From parent classes; */ switch( LOOKUP_ST( node->value.pInt ) ){ /* Check if it is from mixins; */ case DAO_CLASS_CONSTANT : fromMixin = id >= self->cstMixinStart && id < self->cstMixinEnd; break; case DAO_CLASS_VARIABLE : fromMixin = id >= self->glbMixinStart && id < self->glbMixinEnd; break; case DAO_OBJECT_VARIABLE : fromMixin = id >= self->objMixinStart && id < self->objMixinEnd; break; } } assert( data != NULL ); if( fromParent || fromMixin ){ /* inherited field: */ sto = LOOKUP_ST( node->value.pInt ); pm = LOOKUP_PM( node->value.pInt ); id = LOOKUP_ID( node->value.pInt ); if( sto != DAO_CLASS_CONSTANT ){ /* override inherited variable: */ DMap_EraseNode( self->lookupTable, node ); return DaoClass_AddConst( self, name, data, s ); } node->value.pInt = LOOKUP_BIND( sto, pm, 0, id ); dest = self->constants->items.pConst[id]; if( dest->value->type == DAO_ROUTINE && data->type == DAO_ROUTINE ){ /* Add the inherited routine(s) for overloading: */ DaoRoutine *routs = DaoRoutines_New( ns, self->objType, (DaoRoutine*)dest->value ); DaoConstant *cst = DaoConstant_New( (DaoValue*) routs ); routs->trait |= DAO_VALUE_CONST; node->value.pInt = LOOKUP_BIND( sto, pm, 0, self->constants->size ); DArray_Append( self->cstDataName, (void*) name ); DArray_Append( self->constants, cst ); return DaoClass_AddConst( self, name, data, s ); }else{ /* Add the new constant: */ DaoConstant *cst = DaoConstant_New( data ); node->value.pInt = LOOKUP_BIND( sto, pm, 0, self->constants->size ); DArray_Append( self->cstDataName, (void*) name ); DArray_Append( self->constants, cst ); return node->value.pInt; } }else if( node ){ sto = LOOKUP_ST( node->value.pInt ); pm = LOOKUP_PM( node->value.pInt ); id = LOOKUP_ID( node->value.pInt ); if( sto != DAO_CLASS_CONSTANT ) return -DAO_CTW_WAS_DEFINED; dest = self->constants->items.pConst[id]; value = dest->value; if( value->type != DAO_ROUTINE || data->type != DAO_ROUTINE ) return -DAO_CTW_WAS_DEFINED; if( s > pm ) node->value.pInt = LOOKUP_BIND( sto, s, 0, id ); if( value->xRoutine.overloads == NULL || value->xRoutine.routHost != self->objType ){ DaoRoutine *routs = DaoRoutines_New( ns, self->objType, (DaoRoutine*) value ); routs->trait |= DAO_VALUE_CONST; /* Add individual entry for the existing function: */ if( value->xRoutine.routHost == self->objType ) DaoClass_AddConst3( self, name, value ); GC_ShiftRC( routs, dest->value ); dest->value = (DaoValue*) routs; } if( data->xRoutine.overloads ){ DaoRoutines_Import( (DaoRoutine*) dest->value, data->xRoutine.overloads ); }else{ DaoRoutine *rout = (DaoRoutine*) data; DRoutines_Add( dest->value->xRoutine.overloads, rout ); /* Add individual entry for the new function: */ if( data->xRoutine.routHost == self->objType ) DaoClass_AddConst3( self, name, data ); } return node->value.pInt; } node = MAP_Find( self->lookupTable, name ); if( node && LOOKUP_UP( node->value.pInt ) ) return -DAO_CTW_WAS_DEFINED; return DaoClass_AddConst2( self, name, data, s ); }
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 = DaoGetSectionCode( proc->activeCode ); 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_APPLY : DaoProcess_PutValue( proc, param ); break; case DVM_FUNCT_FIND : DaoProcess_PutValue( proc, dao_none_value ); break; } if( threads <= 0 ) threads = 2; if( sect == NULL || DaoMT_PushSectionFrame( proc ) == 0 ) return; if( list ){ DArray_Clear( & list->items ); if( param->type == DAO_LIST ) DArray_Resize( & list->items, param->xList.items.size, NULL ); if( param->type == DAO_MAP ) DArray_Resize( & list->items, param->xMap.items->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 ); task->clone->mutex = & mutex; if( i ) DaoCallServer_AddTask( DaoMT_RunFunctional, task, 1 ); } 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, 0 ); if( param->type == DAO_LIST && index != -1 ){ DaoValue **items = param->xList.items.items.pValue; GC_ShiftRC( items[index], tuple->items[1] ); tuple->items[1] = items[index]; tuple->items[0]->xInteger.value = index; }else if( param->type == DAO_MAP && node ){ GC_ShiftRC( node->key.pValue, tuple->items[0] ); GC_ShiftRC( node->value.pValue, tuple->items[1] ); tuple->items[0] = node->key.pValue; tuple->items[1] = node->value.pValue; } } if( status ) DaoProcess_RaiseException( proc, DAO_ERROR, "code section execution failed!" ); DMutex_Destroy( & mutex ); DCondVar_Destroy( & condv ); dao_free( tasks ); }