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 ); }
static void DaoQueue_Merge( DaoProcess *proc, DaoValue *p[], int N ) { DaoQueue *self = (DaoQueue*)DaoValue_CastCstruct( p[0], NULL ); DaoQueue *other = (DaoQueue*)DaoValue_CastCstruct( p[1], NULL ); int merged = 0; DaoMutex_Lock( self->mtx ); DaoMutex_Lock( other->mtx ); if( !self->capacity || self->size + other->size <= self->capacity ){ if( self->size && other->size ){ self->tail->next = other->head; other->head->previous = self->tail; } else if( !self->size ){ self->head = other->head; self->tail = other->tail; DaoCondVar_BroadCast( self->popvar ); } self->size += other->size; if( other->capacity && other->size == other->capacity ) DaoCondVar_BroadCast( other->pushvar ); other->size = 0; other->head = other->tail = NULL; merged = 1; } DaoMutex_Unlock( self->mtx ); DaoMutex_Unlock( other->mtx ); if( !merged ) DaoProcess_RaiseException( proc, DAO_ERROR, "Merging exceeds the queue capacity" ); }
static void DaoState_Value( DaoProcess *proc, DaoValue *p[], int N ) { DaoState *self = (DaoState*)DaoValue_CastCstruct( p[0], NULL ); DaoMutex_Lock( self->lock ); DaoProcess_PutValue( proc, self->state ); DaoMutex_Unlock( self->lock ); }
static void DaoQueue_Size( DaoProcess *proc, DaoValue *p[], int N ) { DaoQueue *self = (DaoQueue*)DaoValue_CastCstruct( p[0], NULL ); int size; DaoMutex_Lock( self->mtx ); size = self->size; DaoMutex_Unlock( self->mtx ); DaoProcess_PutInteger( proc, size ); }
static void DaoMutex_Lib_Protect( DaoProcess *proc, DaoValue *p[], int n ) { DaoMutex *self = (DaoMutex*) p[0]; DaoVmCode *sect = DaoGetSectionCode( proc->activeCode ); if( sect == NULL || DaoMT_PushSectionFrame( proc ) == 0 ) return; DaoMutex_Lock( self ); DaoProcess_Execute( proc ); DaoMutex_Unlock( self ); DaoProcess_PopFrame( proc ); }
static void DaoState_Waitlist( DaoProcess *proc, DaoValue *p[], int N ) { DaoState *self = (DaoState*)DaoValue_CastCstruct( p[0], NULL ); DaoList *list = DaoProcess_PutList( proc ); DNode *node; DaoMutex_Lock( self->lock ); node = DaoMap_First( self->demands ); while( node ){ DaoList_PushBack( list, DNode_Key( node ) ); node = DaoMap_Next( self->demands, node ); } DaoMutex_Unlock( self->lock ); }
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 ); }
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 DaoQueue_Pop( DaoProcess *proc, DaoValue *p[], int N ) { DaoQueue *self = (DaoQueue*)DaoValue_CastCstruct( p[0], NULL ); QueueItem *item = NULL; DaoMutex_Lock( self->mtx ); while( !self->size ) DaoCondVar_Wait( self->popvar, self->mtx ); item = self->head; self->head = item->next; if( !self->head ) self->tail = NULL; else self->head->previous = NULL; if( self->capacity && self->size == self->capacity ) DaoCondVar_Signal( self->pushvar ); self->size--; DaoMutex_Unlock( self->mtx ); DaoProcess_PutValue( proc, item->value ); DaoGC_DecRC( item->value ); dao_free( item ); }
static void DaoQueue_Push( DaoProcess *proc, DaoValue *p[], int N ) { DaoQueue *self = (DaoQueue*)DaoValue_CastCstruct( p[0], NULL ); QueueItem *item = (QueueItem*)dao_malloc( sizeof(QueueItem) ); item->value = NULL; DaoValue_Copy( p[1], &item->value ); item->next = NULL; DaoMutex_Lock( self->mtx ); while( self->capacity && self->size == self->capacity ) DaoCondVar_Wait( self->pushvar, self->mtx ); item->previous = self->tail; if( self->tail ) self->tail->next = item; else{ self->head = item; DaoCondVar_Signal( self->popvar ); } self->tail = item; self->size++; DaoMutex_Unlock( self->mtx ); }
static void DaoQueue_TryPush( DaoProcess *proc, DaoValue *p[], int N ) { DaoQueue *self = (DaoQueue*)DaoValue_CastCstruct( p[0], NULL ); QueueItem *item = (QueueItem*)dao_malloc( sizeof(QueueItem) ); float timeout = DaoValue_TryGetFloat( p[2] ); int pushable = 0, timed = 0; item->value = NULL; DaoValue_Copy( p[1], &item->value ); item->next = NULL; DaoMutex_Lock( self->mtx ); if( timeout == 0 ) pushable = ( !self->capacity || self->size < self->capacity ); else if( timeout < 0 ){ while( self->capacity && self->size == self->capacity ) DaoCondVar_Wait( self->pushvar, self->mtx ); pushable = 1; } else{ while( !timed && self->capacity && self->size == self->capacity ) timed = DaoCondVar_TimedWait( self->pushvar, self->mtx, timeout ); pushable = !timed; } if( pushable ){ item->previous = self->tail; if( self->tail ) self->tail->next = item; else{ self->head = item; DaoCondVar_Signal( self->popvar ); } self->tail = item; self->size++; } DaoMutex_Unlock( self->mtx ); if( !pushable ){ DaoGC_DecRC( item->value ); dao_free( item ); } DaoProcess_PutInteger( proc, pushable ); }
static void DaoQueue_TryPop( DaoProcess *proc, DaoValue *p[], int N ) { DaoQueue *self = (DaoQueue*)DaoValue_CastCstruct( p[0], NULL ); QueueItem *item = NULL; float timeout = DaoValue_TryGetFloat( p[1] ); int popable = 0, timed = 0; DaoMutex_Lock( self->mtx ); if( timeout == 0 ) popable = self->size; else if( timeout < 0 ){ while( !self->size ) DaoCondVar_Wait( self->popvar, self->mtx ); popable = 1; } else{ while( !timed && !self->size ) timed = DaoCondVar_TimedWait( self->popvar, self->mtx, timeout ); popable = !timed; } if( popable ){ item = self->head; self->head = item->next; if( !self->head ) self->tail = NULL; else self->head->previous = NULL; if( self->capacity && self->size == self->capacity ) DaoCondVar_Signal( self->pushvar ); self->size--; } DaoMutex_Unlock( self->mtx ); DaoProcess_PutValue( proc, item? item->value : dao_none_value ); if( item ){ DaoGC_DecRC( item->value ); dao_free( item ); } }
static void DaoMutex_Lib_Unlock( DaoProcess *proc, DaoValue *par[], int N ) { DaoMutex *self = (DaoMutex*) par[0]; DaoMutex_Unlock( self ); }