static void SYS_Sleep( DaoProcess *proc, DaoValue *p[], int N ) { #ifdef DAO_WITH_THREAD DMutex mutex; DCondVar condv; #endif double s = p[0]->xFloat.value; if( s < 0 ){ DaoProcess_RaiseException( proc, DAO_WARNING_VALUE, "expecting positive value" ); return; } #ifdef DAO_WITH_THREAD /* sleep only the current thread: */ DMutex_Init( & mutex ); DCondVar_Init( & condv ); DMutex_Lock( & mutex ); DCondVar_TimedWait( & condv, & mutex, s ); DMutex_Unlock( & mutex ); DMutex_Destroy( & mutex ); DCondVar_Destroy( & condv ); #elif UNIX sleep( (int)s ); /* This may cause the whole process to sleep. */ #else Sleep( s * 1000 ); #endif }
static void DaoCondV_Lib_TimedWait( DaoProcess *proc, DaoValue *par[], int N ) { DaoCondVar *self = (DaoCondVar*) par[0]; DaoMutex *mutex = (DaoMutex*) par[1]; DaoProcess_PutInteger( proc, DCondVar_TimedWait( & self->myCondVar, & mutex->myMutex, par[2]->xFloat.value ) ); }
void DaoCallServer_AddTimedWait( DaoProcess *wait, DaoTaskEvent *event, double timeout ) { DaoCallServer *server; if( daoCallServer == NULL ) DaoCallServer_Init( mainVmSpace ); server = daoCallServer; DMutex_Lock( & server->mutex ); if( timeout >= 1E-27 ){ server->timestamp.value.real = timeout + Dao_GetCurrentTime(); server->timestamp.value.imag += 1; event->expiring = server->timestamp.value.real; DMap_Insert( server->waitings, & server->timestamp, event ); DMap_Insert( server->pending, event, NULL ); DCondVar_Signal( & server->condv2 ); }else{ event->expiring = -1.0; DaoCallServer_AddEvent( event ); DCondVar_Signal( & server->condv ); } if( wait->condv ){ /* // Need to suspend the native thread, for suspending inside code sections // for functional methods such as std.iterate(), mt.iterate() etc: */ wait->pauseType = DAO_PAUSE_NATIVE_THREAD; if( timeout > 0 ){ DCondVar_TimedWait( wait->condv, & server->mutex, timeout ); }else{ DCondVar_Wait( wait->condv, & server->mutex ); } wait->status = DAO_PROCESS_RUNNING; } DMutex_Unlock( & server->mutex ); }
void DaoCallServer_Stop() { DCondVar condv; DaoCallThread *calth; if( daoCallServer == NULL ) return; DCondVar_Init( & condv ); daoCallServer->finishing = 1; calth = DaoCallThread_New( NULL, NULL ); DMutex_Lock( & daoCallServer->mutex ); daoCallServer->total += 1; DMutex_Unlock( & daoCallServer->mutex ); DaoCallThread_Run( calth ); /* process tasks in the main thread; */ DMutex_Lock( & daoCallServer->mutex ); while( daoCallServer->stopped != daoCallServer->total || daoCallServer->timing ){ DCondVar_TimedWait( & condv, & daoCallServer->mutex, 0.01 ); } DMutex_Unlock( & daoCallServer->mutex ); DCondVar_Destroy( & condv ); DaoCallThread_Delete( calth ); DaoCallServer_Delete( daoCallServer ); daoCallServer = NULL; }
void DThread_PauseVM( DThread *another ) { another->vmpause = 1; DMutex_Lock( & another->mutex ); if( ! another->vmpaused ){ DCondVar_TimedWait( & another->condv, & another->mutex, 0.01 ); } DMutex_Unlock( & another->mutex ); }
static void DaoCallServer_Timer( void *p ) { DaoCallServer *server = daoCallServer; double time = 0.0; daoint i, timeout; server->timing = 1; while( server->finishing == 0 || server->stopped != server->total ){ DMutex_Lock( & server->mutex ); while( server->waitings->size == 0 ){ if( server->idle == server->total && server->events2->size ){ DaoCallServer_ActivateEvents(); } if( server->finishing && server->stopped == server->total ) break; DCondVar_TimedWait( & server->condv2, & server->mutex, 0.01 ); } if( server->waitings->size ){ DNode *node = DMap_First( server->waitings ); time = node->key.pValue->xComplex.value.real; time -= Dao_GetCurrentTime(); /* wait the right amount of time for the closest arriving timeout: */ if( time > 0 ) DCondVar_TimedWait( & server->condv2, & server->mutex, time ); } DMutex_Unlock( & server->mutex ); if( server->finishing && server->stopped == server->total ) break; DMutex_Lock( & server->mutex ); if( server->waitings->size ){ /* a new wait timed out: */ DNode *node = DMap_First( server->waitings ); time = Dao_GetCurrentTime(); if( node->key.pValue->xComplex.value.real < time ){ DaoTaskEvent *event = (DaoTaskEvent*) node->value.pVoid; event->state = DAO_EVENT_RESUME; event->timeout = 1; event->expiring = MIN_TIME; DArray_Append( server->events, node->value.pVoid ); DMap_EraseNode( server->waitings, node ); } } DCondVar_Signal( & server->condv ); DMutex_Unlock( & server->mutex ); } server->timing = 0; }
void DaoCallServer_Stop() { DCondVar condv; if( daoCallServer == NULL ) return; DCondVar_Init( & condv ); daoCallServer->finishing = 1; DMutex_Lock( & daoCallServer->mutex ); while( daoCallServer->pending->size || daoCallServer->idle != daoCallServer->total ){ /* printf( "finalizing: %3i %3i\n", daoCallServer->idle, daoCallServer->total ); */ DCondVar_TimedWait( & condv, & daoCallServer->mutex, 0.01 ); } while( daoCallServer->stopped != daoCallServer->total || daoCallServer->timing ){ DCondVar_TimedWait( & condv, & daoCallServer->mutex, 0.01 ); } DMutex_Unlock( & daoCallServer->mutex ); DCondVar_Destroy( & condv ); DaoCallServer_Delete( daoCallServer ); daoCallServer = NULL; }
void DaoCallServer_Join() { DCondVar condv; if( daoCallServer == NULL ) return; DCondVar_Init( & condv ); DMutex_Lock( & daoCallServer->mutex ); while( daoCallServer->pending->size || daoCallServer->vacant != daoCallServer->total ){ DCondVar_TimedWait( & condv, & daoCallServer->mutex, 0.01 ); } DMutex_Unlock( & daoCallServer->mutex ); DCondVar_Destroy( & condv ); }
void DaoVmSpace_JoinTasklets( DaoVmSpace *self ) { DaoTaskletServer *server = (DaoTaskletServer*) self->taskletServer; DCondVar condv; if( server == NULL ) return; DCondVar_Init( & condv ); DMutex_Lock( & server->mutex ); while( server->pending->size || server->vacant != server->total ){ DCondVar_TimedWait( & condv, & server->mutex, 0.01 ); } DMutex_Unlock( & server->mutex ); DCondVar_Destroy( & 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 ); self->taskOwner = NULL; } while( server->vmspace->stopit == 0 ){ 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; server->vacant += self->taskOwner == NULL; 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->vmspace->stopit ) break; if( server->finishing && server->vacant == server->total ){ if( (server->events2->size + server->waitings->size) == 0 ) break; } wt = 0.01*(server->idle == server->total) + 0.001; 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 ); self->taskOwner = server->owners->items.pVoid[i]; function = (DThreadTask) server->functions->items.pVoid[i]; parameter = param; DList_Erase( server->functions, i, 1 ); DList_Erase( server->parameters, i, 1 ); DList_Erase( server->owners, i, 1 ); DMap_Erase( server->pending, parameter ); server->idle -= 1; server->vacant -= 1; break; } DMutex_Unlock( & server->mutex ); if( server->vmspace->stopit ) break; if( function ){ (*function)( parameter ); self->taskOwner = NULL; DMutex_Lock( & server->mutex ); DMap_Erase( server->active, parameter ); DMutex_Unlock( & server->mutex ); continue; } if( server->pending->size == 0 && server->finishing && server->vacant == server->total ) break; DMutex_Lock( & server->mutex ); server->idle -= 1; server->vacant -= self->taskOwner == NULL; 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_Start( process ); if( process->exceptions->size > count ) DaoProcess_PrintException( process, NULL, 1 ); if( process->status <= DAO_PROCESS_ABORTED ) self->taskOwner = NULL; 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 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 = DaoGetSectionCode( proc->activeCode ); 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_APPLY : DaoProcess_PutValue( proc, param ); break; case DVM_FUNCT_FIND : DaoProcess_PutValue( proc, dao_none_value ); break; } if( threads <= 0 ) threads = 2; if( sect == NULL || DaoMT_PushSectionFrame( proc ) == 0 ) return; if( list ){ DArray_Clear( & list->items ); if( param->type == DAO_LIST ) DArray_Resize( & list->items, param->xList.items.size, NULL ); if( param->type == DAO_MAP ) DArray_Resize( & list->items, param->xMap.items->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 ); task->clone->mutex = & mutex; if( i ) DaoCallServer_AddTask( DaoMT_RunFunctional, task, 1 ); } 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, 0 ); if( param->type == DAO_LIST && index != -1 ){ DaoValue **items = param->xList.items.items.pValue; GC_ShiftRC( items[index], tuple->items[1] ); tuple->items[1] = items[index]; tuple->items[0]->xInteger.value = index; }else if( param->type == DAO_MAP && node ){ GC_ShiftRC( node->key.pValue, tuple->items[0] ); GC_ShiftRC( node->value.pValue, tuple->items[1] ); tuple->items[0] = node->key.pValue; tuple->items[1] = node->value.pValue; } } if( status ) DaoProcess_RaiseException( proc, DAO_ERROR, "code section execution failed!" ); DMutex_Destroy( & mutex ); DCondVar_Destroy( & condv ); dao_free( tasks ); }
int DaoCondVar_TimedWait( DaoCondVar *self, DaoMutex *mutex, double seconds ) { return DCondVar_TimedWait( & self->myCondVar, & mutex->myMutex, seconds ); }
static void DaoCallThread_Run( DaoCallThread *self ) { DaoCallServer *server = daoCallServer; double wt = 0.001; daoint i, 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; 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; } if( process->pauseType == DAO_PAUSE_NATIVE_THREAD ){ DMutex_Lock( & server->mutex ); process->pauseType = 0; /* TODO: demo/concurrent/future.dao */ if( process->condv ) DCondVar_Signal( process->condv ); DMutex_Unlock( & server->mutex ); }else{ int 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 ){ DMutex_Lock( & server->mutex ); DMap_Erase( server->active, future->actor->rootObject ); DMutex_Unlock( & server->mutex ); } DMutex_Lock( & server->mutex ); DMap_Erase( server->active, process ); 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 ); }