Example #1
0
void DaoTaskEvent_Init( DaoTaskEvent *self, int T, int S, DaoFuture *F, DaoChannel *C )
{
	GC_Assign( & self->future, F );
	GC_Assign( & self->channel, C );
	self->type = T;
	self->state = S;
}
Example #2
0
DaoFuture* DaoProcess_GetInitFuture( DaoProcess *self )
{
	DaoFuture *future;
	if( self->future ) return self->future;

	future = DaoFuture_New( NULL, 1 );
	GC_Assign( & self->future, future );
	GC_Assign( & future->process, self );
	return future;
}
Example #3
0
DaoCinValue* DaoCinValue_New( DaoCinType *cintype, DaoValue *value )
{
	DaoCinValue *self = (DaoCinValue*)dao_calloc( 1, sizeof(DaoCinValue) );
	DaoValue_Init( self, DAO_CINVALUE );
	GC_Assign( & self->cintype, cintype );
	GC_Assign( & self->value, value );
#ifdef DAO_USE_GC_LOGGER
	DaoObjectLogger_LogNew( (DaoValue*) self );
#endif
	return self;
}
Example #4
0
static void DaoSTD_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_TryGetChars( p[0] );
	if( redirect != prevStream ) GC_Assign( & proc->stdioStream, redirect );
	DaoProcess_Eval( proc, ns, source );
	DaoProcess_PutValue( proc, proc->stackValues[0] );
	if( redirect != prevStream ) GC_Assign( & proc->stdioStream, prevStream );
}
Example #5
0
void DaoValue_SetType( DaoValue *to, DaoType *tp )
{
	DaoVmSpace *vms;
	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->args == NULL || tp->args->size == 0 ) break;
		tp = tp->args->items.pType[0];
		if( tp->tid == DAO_NONE || tp->tid > DAO_COMPLEX ) break;
		DaoArray_SetNumType( (DaoArray*) to, tp->tid );
		break;
#endif
	case DAO_LIST :
		/* var x: any = {}, x->ctype should be list<any> */
		if( tp->tid == DAO_ANY ){
			vms = DaoType_GetVmSpace( tp );
			tp = vms->typeListAny;
		}
		if( to->xList.ctype && !(to->xList.ctype->attrib & DAO_TYPE_UNDEF) ) break;
		GC_Assign( & to->xList.ctype, tp );
		break;
	case DAO_MAP :
		if( tp->tid == DAO_ANY ){
			vms = DaoType_GetVmSpace( tp );
			tp = vms->typeMapAny;
		}
		if( to->xMap.ctype && !(to->xMap.ctype->attrib & DAO_TYPE_UNDEF) ) break;
		GC_Assign( & to->xMap.ctype, tp );
		break;
	case DAO_TUPLE :
		tp2 = to->xTuple.ctype;
		if( tp->tid == DAO_ANY ) break;
		if( tp->args->size ==0 ) break; /* not to the generic tuple type */
		if( tp2 == NULL || tp2->mapNames == NULL || tp2->mapNames->size ==0 ){
			GC_Assign( & to->xTuple.ctype, 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_Assign( & to->xTuple.ctype, tp );
		break;
	default : break;
	}
}
Example #6
0
void DaoxGraphData_Reset( DaoxGraphData *self, DaoxGraph *graph, int nodeSize, int edgeSize )
{
	daoint i, M, N;
	char *data;

	if( self->graph ){
		N = self->graph->nodes->size;
		M = self->graph->edges->size;
		for(i=0; i<N; i++){
			DaoxNode *node = self->graph->nodes->items.pgNode[i];
			node->X.Void = NULL;
		}
		for(i=0; i<N; i++){
			DaoxEdge *edge = self->graph->edges->items.pgEdge[i];
			edge->X.Void = NULL;
		}
	}
	GC_Assign( & self->graph, graph );
	if( graph == NULL ) return;

	N = graph->nodes->size;
	M = graph->edges->size;
	DString_Reserve( self->nodeData, N * nodeSize );
	DString_Reserve( self->edgeData, M * edgeSize );
	for(i=0, data=self->nodeData->chars;  i<N;  i++, data+=nodeSize){
		DaoxNode *node = graph->nodes->items.pgNode[i];
		node->X.Void = data;
	}
	for(i=0, data=self->edgeData->chars;  i<M;  i++, data+=edgeSize){
		DaoxEdge *edge = graph->edges->items.pgEdge[i];
		edge->X.Void = data;
	}
}
Example #7
0
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;

	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_RaiseError( proc, "Param", "invalid type selection" );
			return;
		}
	}

	event = DaoCallServer_MakeEvent();
	DaoTaskEvent_Init( event, DAO_EVENT_WAIT_SELECT, DAO_EVENT_WAIT, future, NULL );
	GC_Assign( & 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 );
}
Example #8
0
void DaoObject_Init( DaoObject *self, DaoObject *that, int offset )
{
	DaoClass *klass = self->defClass;
	daoint i;

	self->isAsync = (klass->attribs & DAO_CLS_ASYNCHRONOUS) != 0;
	if( that ){
		GC_Assign( & self->rootObject, that );
		self->objValues = that->objValues + offset;
	}else if( self->rootObject == NULL ){
		GC_Assign( & 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_Assign( & self->parent, sup );
	}
	GC_Assign( & self->objValues[0], 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 );
		}else if( *value == NULL && var->dtype && var->dtype->value ){
			DaoValue_Copy( var->dtype->value, value );
		}
	}
}
Example #9
0
static void COROUT_Suspend( DaoProcess *proc, DaoValue *p[], int N )
{
	DaoxCoroutine *self = (DaoxCoroutine*) p[0];
	DaoValue *value = N > 1 ? p[1] : DaoValue_MakeNone();
	if( self->process != proc ){
		DaoProcess_RaiseError( proc, NULL, "coroutine cannot suspend in alien process." );
		return;
	}
	GC_Assign( & proc->stackValues[0], value );
	proc->status = DAO_PROCESS_SUSPENDED;
	proc->pauseType = DAO_PAUSE_COROUTINE_YIELD;
}
Example #10
0
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_Assign( & copy->ctype, list->ctype );
		for(i=0; i<list->value->size; ++i){
			DaoValue *value = DaoValue_DeepCopy( list->value->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->value->hashing );
		GC_Assign( & copy->ctype, map->ctype );
		for(it=DMap_First(map->value); it; it=DMap_Next(map->value,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_Assign( & copy->ctype, tuple->ctype );
		for(i=0; i<tuple->size; ++i){
			DaoValue *value = DaoValue_DeepCopy( tuple->values[i] );
			DaoTuple_SetItem( copy, value, i );
		}
		return (DaoValue*) copy;
	}
	return NULL;
}
Example #11
0
void DaoValue_MoveCinValue( DaoCinValue *S, DaoValue **D )
{
	DaoValue *D2 = *D;
	if( D2 == (DaoValue*) S ) return;
	if( D2 == NULL || D2->type != DAO_CINVALUE || D2->xCinValue.refCount > 1 ){
		S = DaoCinValue_Copy( S );
		DaoGC_Assign( D, (DaoValue*) S );
		return;
	}
	if( D2->xCinValue.cintype != S->cintype ){
		GC_Assign( & D2->xCinValue.cintype, S->cintype );
	}
	DaoValue_Copy( S->value, & D2->xCinValue.value );
}
Example #12
0
void DaoVmSpace_AddTaskletWait( DaoVmSpace *self, DaoProcess *wait, DaoFuture *pre, double timeout )
{
	DaoTaskletEvent *event;
	DaoTaskletServer *server = DaoTaskletServer_TryInit( self );
	DaoFuture *future = DaoProcess_GetInitFuture( wait );

	GC_Assign( & future->precond, pre );
	future->state = DAO_TASKLET_PAUSED;

	event = DaoTaskletServer_MakeEvent( server );
	DaoTaskletEvent_Init( event, DAO_EVENT_WAIT_TASKLET, DAO_EVENT_WAIT, future, NULL );

	DaoTaskletServer_AddTimedWait( server, wait, event, timeout );
}
Example #13
0
void DaoCallServer_AddWait( DaoProcess *wait, DaoFuture *pre, double timeout )
{
	DaoTaskEvent *event;
	DaoCallServer *server = DaoCallServer_TryInit( mainVmSpace );;
	DaoFuture *future = DaoProcess_GetInitFuture( wait );

	GC_Assign( & 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 );
}
Example #14
0
static int DaoValue_TryCastTuple( DaoValue *src, DaoValue **dest, DaoType *tp )
{
	DaoTuple *tuple;
	DaoType **item_types = tp->args->items.pType;
	DaoType *totype = src->xTuple.ctype;
	DaoValue **data = src->xTuple.values;
	DMap *names = totype ? totype->mapNames : NULL;
	DNode *node, *search;
	daoint i, T = tp->args->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.ctype->mapNames";
	*/
	if( src->xTuple.ctype == NULL ){
		GC_IncRC( tp );
		src->xTuple.ctype = tp;
		return 1;
	}
	if( DaoType_MatchValue( tp, src, NULL ) < DAO_MT_SIM ) return 1; /* Redundant? */
	/*
	// 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->values+i, it );
	}
	GC_IncRC( tp );
	tuple->ctype = tp;
	GC_Assign( dest, tuple );
	return 1;
}
Example #15
0
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_Assign( & self->parent, parent );
		}
	}
}
Example #16
0
static void DaoMT_Start( DaoProcess *proc, DaoValue *p[], int n )
{
	DaoProcess *clone;
	DaoVmCode *vmc, *end, *sect;
	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 );
	sect = DaoProcess_InitCodeSection( proc, 0 );
	if( sect == NULL ) 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 );
	DaoMT_InitProcess( proc, clone, 0 );
	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_Assign( & 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 ) DaoValue_Move( proc->activeValues[i], & clone->activeValues[i], NULL );
	}
	DaoCallServer_AddTask( DaoMT_Start0, clone, p[0]->xEnum.value ? clone : NULL );
}
Example #17
0
void DaoValue_CopyX( DaoValue *src, DaoValue **dest, DaoType *cst )
{
	DaoValue *dest2 = *dest;
	if( src == dest2 ) return;
	if( dest2 && dest2->xBase.refCount >1 ){
		GC_DecRC( dest2 );
		*dest = dest2 = NULL;
	}
	if( src->type == DAO_CSTRUCT || src->type == DAO_CDATA ){
		DaoValue_MoveCstruct( src, dest, cst != NULL && cst->invar != 0 );
		return;
	}else if( src->type == DAO_CINVALUE ){
		DaoValue_MoveCinValue( (DaoCinValue*) src, dest );
		return;
	}
	if( dest2 == NULL ){
		src = DaoValue_SimpleCopyWithTypeX( src, NULL, cst );
		GC_IncRC( src );
		*dest = src;
		return;
	}
	if( src->type != dest2->type || src->type > DAO_ENUM ){
		src = DaoValue_SimpleCopyWithTypeX( src, NULL, cst );
		GC_Assign( dest, src );
		return;
	}
	switch( src->type ){
	case DAO_ENUM    :
		DaoEnum_SetType( & dest2->xEnum, src->xEnum.etype );
		DaoEnum_SetValue( & dest2->xEnum, & src->xEnum );
		break;
	case DAO_BOOLEAN : dest2->xBoolean.value = src->xBoolean.value; break;
	case DAO_INTEGER : dest2->xInteger.value = src->xInteger.value; break;
	case DAO_FLOAT   : dest2->xFloat.value = src->xFloat.value; break;
	case DAO_COMPLEX : dest2->xComplex.value = src->xComplex.value; break;
	case DAO_STRING  : DString_Assign( dest2->xString.value, src->xString.value ); break;
	}
}
Example #18
0
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;
}
Example #19
0
void DaoCallServer_AddCall( DaoProcess *caller )
{
	DaoFuture *future;
	DaoTaskEvent *event;
	DaoProcess *callee = DaoVmSpace_AcquireProcess( caller->vmSpace );
	DaoStackFrame *frame = caller->topFrame;
	DaoRoutine *routine = frame->routine;
	DaoType *type = (DaoType*) routine->routType->aux;
	DaoValue **params = caller->stackValues + caller->topFrame->stackBase;
	int i, count = caller->topFrame->parCount;

	if( caller->activeCode->b & DAO_CALL_BLOCK ){
		DaoValue **calleeValues, **callerValues = caller->activeValues;
		DaoStackFrame *sectFrame = DaoProcess_FindSectionFrame( caller );
		DaoStackFrame *callerFrame = caller->topFrame->prev;
		DaoVmCode *vmc, *end, *sect;
		if( sectFrame != callerFrame ){
			DaoVmSpace_ReleaseProcess( caller->vmSpace, callee );
			DaoProcess_RaiseError( caller, NULL, "Invalid code section" );
			return;
		}
		if( routine->body ){
			DaoProcess_PushRoutine( callee, callerFrame->routine, callerFrame->object );
			callerValues = caller->stackValues + callerFrame->stackBase;
		}else{
			DaoProcess_PushRoutine( callee, caller->activeRoutine, caller->activeObject );
		}
		DaoProcess_SetActiveFrame( callee, callee->topFrame );
		calleeValues = callee->stackValues + callee->topFrame->stackBase;
		callee->activeCode = caller->activeCode;
		vmc = callerFrame->routine->body->vmCodes->data.codes + callerFrame->entry;
		end = callerFrame->routine->body->vmCodes->data.codes + vmc->b;
		sect = vmc + 1;
		for(vmc=sect; vmc!=end; vmc++){
			int i = -1, code = vmc->code;
			if( code == DVM_GETVH || (code >= DVM_GETVH_I && code <= DVM_GETVH_C) ){
				i = vmc->b;
			}else if( code == DVM_SETVH || (code >= DVM_SETVH_II && code <= DVM_SETVH_CC) ){
				i = vmc->b;
			}
			if( i >= 0 ) DaoValue_Move( callerValues[i], & calleeValues[i], NULL );
		}
	}

	future = DaoFuture_New( type, 1 );
	future->state = DAO_CALL_PAUSED;
	future->actor = caller->topFrame->object;
	GC_IncRC( future->actor );

	GC_Assign( & future->process, callee );
 	GC_Assign( & callee->future, future );

	callee->parCount = count;
	/* Use routine->parCount instead of caller->topFrame->parCount, for default parameters: */
	for(i=0; i<routine->parCount; ++i) DaoValue_Copy( params[i], & callee->paramValues[i] );
	if( routine->body ){
		DaoProcess_PushRoutine( callee, routine, future->actor );
	}else{
		DaoProcess_PushFunction( callee, routine );
		callee->activeNamespace = caller->activeNamespace;
	}
	if( caller->activeCode->b & DAO_CALL_BLOCK ){
		callee->topFrame->host = callee->topFrame;
		callee->topFrame->retmode = DVM_RET_PROCESS;
		callee->topFrame->returning = 0;
	}

#ifdef DAO_WITH_CONCURRENT
	DaoCallServer_TryInit( mainVmSpace );
	event = DaoCallServer_MakeEvent();
	DaoTaskEvent_Init( event, DAO_EVENT_RESUME_TASKLET, DAO_EVENT_RESUME, future, NULL );

	DaoProcess_PopFrame( caller );
	DaoProcess_PutValue( caller, (DaoValue*) future );

	DaoCallServer_Add( event );
#else
	DaoProcess_PopFrame( caller );
	DaoProcess_PutValue( caller, (DaoValue*) future );
	DaoProcess_InterceptReturnValue( callee );
	DaoProcess_Execute( callee );
	DaoProcess_ReturnFutureValue( callee, future );
	DaoVmSpace_ReleaseProcess( caller->vmSpace, callee );
#endif
}
Example #20
0
int DaoValue_Move4( DaoValue *S, DaoValue **D, DaoType *T, DaoType *C, DMap *defs )
{
	DaoCinType *cintype;
	int tm = 1;
	switch( (T->tid << 8) | S->type ){
	case (DAO_BOOLEAN << 8) | DAO_BOOLEAN :
	case (DAO_BOOLEAN << 8) | DAO_INTEGER :
	case (DAO_BOOLEAN << 8) | DAO_FLOAT   :
	case (DAO_INTEGER << 8) | DAO_BOOLEAN :
	case (DAO_INTEGER << 8) | DAO_INTEGER :
	case (DAO_INTEGER << 8) | DAO_FLOAT   :
	case (DAO_FLOAT   << 8) | DAO_BOOLEAN :
	case (DAO_FLOAT   << 8) | DAO_INTEGER :
	case (DAO_FLOAT   << 8) | DAO_FLOAT   :
	case (DAO_COMPLEX << 8) | DAO_COMPLEX :
	case (DAO_STRING  << 8) | DAO_STRING  :
	case (DAO_CINVALUE<< 8) | DAO_CINVALUE  :
		S = DaoValue_SimpleCopyWithTypeX( S, T, C );
		GC_Assign( D, S );
		return 1;
	}
	switch( S->type ){
	case DAO_ENUM : if( S->xEnum.subtype == DAO_ENUM_SYM && T->realnum ) return 0; break;
	case DAO_OBJECT : if( S->xObject.isNull ) return 0; break;
	case DAO_CDATA  : if( S->xCdata.data == NULL && ! DaoType_IsNullable(T) ) return 0; break;
	}
	if( !(S->xBase.trait & DAO_VALUE_CONST) ){
		DaoVmSpace *vms;
		DaoType *ST = NULL;
		switch( (S->type << 8) | T->tid ){
		case (DAO_ARRAY<<8)|DAO_ARRAY :
			vms = DaoType_GetVmSpace( T );
			ST = vms->typeArrays[ S->xArray.etype ]; break;
		case (DAO_TUPLE<<8)|DAO_TUPLE : ST = S->xTuple.ctype; break;
		case (DAO_LIST <<8)|DAO_LIST  : ST = S->xList.ctype; break;
		case (DAO_MAP  <<8)|DAO_MAP   : ST = S->xMap.ctype; 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 ){
			if( ST->tid == DAO_CSTRUCT || ST->tid == DAO_CDATA ){
				DaoValue_MoveCstruct( S, D, C != NULL && C->invar != 0 );
			}else{
				GC_Assign( D, S );
			}
			return 1;
		}
	}
	if( (T->tid == DAO_OBJECT || T->tid == DAO_CSTRUCT || T->tid == DAO_CDATA) && S->type == DAO_OBJECT ){
		if( S->xObject.defClass != & T->aux->xClass ){
			S = DaoObject_CastToBase( S->xObject.rootObject, T );
			if( S != NULL && S->type == DAO_CDATA && S->xCdata.data == NULL ){
				if( ! DaoType_IsNullable( T ) ) return 0;
			}
			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.classType != T ){
			S = DaoType_CastToParent( S, T );
			tm = (S != NULL);
		}
	}else if( T->tid == DAO_ROUTINE && T->subtid != DAO_ROUTINES && S->type == DAO_ROUTINE && S->xRoutine.overloads ){
		DList *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->chars, T->tid, tm );
		if( S->type == DAO_LIST ) printf( "%s\n", S->xList.ctype->name->chars );
		if( S->type == DAO_TUPLE ) printf( "%p\n", S->xTuple.ctype );
	}
	printf( "S->type = %p %s %i\n", S, T->name->chars, tm );
#endif
	if( tm == 0 ) return 0;


	/*
	// Composite 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.
	*/
	cintype = NULL;
	if( T->tid == DAO_CINVALUE ){
		if( DaoType_MatchValue( T->aux->xCinType.target, S, NULL ) >= DAO_MT_CIV ){
			cintype = (DaoCinType*) T->aux;
		}
	}else if( T->tid == DAO_INTERFACE && T->aux->xInterface.concretes ){
		DaoInterface *inter = (DaoInterface*) T->aux;
		DaoType *st = DaoValue_GetType( S, inter->nameSpace->vmSpace );
		DNode *it; 
		cintype = DaoInterface_GetConcrete( inter, st );
		if( cintype == NULL ){
			for(it=DMap_First(inter->concretes); it; it=DMap_Next(inter->concretes,it)){
				if( DaoType_MatchValue( it->key.pType, S, NULL ) >= DAO_MT_CIV ){
					cintype = (DaoCinType*) it->value.pVoid;
					break;
				}
			}
		}
	}
	if( cintype ){
		S = (DaoValue*) DaoCinValue_New( cintype, S );
	}else if( S->type == DAO_CSTRUCT || S->type == DAO_CDATA ){
		DaoValue_MoveCstruct( S, D, C != NULL && C->invar != 0 );
		return 1;
	}else{
		S = DaoValue_SimpleCopyWithTypeX( S, T, C );
	}
	GC_Assign( D, S );
	if( S->type == DAO_TUPLE && S->xTuple.ctype != 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;
}
Example #21
0
int DaoValue_Move5( DaoValue *S, DaoValue **D, DaoType *T, DaoType *C, DMap *defs )
{
	DaoValue *D2 = *D;
	if( S == D2 && (S == NULL || DaoValue_FastMatchTo( S, T )) ) return 1;
	if( S == NULL ){
		GC_DecRC( *D );
		*D = NULL;
		return 0;
	}
	if( T == NULL ){
		DaoValue_CopyX( S, D, C );
		return 1;
	}
	if( T->valtype ){
		if( DaoValue_Compare( S, T->value ) !=0 ) return 0;
		DaoValue_CopyX( S, D, C );
		return 1;
	}
	switch( T->tid ){
	case DAO_UDT :
		DaoValue_CopyX( S, D, C );
		return 1;
	case DAO_THT :
		if( T->aux ) return DaoValue_Move5( S, D, (DaoType*) T->aux, C, defs );
		DaoValue_CopyX( S, D, C );
		return 1;
	case DAO_ANY :
		DaoValue_CopyX( S, D, C );
		DaoValue_SetType( *D, T );
		return 1;
	case DAO_VARIANT :
		return DaoValue_MoveVariant( S, D, T, C );
	default : break;
	}
	if( S->type >= DAO_OBJECT || !(S->xBase.trait & DAO_VALUE_CONST) || T->invar ){
		if( DaoValue_FastMatchTo( S, T ) ){
			if( S->type == DAO_CDATA && S->xCdata.data == NULL ){
				if( ! DaoType_IsNullable( T ) ) return 0;
			}
			if( S->type == DAO_CSTRUCT || S->type == DAO_CDATA ){
				DaoValue_MoveCstruct( S, D, C != NULL && C->invar != 0 );
			}else if( S->type == DAO_CINVALUE ){
				DaoValue_MoveCinValue( (DaoCinValue*) S, D );
			}else{
				GC_Assign( D, S );
			}
			return 1;
		}
	}
	if( S->type == DAO_CINVALUE ){
		if( S->xCinValue.cintype->target == T ){
			S = S->xCinValue.value;
		}else if( DaoType_MatchTo( S->xCinValue.cintype->target, T, NULL ) >= DAO_MT_EQ ){
			S = S->xCinValue.value;
		}
	}
	if( D2 && D2->xBase.refCount > 1 ){
		GC_DecRC( D2 );
		*D = D2 = NULL;
	}
#if 0
	if( D2 && S->type == D2->type && S->type == T->tid && S->type <= DAO_ENUM ){
		switch( S->type ){
		case DAO_ENUM    :
			DaoEnum_SetType( & D2->xEnum, T->subtid == DAO_ENUM_ANY ? S->xEnum.etype : T );
			return DaoEnum_SetValue( & D2->xEnum, & S->xEnum );
		case DAO_BOOLEAN :
		case DAO_INTEGER : D2->xInteger.value = S->xInteger.value; break;
		case DAO_FLOAT   : D2->xFloat.value = S->xFloat.value; break;
		case DAO_COMPLEX : D2->xComplex.value = S->xComplex.value; break;
		case DAO_STRING  : DString_Assign( D2->xString.value, S->xString.value ); break;
		}
		return 1;
	}
#endif
	if( D2 == NULL || D2->type != T->tid ) return DaoValue_Move4( S, D, T, C, defs );

	switch( (S->type << 8) | T->tid ){
	case (DAO_STRING<<8)|DAO_STRING :
		DString_Assign( D2->xString.value, S->xString.value );
		break;
	case (DAO_ENUM<<8)|DAO_ENUM :
		DaoEnum_SetType( & D2->xEnum, T->subtid == DAO_ENUM_ANY ? S->xEnum.etype : T );
		DaoEnum_SetValue( & D2->xEnum, & S->xEnum );
		break;
	case (DAO_CINVALUE<<8)|DAO_CINVALUE :
		if( S->xCinValue.cintype->vatype != T ) return DaoValue_Move4( S, D, T, C, defs );
		DaoValue_MoveCinValue( (DaoCinValue*) S, D );
		break;
	case (DAO_BOOLEAN<<8)|DAO_BOOLEAN : D2->xBoolean.value = S->xBoolean.value; break;
	case (DAO_BOOLEAN<<8)|DAO_INTEGER : D2->xInteger.value = S->xBoolean.value; break;
	case (DAO_BOOLEAN<<8)|DAO_FLOAT   : D2->xFloat.value   = S->xBoolean.value; break;
	case (DAO_INTEGER<<8)|DAO_BOOLEAN : D2->xBoolean.value = S->xInteger.value; break;
	case (DAO_INTEGER<<8)|DAO_INTEGER : D2->xInteger.value = S->xInteger.value; break;
	case (DAO_INTEGER<<8)|DAO_FLOAT   : D2->xFloat.value   = S->xInteger.value; break;
	case (DAO_FLOAT  <<8)|DAO_BOOLEAN : D2->xBoolean.value = S->xFloat.value; break;
	case (DAO_FLOAT  <<8)|DAO_INTEGER : D2->xInteger.value = S->xFloat.value; break;
	case (DAO_FLOAT  <<8)|DAO_FLOAT   : D2->xFloat.value   = S->xFloat.value; break;
	case (DAO_COMPLEX<<8)|DAO_COMPLEX : D2->xComplex.value = S->xComplex.value; break;
	default : return DaoValue_Move4( S, D, T, C, defs );
	}
	return 1;
}
Example #22
0
static void WIN_Show( DaoProcess *proc, DaoValue *p[], int N )
{
	DaoxWindow *self = (DaoxWindow*) p[0];
	DaoxCanvas *canvas = (DaoxCanvas*) DaoValue_CastCstruct( p[1], daox_type_canvas );
	DaoxScene *scene = (DaoxScene*) DaoValue_CastCstruct( p[1], daox_type_scene );
	DaoxFont *font = DaoxFont_GetDefault();
	int fpsLimit = p[2]->xInteger.value;
	int fpsTest = p[3]->xBoolean.value;
	double fpsTestTime = 0.0;
	double timeInterval = 0.0;
	double lastFrameStart = 0.0;
	float currentFPS = 0.0;
	size_t fpsCount = 0;
	char chars[32];

	if( fpsTest && self->widget == NULL ){
		char *fpsText = "FPS:       ";
		DaoxColor bgcolor = {0.0,0.0,0.0,0.0};
		DaoxBrush *brush;
		self->widget = DaoxCanvas_New( NULL );
		self->widget->viewport.right = self->width;
		self->widget->viewport.top = self->height;
		DaoGC_IncRC( (DaoValue*) self->widget );
		DaoxCanvas_SetBackground( self->widget, bgcolor );
		brush = DaoxCanvas_PushBrush( self->widget, 0 );
		brush->strokeColor.blue = 1.0;
		brush->fillColor.blue = 1.0;
		brush->fillColor.alpha = 1.0;
		brush->fontSize = 20;
		self->fpsLabel = DaoxCanvas_AddText( self->widget, fpsText, 10, self->height - 20, 0 );
	}
	if( self->painter == NULL && (canvas != NULL || self->widget != NULL) ){
		self->painter = DaoxPainter_New( self->context );
		DaoGC_IncRC( (DaoValue*) self->painter );
	}
	if( self->renderer == NULL && scene != NULL ){
		self->renderer = DaoxRenderer_New( self->context );
		DaoGC_IncRC( (DaoValue*) self->renderer );
	}
	if( canvas != NULL ){
		float dm = sqrt(self->width*self->width + self->height*self->height );
		float cx = 0.5*(canvas->viewport.left + canvas->viewport.right);
		float cy = 0.5*(canvas->viewport.top + canvas->viewport.bottom);
		float w = canvas->viewport.right - canvas->viewport.left;
		float h = canvas->viewport.top - canvas->viewport.bottom;
		float d = sqrt(w*w + h*h);
		w = 0.5 * self->width * d / dm;
		h = 0.5 * self->height * d / dm;
		canvas->viewport.left = cx - w;
		canvas->viewport.right = cx + w;
		canvas->viewport.bottom = cy - h;
		canvas->viewport.top = cy + h;
	}
	GC_Assign( & self->model, p[1] );
	self->visible = 1;

	glfwShowWindow( self->handle );
	glfwMakeContextCurrent( self->handle );
	glfwSetKeyCallback( self->handle, DaoxWindow_KeyCallback );
	glfwSetCursorPosCallback( self->handle, DaoxWindow_CursorMoveCallback );
	glfwSetCursorEnterCallback( self->handle, DaoxWindow_CursorEnterCallback );
	glfwSetWindowFocusCallback( self->handle, DaoxWindow_FocusCallback );

#ifdef SAVE_RENDERED_SCENE
	char name[50];
	int frame = 1;
	DaoxImage *image = DaoxImage_New();
	image->depth = DAOX_IMAGE_BIT32;
	DaoxImage_Resize( image, self->width, self->height );
#endif
	while( self->visible && ! glfwWindowShouldClose( self->handle ) ){
		double frameStartTime = 0.0;
		double frameEndTime = 0.0;
		frameStartTime = glfwGetTime();
		if( canvas ) DaoxPainter_Paint( self->painter, canvas, canvas->viewport );
		if( scene ){
#ifdef SAVE_RENDERED_SCENE
			DaoxScene_Update( scene, 1.0/30.0 );
			glReadBuffer( GL_BACK );
			glPixelStorei( GL_UNPACK_ALIGNMENT, 4 );
			glPixelStorei( GL_PACK_ROW_LENGTH, image->width );
			DaoxRenderer_Render( self->renderer, scene, scene->camera );
			glReadPixels( 0, 0, self->width, self->height, GL_RGBA, GL_UNSIGNED_BYTE, image->imageData );
			sprintf( name, "rama_attack_frame_%03i.png", frame );
			DaoxImage_SavePNG( image, name );
			frame += 1;
			if( frame > 155 ) break;
#else
			DaoxScene_Update( scene, frameStartTime - lastFrameStart );
			DaoxRenderer_Render( self->renderer, scene, scene->camera );
#endif
		}
		lastFrameStart = frameStartTime;
		if( fpsTest ){
			if( fpsCount % 10 == 0 ){
				int i, n = sprintf( chars, "%.1f", currentFPS );
				for(i=0; i<n; ++i){
					DaoxGlyph *glyph = DaoxFont_GetGlyph( font, chars[i] );
					DaoxCanvasNode *chnode = self->fpsLabel->children->items.pCanvasNode[i+5];
					DaoxPath *path = DaoxPathCache_FindPath( self->widget->pathCache, glyph->shape );
					GC_Assign( & chnode->path, path );
					DaoxCanvasNode_MarkDataChanged( chnode );
				}
			}
			DaoxPainter_Paint( self->painter, self->widget, self->widget->viewport );
		}
		glfwSwapBuffers( self->handle );
		glfwPollEvents();

		if( fpsTest == 0 ) continue;
		frameEndTime = glfwGetTime();
		timeInterval = frameEndTime - frameStartTime;
		if( timeInterval < 1.0/fpsLimit ) usleep( 1000000 * (1.0/fpsLimit -  timeInterval) );

		fpsCount += 1;
		currentFPS = fpsCount / (frameEndTime - fpsTestTime);
		if( frameEndTime > (fpsTestTime + 3) ){
			fpsTestTime = frameEndTime - 1.0;
			fpsCount = currentFPS; /* Frame count estimation in the past second; */
		}
	}
	glfwHideWindow( self->handle );
}
Example #23
0
void DaoxGraph_ConnectedComponents( DaoxGraph *self, DList *cclist )
{
	DList *nodes;
	DaoxGraph *subgraph;
	daoint i, j, k, n;
	if( self->nodes->size == 0 ){
		DList_PushBack( cclist, self );
		return;
	}
	for(i=0; i<self->nodes->size; i++){
		DaoxNode *node = (DaoxNode*) self->nodes->items.pVoid[i];
		node->state = 0;
	}
	nodes = DList_New(0);
	while( self->nodes->size ){
		DaoxNode_BreadthFirstSearch( (DaoxNode*) self->nodes->items.pVoid[0], nodes );
#if 0
		printf( "self->nodes->size = %i, %i\n", self->nodes->size, nodes->size );
#endif
		if( nodes->size == self->nodes->size ){
			DList_PushBack( cclist, self );
			break;
		}
		subgraph = DaoxGraph_New( self->ctype, self->directed );
		DList_PushBack( cclist, subgraph );
		for(i=0,n=nodes->size; i<n; i++){
			DaoxNode *node = (DaoxNode*) nodes->items.pVoid[i];
			GC_Assign( & node->graph, subgraph );
			DList_PushBack( subgraph->nodes, node );
			for(j=0; j<node->outs->size; j++){
				DaoxEdge *edge = (DaoxEdge*) node->outs->items.pVoid[j];
				if( edge->graph == subgraph ) continue;
				GC_Assign( & edge->graph, subgraph );
				DList_PushBack( subgraph->edges, edge );
			}
		}
		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->graph != self ){
				GC_DecRC( node );
				continue;
			}
			self->nodes->items.pVoid[k++] = node;
		}
		self->nodes->size = k;
		for(i=0,k=0,n=self->edges->size; i<n; i++){
			DaoxNode *edge = (DaoxNode*) self->edges->items.pVoid[i];
			/* Ensure no duplication of the reference (for the Concurrent GC): */
			self->edges->items.pVoid[i] = NULL;
			if( edge->graph != self ){
				GC_DecRC( edge );
				continue;
			}
			self->edges->items.pVoid[k++] = edge;
		}
		self->edges->size = k;
	}
	DList_Delete( nodes );
}
Example #24
0
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 = NULL;
	DaoStackFrame *frame = DaoProcess_FindSectionFrame( proc );
	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_FIND : DaoProcess_PutValue( proc, dao_none_value ); break;
	}
	if( threads <= 0 ) threads = 2;
	if( frame != proc->topFrame->prev ){
		DaoProcess_RaiseError( proc, NULL, "Invalid code section from non-immediate caller" );
		return;
	}
	sect = DaoProcess_InitCodeSection( proc, 0 );
	if( sect == NULL ) return;
	if( list ){
		DList_Clear( list->value );
		if( param->type == DAO_LIST ) DList_Resize( list->value, param->xList.value->size, NULL );
		if( param->type == DAO_MAP ) DList_Resize( list->value, param->xMap.value->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 );
		if( i ) DaoCallServer_AddTask( DaoMT_RunFunctional, task, task->clone );
	}
	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, 2 );
		if( param->type == DAO_LIST && index != -1 ){
			DaoValue **items = param->xList.value->items.pValue;
			GC_Assign( & tuple->values[1], items[index] );
			tuple->values[0]->xInteger.value = index;
		}else if( param->type == DAO_MAP && node ){
			GC_Assign( & tuple->values[0], node->key.pValue );
			GC_Assign( & tuple->values[1], node->value.pValue );
		}
	}
	if( status ) DaoProcess_RaiseError( proc, NULL, "code section execution failed!" );
	DMutex_Destroy( & mutex );
	DCondVar_Destroy( & condv );
	dao_free( tasks );
}