static void DaoState_WaitFor2( DaoProcess *proc, DaoValue *p[], int N ) { DaoState *self = (DaoState*)DaoValue_CastCstruct( p[0], NULL ); int eq = 0, res = 1; DaoValue *state = p[1]; float timeout; DaoCondVar *condvar = NULL; DaoMutex_Lock( self->lock ); if( !DaoValue_Compare( self->state, state ) ) eq = 1; else{ condvar = (DaoCondVar*)DaoMap_GetValue( self->demands, state ); if( !condvar ){ condvar = DaoCondVar_New(); DaoMap_Insert( self->demands, state, (DaoValue*)condvar ); } } DaoMutex_Unlock( self->lock ); if( !eq ){ DaoMutex_Lock( self->defmtx ); timeout = DaoValue_TryGetFloat( p[2] ); if( timeout > 0 ) do res = !DaoCondVar_TimedWait( condvar, self->defmtx, timeout ); while( res && DaoValue_Compare( self->state, state ) ); else if( timeout == 0 ) res = 0; else do DaoCondVar_Wait( condvar, self->defmtx ); while( DaoValue_Compare( self->state, state ) ); DaoMutex_Unlock( self->defmtx ); } DaoProcess_PutInteger( proc, res ); }
int DaoValue_Compare( DaoValue *left, DaoValue *right ) { double L, R; int res = 0; if( left == right ) return 0; if( left == NULL || right == NULL ) return left < right ? -100 : 100; if( left->type != right->type ){ res = left->type < right->type ? -100 : 100; if( right->type == DAO_TUPLE && right->xTuple.subtype == DAO_PAIR ){ if( (res = DaoValue_Compare( left, right->xTuple.items[0] )) <= 0 ) return res; if( (res = DaoValue_Compare( left, right->xTuple.items[1] )) >= 0 ) return res; return 0; }else if( left->type == DAO_TUPLE && left->xTuple.subtype == DAO_PAIR ){ if( (res = DaoValue_Compare( left->xTuple.items[0], right )) >= 0 ) return res; if( (res = DaoValue_Compare( left->xTuple.items[1], right )) <= 0 ) return res; return 0; } #ifdef DAO_WITH_LONGINT if( left->type == DAO_LONG && (right->type && right->type <= DAO_DOUBLE) ){ if( right->type == DAO_INTEGER ){ return DLong_CompareToInteger( left->xLong.value, right->xInteger.value ); } return DLong_CompareToDouble( left->xLong.value, DaoValue_GetDouble( right ) ); }else if( right->type == DAO_LONG && (left->type && left->type <= DAO_DOUBLE) ){ if( left->type == DAO_INTEGER ){ return - DLong_CompareToInteger( right->xLong.value, left->xInteger.value ); } return - DLong_CompareToDouble( right->xLong.value, DaoValue_GetDouble( left ) ); } #endif if( left->type < DAO_INTEGER || left->type > DAO_DOUBLE ) return res; if( right->type < DAO_INTEGER || right->type > DAO_DOUBLE ) return res; L = DaoValue_GetDouble( left ); R = DaoValue_GetDouble( right ); return L == R ? 0 : (L < R ? -1 : 1); } switch( left->type ){ case DAO_NONE : return 0; case DAO_INTEGER : return number_compare( left->xInteger.value, right->xInteger.value ); case DAO_FLOAT : return number_compare( left->xFloat.value, right->xFloat.value ); case DAO_DOUBLE : return number_compare( left->xDouble.value, right->xDouble.value ); case DAO_COMPLEX : return DaoComplex_Compare( & left->xComplex, & right->xComplex ); #ifdef DAO_WITH_LONGINT case DAO_LONG : return DLong_Compare( left->xLong.value, right->xLong.value ); #endif case DAO_STRING : return DString_Compare( left->xString.data, right->xString.data ); case DAO_ENUM : return DaoEnum_Compare( & left->xEnum, & right->xEnum ); case DAO_TUPLE : return DaoTuple_Compare( & left->xTuple, & right->xTuple ); case DAO_LIST : return DaoList_Compare( & left->xList, & right->xList ); case DAO_CDATA : case DAO_CSTRUCT : case DAO_CTYPE : return DaoCstruct_Compare( left, right ); #ifdef DAO_WITH_NUMARRAY case DAO_ARRAY : return DaoArray_Compare( & left->xArray, & right->xArray ); #endif } return left < right ? -100 : 100; /* needed for map */ }
int DaoTuple_Compare( DaoTuple *lt, DaoTuple *rt ) { int i, lb, rb, res; if( lt->size < rt->size ) return -100; if( lt->size > rt->size ) return 100; for(i=0; i<lt->size; i++){ DaoValue *lv = lt->items[i]; DaoValue *rv = rt->items[i]; int lb = lv ? lv->type : 0; int rb = rv ? rv->type : 0; if( lb == rb && lb == DAO_TUPLE ){ res = DaoTuple_Compare( (DaoTuple*) lv, (DaoTuple*) rv ); if( res != 0 ) return res; }else if( lb != rb || lb ==0 || lb > DAO_ARRAY || lb == DAO_COMPLEX ){ if( lv < rv ){ return -100; }else if( lv > rv ){ return 100; } }else{ res = DaoValue_Compare( lv, rv ); if( res != 0 ) return res; } } return 0; }
static void DaoState_TestSet( DaoProcess *proc, DaoValue *p[], int N ) { DaoState *self = (DaoState*)DaoValue_CastCstruct( p[0], NULL ); int set = 0; DNode *node; DaoMutex_Lock( self->lock ); if( !DaoValue_Compare( self->state, p[1] ) ){ DaoValue_Copy( p[2], &self->state ); set = 1; node = DaoMap_First( self->demands ); while( node && DaoValue_Compare( DNode_Key( node ), self->state ) ) node = DaoMap_Next( self->demands, node ); if( node ) DaoCondVar_BroadCast( (DaoCondVar*)DNode_Value( node ) ); } DaoMutex_Unlock( self->lock ); DaoProcess_PutInteger( proc, set ); }
static void DaoMT_RunMapFunctional( void *p ) { DaoValue *res; DaoInteger tidint = {DAO_INTEGER,0,0,0,0,0}; DaoValue *threadid = (DaoValue*)(void*)&tidint; DaoTaskData *self = (DaoTaskData*)p; DaoMap *map = (DaoMap*) self->param; DaoList *list2 = (DaoList*) self->result; DaoProcess *clone = self->clone; DaoVmCode *sect = self->sect; DaoType *type = map->ctype; DNode *node = NULL; daoint i = 0; DaoMT_InitProcess( self->proto, clone, 3 ); tidint.value = self->first; type = type && type->nested->size > 1 ? type->nested->items.pType[1] : NULL; for(node=DMap_First( map->value ); node; node=DMap_Next(map->value, node) ){ if( (i++) % self->step != self->first ) continue; if( sect->b >0 ) DaoProcess_SetValue( clone, sect->a, node->key.pValue ); if( sect->b >1 ) DaoProcess_SetValue( clone, sect->a+1, node->value.pValue ); if( sect->b >2 ) DaoProcess_SetValue( clone, sect->a+2, threadid ); clone->topFrame->entry = self->entry; DaoProcess_Execute( clone ); if( clone->status != DAO_PROCESS_FINISHED ) break; res = clone->stackValues[0]; if( self->funct == DVM_FUNCT_MAP ){ self->status |= DaoList_SetItem( list2, res, i-1 ); }else if( self->funct == DVM_FUNCT_APPLY ){ self->status |= DaoValue_Move( res, & node->value.pValue, type ) == 0; }else if( self->funct == DVM_FUNCT_FIND ){ DNode **p = self->node; /* XXX: 2014-11-11 */ if( *p && DaoValue_Compare( (*p)->key.pValue, node->key.pValue ) < 0 ) break; if( res->xInteger.value ){ DMutex_Lock( self->mutex ); if( *p == NULL || DaoValue_Compare( (*p)->key.pValue, node->key.pValue ) >0 ) *p = node; DMutex_Unlock( self->mutex ); break; } } } }
static void DaoState_Set( DaoProcess *proc, DaoValue *p[], int N ) { DaoState *self = (DaoState*)DaoValue_CastCstruct( p[0], NULL ); DNode *node; DaoMutex_Lock( self->lock ); DaoValue_Copy( p[1], &self->state ); node = DaoMap_First( self->demands ); while( node && DaoValue_Compare( DNode_Key( node ), self->state ) ) node = DaoMap_Next( self->demands, node ); if( node ){ DaoCondVar_BroadCast( (DaoCondVar*)DNode_Value( node ) ); DaoMap_Erase( self->demands, DNode_Key( node ) ); } DaoMutex_Unlock( self->lock ); }
int DaoList_Compare( DaoList *list1, DaoList *list2 ) { DaoValue **d1 = list1->items.items.pValue; DaoValue **d2 = list2->items.items.pValue; int size1 = list1->items.size; int size2 = list2->items.size; int min = size1 < size2 ? size1 : size2; int res = size1 == size2 ? 1 : 100; int i = 0, cmp = 0; /* find the first unequal items */ while( i < min && (cmp = DaoValue_Compare(*d1, *d2)) ==0 ) i++, d1++, d2++; if( i < min ){ if( abs( cmp > 1 ) ) return cmp; return cmp * res; } if( size1 == size2 ) return 0; return size1 < size2 ? -100 : 100; }
int DaoValue_Move5( DaoValue *S, DaoValue **D, DaoType *T, DMap *defs, DaoDataCache *cache ) { DaoValue *D2 = *D; if( S == D2 ) return 1; if( S == NULL ){ GC_DecRC( *D ); *D = NULL; return 0; } if( T == NULL ){ DaoValue_CopyX( S, D, cache ); return 1; } switch( T->tid ){ case DAO_UDT : DaoValue_CopyX( S, D, cache ); return 1; case DAO_THT : if( T->aux ) return DaoValue_Move4( S, D, (DaoType*) T->aux, defs, cache ); DaoValue_CopyX( S, D, cache ); return 1; case DAO_ANY : DaoValue_CopyX( S, D, cache ); DaoValue_SetType( *D, T ); return 1; case DAO_VALTYPE : if( DaoValue_Compare( S, T->aux ) !=0 ) return 0; DaoValue_CopyX( S, D, cache ); return 1; case DAO_VARIANT : return DaoValue_MoveVariant( S, D, T ); default : break; } if( D2 && D2->xBase.refCount >1 ){ GC_DecRC( D2 ); *D = D2 = NULL; } if( D2 == NULL || D2->type != T->tid ) return DaoValue_Move4( S, D, T, defs, cache ); switch( (S->type << 8) | T->tid ){ case (DAO_STRING<<8)|DAO_STRING : DString_Assign( D2->xString.data, S->xString.data ); break; case (DAO_ENUM<<8)|DAO_ENUM : DaoEnum_SetType( & D2->xEnum, T ); DaoEnum_SetValue( & D2->xEnum, & S->xEnum, NULL ); 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_INTEGER<<8)|DAO_DOUBLE : D2->xDouble.value = S->xInteger.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_FLOAT <<8)|DAO_DOUBLE : D2->xDouble.value = S->xFloat.value; break; case (DAO_DOUBLE <<8)|DAO_INTEGER : D2->xInteger.value = S->xDouble.value; break; case (DAO_DOUBLE <<8)|DAO_FLOAT : D2->xFloat.value = S->xDouble.value; break; case (DAO_DOUBLE <<8)|DAO_DOUBLE : D2->xDouble.value = S->xDouble.value; break; case (DAO_COMPLEX<<8)|DAO_COMPLEX : D2->xComplex.value = S->xComplex.value; break; #ifdef DAO_WITH_LONGINT case (DAO_LONG <<8)|DAO_LONG : DLong_Move( D2->xLong.value, S->xLong.value ); break; #endif default : return DaoValue_Move4( S, D, T, defs, cache ); } return 1; }
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; }