void DaoCinType_DeriveMethods( DaoCinType *self ) { daoint i, k, m, N = self->supers->size; DaoCinType *super; DNode *it; for(i=0; i<N; i++){ super = (DaoCinType*) self->supers->items.pValue[i]; self->citype->bases = DList_New( DAO_DATA_VALUE ); self->vatype->bases = DList_New( DAO_DATA_VALUE ); DList_Append( self->citype->bases, super->citype ); DList_Append( self->vatype->bases, super->vatype ); for(it=DMap_First(super->methods); it; it=DMap_Next( super->methods, it )){ if( it->value.pRoutine->overloads ){ DRoutines *routs = it->value.pRoutine->overloads; for(k=0,m=routs->routines->size; k<m; k++){ DaoRoutine *rout = routs->routines->items.pRoutine[i]; DaoMethods_Insert( self->methods, rout, NULL, self->vatype ); } }else{ DaoMethods_Insert( self->methods, it->value.pRoutine, NULL, self->vatype ); } } } self->derived = 1; }
/* // Only activate one event per channel: */ void DaoChannel_ActivateEvent( DaoChannel *self, int type ) { DaoCallServer *server = daoCallServer; DNode *node; daoint i; for(i=0; i<server->events2->size; ++i){ DaoTaskEvent *event = (DaoTaskEvent*) server->events2->items.pVoid[i]; if( event->type != type ) continue; if( DaoCallServer_CheckEvent( event, NULL, self ) ){ DList_Append( server->events, event ); DList_Erase( server->events2, i, 1 ); return; } } for(node=DMap_First(server->waitings); node; node=DMap_Next(server->waitings,node)){ DaoTaskEvent *event = (DaoTaskEvent*) node->value.pValue; if( event->type != type ) continue; if( DaoCallServer_CheckEvent( event, NULL, self ) ){ DList_Append( server->events, event ); DMap_EraseNode( server->waitings, node ); return; } } }
DaoCinType* DaoCinType_New( DaoInterface *inter, DaoType *target ) { DaoCinType *self = (DaoCinType*) dao_calloc( 1, sizeof(DaoCinType) ); DaoValue_Init( self, DAO_CINTYPE ); self->trait |= DAO_VALUE_DELAYGC; self->derived = 0; self->supers = DList_New( DAO_DATA_VALUE ); self->methods = DHash_New( DAO_DATA_STRING, DAO_DATA_VALUE ); self->citype = DaoType_New( "interface<", DAO_CINTYPE, (DaoValue*)self, NULL ); self->vatype = DaoType_New( inter->abtype->name->chars, DAO_CINVALUE, (DaoValue*)self, NULL ); self->abstract = inter; self->target = target; GC_IncRC( self->citype ); GC_IncRC( self->vatype ); GC_IncRC( self->abstract ); GC_IncRC( self->target ); self->citype->nested = DList_New( DAO_DATA_VALUE ); self->vatype->nested = DList_New( DAO_DATA_VALUE ); DList_Append( self->citype->nested, target ); DList_Append( self->vatype->nested, target ); DString_AppendChar( self->vatype->name, '<' ); DString_Append( self->vatype->name, target->name ); DString_AppendChar( self->vatype->name, '>' ); DString_Append( self->citype->name, self->vatype->name ); DString_AppendChar( self->citype->name, '>' ); #ifdef DAO_USE_GC_LOGGER DaoObjectLogger_LogNew( (DaoValue*) self ); #endif return self; }
/* // Activate all events waiting on a future value: */ void DaoFuture_ActivateEvent( DaoFuture *self ) { DaoCallServer *server = daoCallServer; DList *array = DList_New(0); DNode *node; daoint i; DMutex_Lock( & server->mutex ); for(i=0; i<server->events2->size; ++i){ DaoTaskEvent *event = (DaoTaskEvent*) server->events2->items.pVoid[i]; if( DaoCallServer_CheckEvent( event, self, NULL ) ){ event->state = DAO_EVENT_RESUME; DList_Append( server->events, event ); DList_Erase( server->events2, i, 1 ); i -= 1; } } for(node=DMap_First(server->waitings); node; node=DMap_Next(server->waitings,node)){ DaoTaskEvent *event = (DaoTaskEvent*) node->value.pValue; /* remove from timed waiting list: */ if( DaoCallServer_CheckEvent( event, self, NULL ) ){ event->state = DAO_EVENT_RESUME; DList_Append( server->events, event ); DList_Append( array, node->key.pVoid ); } } for(i=0; i<array->size; i++) DMap_Erase( server->waitings, array->items.pVoid[i] ); DCondVar_Signal( & server->condv ); DMutex_Unlock( & server->mutex ); DList_Delete( array ); }
static void DaoxGraph_HandleGC( DaoValue *p, DList *values, DList *arrays, DList *maps, int remove ) { daoint i, n; DaoxGraph *self = (DaoxGraph*) p; DList_Append( arrays, self->nodes ); DList_Append( arrays, self->edges ); if( self->nodeType ) DList_Append( values, self->nodeType ); if( self->edgeType ) DList_Append( values, self->edgeType ); if( remove ){ self->nodeType = NULL; self->edgeType = NULL; for(i=0,n=self->nodes->size; i<n; i++){ DaoxNode *node = self->nodes->items.pgNode[i]; if( node->ins ) DList_Clear( node->ins ); DList_Clear( node->outs ); node->graph = NULL; } for(i=0,n=self->edges->size; i<n; i++){ DaoxEdge *edge = self->edges->items.pgEdge[i]; edge->graph = NULL; edge->first = NULL; edge->second = NULL; } } }
static void DaoxWindow_GetGCFields( void *p, DList *values, DList *lists, DList *maps, int remove ) { DaoxWindow *self = (DaoxWindow*) p; DList_Append( values, self->context ); if( self->painter ) DList_Append( values, self->painter ); if( self->renderer ) DList_Append( values, self->renderer ); if( self->widget ) DList_Append( values, self->widget ); if( self->model ) DList_Append( values, self->model ); if( remove ){ self->context = NULL; self->painter = NULL; self->renderer = NULL; self->widget = NULL; self->model = NULL; } }
static void DMap_SortMethods( DMap *hash, DList *methods ) { DMap *map = DMap_New( DAO_DATA_STRING, 0 ); DString *name = DString_New(); DNode *it; daoint i, n; for(it=DMap_First(hash); it; it=DMap_Next(hash,it)){ if( it->value.pRoutine->overloads ){ DRoutines *one = it->value.pRoutine->overloads; for(i=0,n=one->routines->size; i<n; i++){ DaoRoutine *rout = one->routines->items.pRoutine[i]; DString_Assign( name, rout->routName ); DString_AppendChars( name, " " ); DString_Append( name, rout->routType->name ); DMap_Insert( map, name, (void*)rout ); } }else{ DaoRoutine *rout = it->value.pRoutine; DString_Assign( name, rout->routName ); DString_AppendChars( name, " " ); DString_Append( name, rout->routType->name ); DMap_Insert( map, name, (void*)rout ); } } DList_Clear( methods ); for(it=DMap_First(map); it; it=DMap_Next(map,it)) DList_Append( methods, it->value.pVoid ); DMap_Delete( map ); DString_Delete( name ); }
static void DaoSTD_Error3( DaoProcess *proc, DaoValue *p[], int n ) { DaoType *etype = p[0]->xCtype.cdtype; DaoException *exception = DaoException_New( etype ); DaoException_Init( exception, proc, p[1]->xString.value->chars, p[2] ); DList_Append( proc->exceptions, exception ); }
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_PutInteger( 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 ); DMutex_Lock( & daoCallServer->mutex ); DList_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 ); } }
static void DaoSTD_Error( DaoProcess *proc, DaoValue *p[], int n ) { DaoType *etype = DaoVmSpace_MakeExceptionType( proc->vmSpace, "Exception::Error" ); DaoException *exception = DaoException_New( etype ); DaoException_Init( exception, proc, p[0]->xString.value->chars, NULL ); DList_Append( proc->exceptions, exception ); }
void DaoChannel_Send( DaoChannel *self, DaoValue *data ) { DMutex_Lock( & daoCallServer->mutex ); DList_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 ); }
DaoCinType* DaoCinType_New( DaoInterface *inter, DaoType *target ) { DaoCinType *self = (DaoCinType*) dao_calloc( 1, sizeof(DaoCinType) ); DaoNamespace *ns = inter->nameSpace; DString *name = inter->abtype->name; DaoValue_Init( self, DAO_CINTYPE ); self->trait |= DAO_VALUE_DELAYGC; self->derived = 0; self->bases = DList_New( DAO_DATA_VALUE ); self->methods = DHash_New( DAO_DATA_STRING, DAO_DATA_VALUE ); self->citype = DaoType_New( ns, "interface<", DAO_CINTYPE, (DaoValue*)self, NULL ); self->vatype = DaoType_New( ns, name->chars, DAO_CINVALUE, (DaoValue*)self, NULL ); self->abstract = inter; self->target = target; self->citype->core = & daoCinTypeCore; self->vatype->core = & daoCinValueCore; GC_IncRC( self->citype ); GC_IncRC( self->vatype ); GC_IncRC( self->abstract ); GC_IncRC( self->target ); self->vatype->kernel = DaoTypeKernel_New( NULL ); self->vatype->kernel->abtype = self->vatype; GC_IncRC( self->vatype->kernel ); GC_IncRC( self->vatype ); self->citype->args = DList_New( DAO_DATA_VALUE ); self->vatype->args = DList_New( DAO_DATA_VALUE ); DList_Append( self->citype->args, target ); DList_Append( self->vatype->args, target ); DString_AppendChar( self->vatype->name, '<' ); DString_Append( self->vatype->name, target->name ); DString_AppendChar( self->vatype->name, '>' ); DString_Append( self->citype->name, self->vatype->name ); DString_AppendChar( self->citype->name, '>' ); #ifdef DAO_USE_GC_LOGGER DaoObjectLogger_LogNew( (DaoValue*) self ); #endif return self; }
void DaoCallServer_AddTask( DThreadTask func, void *param, int now ) { int scheduled = 0; DaoCallServer *server = DaoCallServer_TryInit( mainVmSpace ); DMutex_Lock( & server->mutex ); if( server->idle > server->parameters->size || now == 0 ){ scheduled = 1; DList_Append( server->functions, func ); DList_Append( server->parameters, param ); DMap_Insert( server->pending, param, NULL ); DCondVar_Signal( & server->condv ); } DMutex_Unlock( & server->mutex ); if( scheduled ){ if( now == 0 ) DaoCallServer_TryAddThread( NULL, NULL, server->parameters->size ); }else{ DaoCallServer_AddThread( func, param ); } }
static void DaoCallServer_ActivateEvents() { DaoCallServer *server = daoCallServer; char message[128]; daoint i, j, count = 0; if( server->finishing == 0 ) return; if( server->idle != server->total ) return; if( server->events->size != 0 ) return; if( server->events2->size == 0 ) return; #ifdef DEBUG sprintf( message, "WARNING: try activating events (%i,%i,%i,%i)!\n", server->total, server->idle, (int)server->events->size, (int)server->events2->size ); DaoStream_WriteChars( mainVmSpace->errorStream, message ); #endif for(i=0; i<server->events2->size; ++i){ DaoTaskEvent *event = (DaoTaskEvent*) server->events2->items.pVoid[i]; DaoChannel *chan = event->channel; DaoFuture *fut = event->future; int move = 0, closed = 0; switch( event->type ){ case DAO_EVENT_WAIT_TASKLET : move = fut->precond == NULL || fut->precond->state == DAO_CALL_FINISHED; break; case DAO_EVENT_WAIT_RECEIVING : move = chan->buffer->size > 0; if( chan->cap <= 0 && chan->buffer->size == 0 ) move = 1; break; case DAO_EVENT_WAIT_SENDING : move = chan->buffer->size < chan->cap; break; case DAO_EVENT_WAIT_SELECT : if( event->selects == NULL ) continue; move = DaoTaskEvent_CheckSelect( event ); break; default: break; } if( move ){ DList_Append( server->events, event ); DList_Erase( server->events2, i, 1 ); count += 1; i -= 1; } } DCondVar_Signal( & server->condv ); if( count == 0 ){ DaoStream *stream = mainVmSpace->errorStream; DaoStream_WriteChars( stream, "ERROR: All tasklets are suspended - deadlock!\n" ); #if DEBUG fprintf( stderr, "ERROR: All tasklets are suspended - deadlock!\n" ); #endif exit(1); } }
void DaoVmSpace_AddTaskletJob( DaoVmSpace *self, DThreadTask func, void *param, void *proc ) { int scheduled = 0; DaoTaskletServer *server = DaoTaskletServer_TryInit( self ); DMutex_Lock( & server->mutex ); if( server->vacant > server->parameters->size || proc == NULL ){ scheduled = 1; DList_Append( server->functions, func ); DList_Append( server->parameters, param ); DList_Append( server->owners, proc ); DMap_Insert( server->pending, param, NULL ); DCondVar_Signal( & server->condv ); } DMutex_Unlock( & server->mutex ); if( scheduled ){ if( proc == NULL ){ DaoVmSpace_TryAddTaskletThread( self, NULL, NULL, server->parameters->size ); } }else{ DaoVmSpace_AddTaskletThread( self, func, param, proc ); } }
void DaoCallServer_AddThread( DThreadTask func, void *param ) { DaoCallThread *calth; DaoCallServer_TryInit( mainVmSpace ); calth = DaoCallThread_New( func, param ); DMutex_Lock( & daoCallServer->mutex ); daoCallServer->total += 1; DList_Append( daoCallServer->threads, calth ); DMutex_Unlock( & daoCallServer->mutex ); if( DThread_Start( & calth->thread, (DThreadTask) DaoCallThread_Run, calth ) == 0 ){ if( func != NULL || daoCallServer->total == 0 ){ dao_abort( "failed to create a task thread" ); } } }
void DaoVmSpace_AddTaskletThread( DaoVmSpace *self, DThreadTask func, void *param, void *proc ) { DaoTaskletThread *taskthd; DaoTaskletServer *server = DaoTaskletServer_TryInit( self ); taskthd = DaoTaskletThread_New( server, func, param ); taskthd->taskOwner = proc; DMutex_Lock( & server->mutex ); server->total += 1; DList_Append( server->threads, taskthd ); DMutex_Unlock( & server->mutex ); if( DThread_Start( & taskthd->thread, (DThreadTask) DaoTaskletThread_Run, taskthd ) == 0 ){ if( func != NULL || server->total == 0 ){ dao_abort( "failed to create a task thread" ); } } }
DaoxEdge* DaoxGraph_AddEdge( DaoxGraph *self, DaoxNode *first, DaoxNode *second ) { DaoxEdge *edge = DaoxEdge_New( self ); DList_PushFront( first->outs, edge ); if( self->directed ){ if( second->ins == NULL ) second->ins = DList_New(DAO_DATA_VALUE); DList_PushBack( second->ins, edge ); }else{ DList_PushBack( second->outs, edge ); } DList_Append( self->edges, edge ); edge->first = first; edge->second = second; return edge; }
void DaoXmlDOM_CacheNode( DaoXmlDOM *self, DaoXmlNode *node ) { daoint i; for(i=0; i<node->children->size; ++i){ DaoXmlDOM_CacheNode( self, (DaoXmlNode*) node->children->items.pVoid[i] ); } node->id = 0; node->parent = NULL; node->data = NULL; node->children->size = 0; node->name->size = 0; /* Most nodes will have empty contents, and some may have long contents, // so it is better to clear the string: */ DString_Clear( node->content ); DMap_Reset( node->attributes ); DList_Append( self->caches, node ); }
static void DaoCallServer_Timer( void *p ) { DaoCallServer *server = daoCallServer; double time = 0.0; daoint i, timeout; server->timing = 1; while( server->finishing == 0 || server->stopped != server->total ){ DMutex_Lock( & server->mutex ); while( server->waitings->size == 0 ){ if( server->idle == server->total && server->events2->size ){ DaoCallServer_ActivateEvents(); } if( server->finishing && server->stopped == server->total ) break; DCondVar_TimedWait( & server->condv2, & server->mutex, 0.01 ); } if( server->waitings->size ){ DNode *node = DMap_First( server->waitings ); time = node->key.pComplex->real; time -= Dao_GetCurrentTime(); /* wait the right amount of time for the closest arriving timeout: */ if( time > 0 ) DCondVar_TimedWait( & server->condv2, & server->mutex, time ); } DMutex_Unlock( & server->mutex ); if( server->finishing && server->stopped == server->total ) break; DMutex_Lock( & server->mutex ); if( server->waitings->size ){ /* a new wait timed out: */ DNode *node = DMap_First( server->waitings ); time = Dao_GetCurrentTime(); if( node->key.pComplex->real < time ){ DaoTaskEvent *event = (DaoTaskEvent*) node->value.pVoid; event->state = DAO_EVENT_RESUME; event->timeout = 1; event->expiring = MIN_TIME; DList_Append( server->events, node->value.pVoid ); DMap_EraseNode( server->waitings, node ); } } DCondVar_Signal( & server->condv ); DMutex_Unlock( & server->mutex ); } server->timing = 0; }
static void GRAPH_RemoveSingletonNodes( DaoProcess *proc, DaoValue *p[], int N ) { DaoxGraph *self = (DaoxGraph*) p[0]; DaoxGraph *save = (DaoxGraph*) p[1]; daoint i, k, n, removed = 0; for(i=0,k=0,n=self->nodes->size; i<n; i++){ DaoxNode *node = (DaoxNode*) self->nodes->items.pVoid[i]; /* Ensure no duplication of the reference (for the Concurrent GC): */ self->nodes->items.pVoid[i] = NULL; if( (node->ins->size + node->outs->size) == 0 ){ if( save ) DList_Append( save->nodes, node ); GC_DecRC( node ); continue; } self->nodes->items.pVoid[k++] = node; } DaoProcess_PutInteger( proc, self->nodes->size - k ); self->nodes->size = k; }
void DList_Assign( DList *left, DList *right ) { daoint i; assert( left->type == right->type || (left->type == DAO_DATA_VALUE && right->type == 0) ); if( left == right ) return; if( right->size == 0 ){ DList_Clear( left ); return; } if( left->type ){ DList_Clear( left); for( i=0; i<right->size; i++ ) DList_Append( left, right->items.pVoid[i] ); }else{ DList_Resize( left, right->size, NULL ); if( left->type == DAO_DATA_VALUE ) DaoGC_LockData(); for( i=0; i<right->size; i++ ) left->items.pVoid[i] = right->items.pVoid[i]; if( left->type == DAO_DATA_VALUE ) DaoGC_UnlockData(); } }
int DaoXmlParser_ParseNodeContent( DaoXmlParser *self, DaoXmlDOM *dom, DaoXmlNode *node ) { DaoXmlNode *child; while( self->source < self->end ){ if( DaoXmlParser_SkipWhiteSpaces( self ) ) return 1; if( self->source >= self->end ) return 1; if( *self->source == '<' ){ char *current = self->source; self->source += 1; if( DaoXmlParser_SkipWhiteSpaces( self ) ) return 1; if( *self->source == '/' ){ self->source = current; return 0; }else if( *self->source == '!' ){ self->source += 1; if( strncmp( self->source, "[CDATA[", 7 ) == 0 ){ self->source = strstr( self->source + 7, "]]>" ); if( self->source == NULL ) return 1; self->source += 3; continue; }else if( strncmp( self->source, "--", 2 ) == 0 ){ self->source = strstr( self->source + 7, "-->" ); if( self->source == NULL ) return 1; self->source += 3; continue; } } child = DaoXmlDOM_NewNode( dom ); child->parent = node; DList_Append( node->children, child ); self->source = current; DaoXmlParser_ParseNode( self, dom, child ); }else{ while( self->source < self->end && *self->source != '<' ){ if( DaoXmlParser_ParseFormatedChar( self, node->content ) ) return 1; } } } return 0; }
static void DaoFuture_GetGCFields( void *p, DList *values, DList *lists, DList *maps, int remove ) { DaoFuture *self = (DaoFuture*) p; if( self->value ) DList_Append( values, self->value ); if( self->actor ) DList_Append( values, self->actor ); if( self->message ) DList_Append( values, self->message ); if( self->selected ) DList_Append( values, self->selected ); if( self->process ) DList_Append( values, self->process ); if( self->precond ) DList_Append( values, self->precond ); if( remove ){ self->value = NULL; self->actor = NULL; self->message = NULL; self->selected = NULL; self->process = NULL; self->precond = NULL; } }
static void DaoSTD_Assert( DaoProcess *proc, DaoValue *p[], int n ) { DaoType *etype; DaoException *exception; DaoRoutine *rout = proc->activeRoutine; DString *file = proc->activeNamespace->name; int line, id = (ushort_t) (proc->activeCode - proc->topFrame->active->codes); if( p[0]->xBoolean.value ) return; line = rout->defLine; if( id < rout->body->vmCodes->size ) line = rout->body->annotCodes->items.pVmc[id]->line; etype = DaoVmSpace_MakeExceptionType( proc->vmSpace, "Error::Assertion" ); exception = DaoException_New( etype ); DList_Append( proc->exceptions, exception ); DaoException_Init( exception, proc, NULL, NULL ); DString_Reserve( exception->info, file->size + 100 ); id = sprintf( exception->info->chars, dao_assertion_format, line, file->chars ); if( id ) exception->info->size = id; DString_Append( exception->info, p[1]->xString.value ); }
void DaoInterface_DeriveMethods( DaoInterface *self ) { daoint i, k, m, N = self->bases->size; DaoNamespace *ns = self->nameSpace; DaoInterface *base; DNode *it; for(i=0; i<N; i++){ base = (DaoInterface*) self->bases->items.pValue[i]; if( self->abtype->bases == NULL ) self->abtype->bases = DList_New( DAO_DATA_VALUE ); DList_Append( self->abtype->bases, base->abtype ); for(it=DMap_First(base->methods); it; it=DMap_Next( base->methods, it )){ if( it->value.pRoutine->overloads ){ DRoutines *routs = it->value.pRoutine->overloads; for(k=0,m=routs->routines->size; k<m; k++){ DaoRoutine *rout = routs->routines->items.pRoutine[i]; DaoMethods_Insert( self->methods, rout, ns, self->abtype ); } }else{ DaoMethods_Insert( self->methods, it->value.pRoutine, ns, self->abtype ); } } } self->derived = 1; }
static DaoFuture* DaoCallServer_GetNextFuture() { DaoCallServer *server = daoCallServer; DaoFuture *first, *future, *precond; DList *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_Assign( & event->message, message ); event->auxiliary = channel->cap <= 0 && channel->buffer->size == 0; event->type = DAO_EVENT_RESUME_TASKLET; DList_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->value->size ){ if( selected == NULL ) goto MoveToWaiting; } GC_Assign( & event->message, message ); GC_Assign( & event->selected, selected ); event->auxiliary = event->selects->value->size == 0; event->type = DAO_EVENT_RESUME_TASKLET; /* change status to not finished: */ if( chselect != NULL || futselect != NULL ) event->auxiliary = 0; if( chselect ){ DList_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->value, 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; DList_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; } /* // DaoValue_Move() should be used instead of GC_Assign() for thread safety. // Because using GC_Assign() here, may caused "future->message" of primitive // type being deleted, right after DaoFuture_GetGCFields() has retrieved it // for GC scanning. */ DaoValue_Move( event->message, & future->message, NULL ); DaoValue_Move( event->selected, & future->selected, NULL ); 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 ){ dao_complex com = {0.0,0.0}; com.real = event->expiring; DMap_Insert( server->waitings, & com, event ); DCondVar_Signal( & server->condv2 ); }else{ DList_Append( server->events2, event ); } DList_Erase( server->events, i, 1 ); i -= 1; } return NULL; }
static void DaoChannel_GetGCFields( void *p, DList *vs, DList *lists, DList *ms, int rm ) { DaoChannel *self = (DaoChannel*) p; DList_Append( lists, self->buffer ); }
bool DaoxDebugger::EditContinue ( DaoProcess *process, int newEntryLine, QList<int> & lineMap, QStringList & newCodes, QStringList & routCodes ) { DaoRoutine *oldrout = process->activeRoutine; int i, j, k, dest = 0; //printf( "=======%s\n", routCodes.join("\n").toLocal8Bit().data() ); //printf( "=======%s\n", newCodes.join("\n").toLocal8Bit().data() ); if( routCodes.size() == newCodes.size() ){ DaoLexer *lexer = DaoLexer_New(); bool eq = true; for(i=0; i<routCodes.size(); i++){ QString s1 = NormalizeCodes( routCodes[i], lexer ); QString s2 = NormalizeCodes( newCodes[i], lexer ); if( s1 != s2 ){ eq = false; break; } } DaoLexer_Delete( lexer ); if( eq ) return true; } QString codes = newCodes.join( "\n" ); DaoParser *parser = DaoParser_New(); DaoRoutine *routine = DaoRoutine_New( oldrout->nameSpace, oldrout->routHost, 1 ); routine->routType = oldrout->routType; routine->parCount = oldrout->parCount; routine->attribs = oldrout->attribs; routine->defLine = oldrout->defLine; parser->routine = routine; parser->nameSpace = routine->nameSpace = oldrout->nameSpace; parser->vmSpace = oldrout->nameSpace->vmSpace; DString_Assign( parser->fileName, oldrout->nameSpace->name ); routine->body->codeStart = oldrout->body->codeStart; routine->body->codeEnd = oldrout->body->codeStart + newCodes.size() + 1; parser->regCount = routine->parCount; parser->levelBase = oldrout->defLine != 0; bool res = DaoParser_LexCode( parser, codes.toLocal8Bit().data(), 1 ); for(i=0; i<(int)parser->tokens->size; i++){ parser->tokens->items.pToken[i]->line += routine->body->codeStart; } for(i=0; i<(int)oldrout->body->defLocals->size; i++){ DaoToken *tok = oldrout->body->defLocals->items.pToken[i]; if( tok->index >= oldrout->parCount || tok->type ==0 ) break; MAP_Insert( DList_Top( parser->lookupTables ), & tok->string, i ); DList_Append( routine->body->defLocals, tok ); } res = res && DaoParser_ParseRoutine( parser ); DaoParser_Delete( parser ); if( res == false ){ DaoRoutine_Delete( routine ); return false; } if( (process->stackSize - process->stackTop) < (routine->body->regCount + DAO_MAX_PARAM) ){ DaoProcess_PushFrame( process, routine->body->regCount ); DaoProcess_PopFrame( process ); } DaoType **regTypes = routine->body->regType->items.pType; DaoValue **newValues = process->activeValues; DaoValue **oldValues = (DaoValue**)calloc( oldrout->body->regCount, sizeof(DaoValue*) ); memcpy( oldValues, newValues, oldrout->body->regCount * sizeof(DaoValue*) ); memset( newValues, 0, oldrout->body->regCount * sizeof(DaoValue*) ); DaoProcess_InitTopFrame( process, routine, process->activeObject ); #if 0 DaoStream *stream = DaoStream_New(); DaoRoutine_PrintCode( oldrout, stream ); DaoRoutine_PrintCode( routine, stream ); #endif regmap.clear(); for(i=0; i<oldrout->parCount; i++) regmap[i] = i; DaoVmCode *oldVMC = oldrout->body->vmCodes->data.codes; DaoVmCode *newVMC = routine->body->vmCodes->data.codes; DaoVmCodeX **oldAnnot = oldrout->body->annotCodes->items.pVmc; DaoVmCodeX **newAnnot = routine->body->annotCodes->items.pVmc; int M = oldrout->body->vmCodes->size; int N = routine->body->vmCodes->size; j = k = 0; for(i=0; i<lineMap.size(); i++){ QList<DaoVmCode> oldLineCodes; QList<DaoVmCode> newLineCodes; if( lineMap[i] <0 ) continue; int old = lineMap[i] + oldrout->body->codeStart + 1; int niu = i + routine->body->codeStart + 1; //printf( "%3i %3i: %3i %3i; %3i %3i\n", j, k, i, niu, lineMap[i], old ); while( j<M && oldAnnot[j]->line < old ) ++j; while( k<N && newAnnot[k]->line < niu ) ++k; while( j<M && oldAnnot[j]->line == old ){ oldLineCodes.append( oldVMC[j] ); ++j; } while( k<N && newAnnot[k]->line == niu ){ newLineCodes.append( newVMC[k] ); ++k; } Matching( oldLineCodes, newLineCodes ); } QMap<int,int>::iterator it, end = regmap.end(); for(it=regmap.begin(); it != end; ++it){ j = it.key(); i = it.value(); DaoValue_Move( oldValues[j], & newValues[i], regTypes[i] ); } int offset = 0; if( newEntryLine <0 ){ DaoVmCodeX **annotCodes = oldrout->body->annotCodes->items.pVmc; int entry = (process->activeCode - process->topFrame->codes) + 1; int entryline = oldrout->body->annotCodes->items.pVmc[entry]->line; /* if the entry line is NOT modified, use it */ entryline -= oldrout->body->codeStart + 1; for(i=0; i<lineMap.size(); i++) if( lineMap[i] == entryline ) break; int newEntryLine = i < lineMap.size() ? i : -1; if( newEntryLine >=0 ){ entryline += oldrout->body->codeStart + 1; while( (--entry) >=0 && annotCodes[entry]->line == entryline ) offset ++; } /* if the entry line IS modified, set the entry line to the first modified line */ if( newEntryLine <0 ){ for(i=0; i<lineMap.size(); i++) if( lineMap[i] <0 ) break; newEntryLine = i; } /* if the entry line is manually set: */ newEntryLine += routine->body->codeStart + 1; } //XXX GC_ShiftRC( routine, oldrout ); GC_IncRC( routine ); oldrout->body->revised = routine; process->activeRoutine = routine; process->activeTypes = regTypes; process->topFrame->codes = routine->body->vmCodes->data.codes; ResetExecution( process, newEntryLine, offset ); i = newCodes.size() - routCodes.size(); DaoNS_UpdateLineInfo( routine->nameSpace, routine->body->codeStart, i ); return true; }
static void DaoCallServer_AddEvent( DaoTaskEvent *event ) { DaoCallServer *server = daoCallServer; DList_Append( server->events, event ); DMap_Insert( server->pending, event, NULL ); }