/* // 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 ) ){ DArray_Append( server->events, event ); DArray_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 ) ){ DArray_Append( server->events, event ); DMap_EraseNode( server->waitings, node ); return; } } }
/* // Activate all events waiting on a future value: */ void DaoFuture_ActivateEvent( DaoFuture *self ) { DaoCallServer *server = daoCallServer; DArray *array = DArray_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; DArray_Append( server->events, event ); DArray_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; DArray_Append( server->events, event ); DArray_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 ); DArray_Delete( array ); }
void DaoProcess_PopValues( DaoProcess *self, int N ) { if( N < 0 ) return; if( N >= (int)self->factory->size ){ DArray_Clear( self->factory ); }else{ DArray_Erase( self->factory, self->factory->size - N, N ); } }
static void DaoCallServer_ActivateEvents() { DaoCallServer *server = daoCallServer; daoint i, j; if( server->idle != server->total ) return; if( server->events->size != 0 ) return; if( server->events2->size == 0 ) return; #ifdef DEBUG DaoStream_WriteMBS( mainVmSpace->errorStream, "WARNING: activating events!\n" ); #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->channels == NULL ) continue; for(j=0; j<event->channels->size; ++j){ DaoChannel *chan = (DaoChannel*) event->channels->items.pValue[j]; closed += chan->cap <= 0; move = chan->buffer->size > 0; if( move ) break; } if( closed == event->channels->size ) move = 1; break; default: break; } if( move ){ DArray_Append( server->events, event ); DArray_Erase( server->events2, i, 1 ); i -= 1; } } DCondVar_Signal( & server->condv ); }
static void DaoCallThread_Run( DaoCallThread *self ) { DaoCallServer *server = daoCallServer; double wt = 0.001; daoint i, count, timeout; self->thdData = DThread_GetSpecific(); if( self->taskFunc ) self->taskFunc( self->taskParam ); while(1){ DaoProcess *process = NULL; DaoFuture *future = NULL; DThreadTask function = NULL; void *parameter = NULL; if( self->thdData != NULL ) self->thdData->state = 0; DMutex_Lock( & server->mutex ); server->idle += 1; while( server->pending->size == (server->events2->size + server->waitings->size) ){ //printf( "%p %i %i %i %i\n", self, server->events->size, server->pending->size, server->events2->size, server->waitings->size ); if( server->finishing && server->idle == server->total ){ if( (server->events2->size + server->waitings->size) == 0 ) break; } timeout = DCondVar_TimedWait( & server->condv, & server->mutex, wt ); } for(i=0; i<server->parameters->size; ++i){ void *param = server->parameters->items.pVoid[i]; if( DMap_Find( server->active, param ) ) continue; DMap_Insert( server->active, param, NULL ); function = (DThreadTask) server->functions->items.pVoid[i]; parameter = param; DArray_Erase( server->functions, i, 1 ); DArray_Erase( server->parameters, i, 1 ); DMap_Erase( server->pending, parameter ); server->idle -= 1; break; } DMutex_Unlock( & server->mutex ); if( function ){ (*function)( parameter ); DMutex_Lock( & server->mutex ); DMap_Erase( server->active, parameter ); DMutex_Unlock( & server->mutex ); continue; } if( server->pending->size == 0 && server->finishing && server->idle == server->total ) break; DMutex_Lock( & server->mutex ); server->idle -= 1; future = DaoCallServer_GetNextFuture(); DMutex_Unlock( & server->mutex ); if( future == NULL ) continue; process = future->process; if( process == NULL ){ GC_DecRC( future ); continue; } count = process->exceptions->size; future->state = DAO_CALL_RUNNING; DaoProcess_InterceptReturnValue( process ); DaoProcess_Execute( process ); if( process->exceptions->size > count ) DaoProcess_PrintException( process, 1 ); if( future->actor ){ int erase = 1; DMutex_Lock( & server->mutex ); if( future->actor->rootObject->isAsync ){ erase = process->status == DAO_PROCESS_FINISHED; } if( erase ) DMap_Erase( server->active, future->actor->rootObject ); DMutex_Unlock( & server->mutex ); } DMutex_Lock( & server->mutex ); DMap_Erase( server->active, process ); process->active = 0; DMutex_Unlock( & server->mutex ); DaoProcess_ReturnFutureValue( process, future ); if( future->state == DAO_CALL_FINISHED ) DaoFuture_ActivateEvent( future ); GC_DecRC( future ); } DMutex_Lock( & server->mutex ); server->stopped += 1; DMutex_Unlock( & server->mutex ); }
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; }
static int DaoParser_MacroApply( DaoParser *self, DArray *tokens, DMacroGroup *group, DMap *tokMap, DMap *used, int level, DString *tag, int pos0, int adjust ) { DMacroUnit **units = (DMacroUnit**) group->units->items.pVoid; DMacroUnit *unit; DMacroGroup *grp; DMacroNode *node, *node2; DArray *toks = DArray_New(D_TOKEN); DaoToken *tk = DaoToken_New(); DaoToken *tt = NULL; DNode *kwnode = NULL; DMap *check = NULL; DMap one = { NULL, 0, 0, 0 }; int M, N = group->units->size; int i, j, gid = -1; int repeated = 0; int start_mbs = -1; int start_wcs = -1; int squote, dquote; if( group->repeat != DMACRO_AUTO ) level ++; for( i=0; i<N; i++ ){ unit = units[i]; if( tokens->size >0 ) pos0 = tokens->items.pToken[ tokens->size -1 ]->line; self->curLine = pos0; /* printf( "apply unit %i: %i\n", i, unit->type ); */ switch( unit->type ){ case DMACRO_TOK : squote = unit->marker->type == DTOK_ESC_SQUO; dquote = unit->marker->type == DTOK_ESC_DQUO; if( (squote && start_mbs >=0) || (dquote && start_wcs >=0) ){ int qstart = squote ? start_mbs : start_wcs; tt = tokens->items.pToken[ qstart ]; for(j=qstart+1,M=tokens->size; j<M; j++){ DaoToken *jtok = tokens->items.pToken[j]; int t = j ? tokens->items.pToken[j-1]->type : 0; if( t == DTOK_IDENTIFIER && jtok->type == t ) DString_AppendChar( & tt->string, ' ' ); DString_Append( & tt->string, & jtok->string ); } if( squote ){ DString_AppendChar( & tt->string, '\'' ); DArray_Erase( tokens, start_mbs+1, tokens->size ); }else{ DString_AppendChar( & tt->string, '\"' ); DArray_Erase( tokens, start_wcs+1, tokens->size ); } start_mbs = -1; break; }else if( squote ){ start_mbs = tokens->size; DArray_Append( tokens, unit->marker ); tt = tokens->items.pToken[ start_mbs ]; tt->type = tt->name = DTOK_MBS; DString_SetMBS( & tt->string, "\'" ); break; }else if( dquote ){ start_wcs = tokens->size; DArray_Append( tokens, unit->marker ); tt = tokens->items.pToken[ start_wcs ]; tt->type = tt->name = DTOK_WCS; DString_SetMBS( & tt->string, "\"" ); break; } DArray_Append( tokens, unit->marker ); tokens->items.pToken[ tokens->size-1 ]->cpos += adjust; break; case DMACRO_VAR : DaoToken_Assign( tk, unit->marker ); DString_Append( & tk->string, tag ); DArray_Append( tokens, tk ); break; case DMACRO_EXP : case DMACRO_ID : case DMACRO_OP : case DMACRO_BL : case DMACRO_IBL : kwnode = MAP_Find( tokMap, & unit->marker->string ); if( kwnode ==NULL ){ DaoParser_Error( self, DAO_CTW_UNDEF_MAC_MARKER, & unit->marker->string ); goto Failed; } node = (DMacroNode*) kwnode->value.pVoid; kwnode = MAP_Find( used, unit ); if( kwnode == NULL ){ DMap_Insert( used, unit, & one ); kwnode = MAP_Find( used, unit ); } check = (DMap*) kwnode->value.pVoid; repeated = 1; /* printf( ">>>\n%s level %i: \n", unit->marker->string.mbs, level ); DMacroNode_Print( node ); printf( "\n" ); */ /* search a leaf */ node2 = DMacroNode_FindLeaf( node, check, level ); if( node2 ){ /* printf( "appending tokens\n" ); DMacroNode_Print( node2 ); printf( "\n" ); */ DArray_InsertArray( tokens, tokens->size, node2->leaves, 0, -1 ); DMap_Insert( check, node2, NULL ); /* DArray_Clear( node2->leaves ); */ }else{ DMacroNode_RemoveEmptyLeftBranch( node, level ); goto Failed; } break; case DMACRO_GRP : case DMACRO_ALT : grp = (DMacroGroup*) unit; DArray_Clear( toks ); j = DaoParser_MacroApply( self, toks, grp, tokMap, used, level, tag, pos0, adjust ); switch( grp->repeat ){ case DMACRO_AUTO : case DMACRO_ONE : if( j <0 && group->type != DMACRO_ALT ) goto Failed; repeated = (j>0); if( j >=0 ){ gid = i; DArray_InsertArray( tokens, tokens->size, toks, 0, -1 ); } break; case DMACRO_ZERO_OR_ONE : gid = i; repeated = (j>0); if( j >=0 ){ DArray_InsertArray( tokens, tokens->size, toks, 0, -1 ); } break; case DMACRO_ZERO_OR_MORE : gid = i; repeated = (j>0); if( j >=0 ){ DArray_InsertArray( tokens, tokens->size, toks, 0, -1 ); } while( j >0 ){ DArray_Clear( toks ); j = DaoParser_MacroApply( self, toks, grp, tokMap, used, level, tag, pos0, adjust ); if( j >0 ){ DArray_InsertArray( tokens, tokens->size, toks, 0, -1 ); } } break; case DMACRO_ONE_OR_MORE : if( j <0 && group->type != DMACRO_ALT ) goto Failed; repeated = (j>0); if( j >=0 ){ DArray_InsertArray( tokens, tokens->size, toks, 0, -1 ); } while( j >0 ){ gid = i; DArray_Clear( toks ); j = DaoParser_MacroApply( self, toks, grp, tokMap, used, level, tag, pos0, adjust ); if( j >0 ){ DArray_InsertArray( tokens, tokens->size, toks, 0, -1 ); } } break; } break; default : goto Failed; } if( group->type == DMACRO_ALT && gid >=0 ) break; } if( group->repeat != DMACRO_AUTO ) level --; if( group->type == DMACRO_ALT && gid <0 ) goto Failed; DaoToken_Delete( tk ); DArray_Delete( toks ); return repeated; Failed : DaoToken_Delete( tk ); DArray_Delete( toks ); return -1; }
int DaoParser_MacroTransform( DaoParser *self, DaoMacro *macro, int start, int tag ) { DString *mbs = DString_New(1); DArray *toks = DArray_New(D_TOKEN); DArray *all = DArray_New(0); DMap *tokMap = DMap_New(D_STRING,0); DMap *used = DMap_New(0,D_MAP); DNode *it; daoint i; int j, p0, lev = 0, adjust=0; int indent[10]; char buf[20]; sprintf( buf, " %p %x", self->nameSpace, tag ); DString_SetMBS( mbs, buf ); for(i=0; i<10; i++) indent[i] = -1; j = DaoParser_MacroMatch( self, start, self->tokens->size, macro->macroMatch, tokMap, lev, all, indent ); /* printf( "MacroTransform %i\n", j ); */ if( j <0 ) goto Failed; for( it = DMap_First( tokMap ); it != NULL; it = DMap_Next( tokMap, it ) ){ DMacroNode *node = (DMacroNode*) it->value.pVoid; while( node->parent ) node = node->parent; it->value.pVoid = node; } lev = 0; p0 = self->tokens->items.pToken[start]->line; adjust = self->tokens->items.pToken[start]->cpos - macro->macroApply->cpos; if( DaoParser_MacroApply( self, toks, macro->macroApply, tokMap, used, lev, mbs, p0, adjust ) <0 ) goto Failed; /* for(i=0; i<toks->size; i++) printf( "%s ", toks->items.pToken[i]->string.mbs ); printf( "\n" ); */ DArray_Erase( self->tokens, start, j-start ); DArray_InsertArray( self->tokens, start, toks, 0, -1 ); /* for(i=0; i<toks->size; i++){ DArray_Insert( self->tokStr, (void*)toks->items.pString[i], start+i ); DArray_Insert( self->tokPos, (void*)poss->items.pInt[i], start+i ); } */ j = toks->size; DString_Delete( mbs ); for(i=0; i<all->size; i++) DMacroNode_Delete( (DMacroNode*) all->items.pVoid[i] ); DArray_Delete( all ); DArray_Delete( toks ); DMap_Delete( tokMap ); DMap_Delete( used ); return start + j; Failed : DString_Delete( mbs ); for(i=0; i<all->size; i++) DMacroNode_Delete( (DMacroNode*) all->items.pVoid[i] ); DArray_Delete( all ); DArray_Delete( toks ); DMap_Delete( tokMap ); DMap_Delete( used ); 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; 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; }