static void STD_Load( DaoProcess *proc, DaoValue *p[], int N ) { DString *name = p[0]->xString.data; int import = p[1]->xInteger.value; int runim = p[2]->xInteger.value; int safe = p[3]->xInteger.value; int wasProt = 0; int res = 0; DaoVmSpace *vms = proc->vmSpace; DaoNamespace *ns; DString_ToMBS( name ); if( safe ) vms->options |= DAO_OPTION_SAFE; if( vms->options & DAO_OPTION_SAFE ) wasProt = 1; DArray_PushFront( vms->pathLoading, proc->activeNamespace->path ); ns = DaoVmSpace_LoadEx( vms, DString_GetMBS( name ), runim ); DaoProcess_PutValue( proc, (DaoValue*) ns ); if( ! wasProt ) vms->options &= ~DAO_OPTION_SAFE; if( ns ){ /* in the case that it is cancelled from console */ DArray_PushFront( vms->pathLoading, ns->path ); res = DaoProcess_Call( proc, ns->mainRoutine, NULL, NULL, 0 ); if( proc->stopit | vms->stopit ){ DaoProcess_RaiseException( proc, DAO_ERROR, "loading cancelled" ); }else if( res ){ DaoProcess_RaiseException( proc, res, "loading failed" ); } DArray_PopFront( vms->pathLoading ); }else{ DaoProcess_RaiseException( proc, DAO_ERROR, "loading failed" ); } DArray_PopFront( vms->pathLoading ); if( import && ns ) DaoNamespace_AddParent( proc->activeNamespace, ns ); }
void DArray_Erase( DArray *self, daoint start, daoint n ) { void **buf = self->items.pVoid - self->offset; daoint rest, locked; if( start >= self->size ) return; if( n < 0 ) n = self->size; if( n > self->size - start ) n = self->size - start; if( n == 1 ){ if( start == 0 ){ DArray_PopFront( self ); return; }else if( start == self->size -1 ){ DArray_PopBack( self ); return; } } DArray_DeleteItems( self, start, start+n ); rest = self->size - start - n; locked = self->type == DAO_DATA_VALUE ? DaoGC_LockArray( self ) : 0; memmove( self->items.pVoid + start, self->items.pVoid + start + n, rest * sizeof(void*) ); self->size -= n; if( self->size < 0.5*self->bufsize && self->size + 10 < self->bufsize ){ if( self->offset ) memmove( buf, self->items.pVoid, self->size * sizeof(void*)); self->bufsize = 0.6 * self->bufsize + 1; self->items.pVoid = (void**) dao_realloc( buf, (self->bufsize+1)*sizeof(void*) ); self->offset = 0; } DaoGC_UnlockArray( self, locked ); }
static void DMacroNode_RemoveEmptyLeftBranch( DMacroNode *self, int level ) { DMacroNode *node = self; while( node->level < level-1 && node->nodes->size ) node = (DMacroNode*) node->nodes->items.pVoid[0]; if( node->level == level-1 && DMacroNode_LeavesAreEmpty( node ) ){ if( node->parent ) DArray_PopFront( node->parent->nodes ); } }
void DCondVar_Signal( DCondVar *self ) { DThread *thread; DMutex_Lock( & self->thdMutex ); if( self->thdWaiting->size > 0 ){ thread = (DThread*) self->thdWaiting->items.pVoid[0]; SetEvent( thread->condv.myCondVar ); DArray_PopFront( self->thdWaiting ); } DMutex_Unlock( & self->thdMutex ); }
static void STD_Load( DaoProcess *proc, DaoValue *p[], int N ) { DString *name = p[0]->xString.data; int import = p[1]->xInteger.value; int runim = p[2]->xInteger.value; int safe = p[3]->xInteger.value; int wasProt = 0; int res = 0; DaoVmSpace *vms = proc->vmSpace; DaoNamespace *ns; DString_ToMBS( name ); if( safe ) vms->options |= DAO_OPTION_SAFE; if( vms->options & DAO_OPTION_SAFE ) wasProt = 1; DArray_PushFront( vms->pathLoading, proc->activeNamespace->path ); ns = DaoVmSpace_LoadEx( vms, DString_GetMBS( name ), runim ); DaoProcess_PutValue( proc, (DaoValue*) ns ); if( ! wasProt ) vms->options &= ~DAO_OPTION_SAFE; if( ns == NULL ) DaoProcess_RaiseException( proc, DAO_ERROR, "loading failed" ); DArray_PopFront( vms->pathLoading ); if( import && ns ) DaoNamespace_AddParent( proc->activeNamespace, ns ); }
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; }
/* // 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; }
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; }