void DaoCallServer_AddTimedWait( DaoProcess *wait, DaoTaskEvent *event, double timeout ) { DaoCallServer *server = daoCallServer; /* // The "wait" process may not be running in the thread pool, // so it may have not been added to active process list. // It is necessary to add it to the active list now, // to avoid it being activated immediately after it is blocked. // Activating it immediately may cause a race condition, // because it may have not been blocked completely // (namely, it may be still running). */ DaoCallServer_MarkActiveProcess( wait, 1 ); DMutex_Lock( & server->mutex ); if( timeout >= 1E-27 ){ server->timestamp.real = timeout + Dao_GetCurrentTime(); server->timestamp.imag += 1; event->expiring = server->timestamp.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 ); } DMutex_Unlock( & server->mutex ); }
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 ); }
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; }