BOOL ChangeTimerQueueTimer(HANDLE TimerQueue, HANDLE Timer, ULONG DueTime, ULONG Period) { struct timespec CurrentTime; WINPR_TIMER_QUEUE* timerQueue; WINPR_TIMER_QUEUE_TIMER* timer; if (!TimerQueue || !Timer) return FALSE; timespec_gettimeofday(&CurrentTime); timerQueue = (WINPR_TIMER_QUEUE*) TimerQueue; timer = (WINPR_TIMER_QUEUE_TIMER*) Timer; pthread_mutex_lock(&(timerQueue->cond_mutex)); RemoveTimerQueueTimer(&(timerQueue->activeHead), timer); RemoveTimerQueueTimer(&(timerQueue->inactiveHead), timer); timer->DueTime = DueTime; timer->Period = Period; timer->next = NULL; timespec_copy(&(timer->StartTime), &CurrentTime); timespec_add_ms(&(timer->StartTime), DueTime); timespec_copy(&(timer->ExpirationTime), &(timer->StartTime)); InsertTimerQueueTimer(&(timerQueue->activeHead), timer); pthread_cond_signal(&(timerQueue->cond)); pthread_mutex_unlock(&(timerQueue->cond_mutex)); return TRUE; }
BOOL DeleteTimerQueueEx(HANDLE TimerQueue, HANDLE CompletionEvent) { void* rvalue; WINPR_TIMER_QUEUE* timerQueue; WINPR_TIMER_QUEUE_TIMER* node; WINPR_TIMER_QUEUE_TIMER* nextNode; if (!TimerQueue) return FALSE; timerQueue = (WINPR_TIMER_QUEUE*) TimerQueue; /* Cancel and delete timer queue timers */ pthread_mutex_lock(&(timerQueue->cond_mutex)); timerQueue->bCancelled = TRUE; pthread_cond_signal(&(timerQueue->cond)); pthread_mutex_unlock(&(timerQueue->cond_mutex)); pthread_join(timerQueue->thread, &rvalue); if (CompletionEvent == INVALID_HANDLE_VALUE) { /* Wait for all callback functions to complete before returning */ } else { /* Cancel all timers and return immediately */ /* Move all active timers to the inactive timer list */ node = timerQueue->activeHead; while (node) { InsertTimerQueueTimer(&(timerQueue->inactiveHead), node); node = node->next; } timerQueue->activeHead = NULL; /* Once all timers are inactive, free them */ node = timerQueue->inactiveHead; while (node) { nextNode = node->next; free(node); node = nextNode; } timerQueue->inactiveHead = NULL; } /* Delete timer queue */ pthread_cond_destroy(&(timerQueue->cond)); pthread_mutex_destroy(&(timerQueue->cond_mutex)); pthread_mutex_destroy(&(timerQueue->mutex)); pthread_attr_destroy(&(timerQueue->attr)); free(timerQueue); if (CompletionEvent && (CompletionEvent != INVALID_HANDLE_VALUE)) SetEvent(CompletionEvent); return TRUE; }
int FireExpiredTimerQueueTimers(WINPR_TIMER_QUEUE* timerQueue) { struct timespec CurrentTime; WINPR_TIMER_QUEUE_TIMER* node; if (!timerQueue->activeHead) return 0; timespec_gettimeofday(&CurrentTime); node = timerQueue->activeHead; while (node) { if (timespec_compare(&CurrentTime, &(node->ExpirationTime)) >= 0) { node->Callback(node->Parameter, TRUE); node->FireCount++; timerQueue->activeHead = node->next; node->next = NULL; if (node->Period) { timespec_add_ms(&(node->ExpirationTime), node->Period); InsertTimerQueueTimer(&(timerQueue->activeHead), node); } else { InsertTimerQueueTimer(&(timerQueue->inactiveHead), node); } node = timerQueue->activeHead; } else { break; } } return 0; }
BOOL CreateTimerQueueTimer(PHANDLE phNewTimer, HANDLE TimerQueue, WAITORTIMERCALLBACK Callback, PVOID Parameter, DWORD DueTime, DWORD Period, ULONG Flags) { struct timespec CurrentTime; WINPR_TIMER_QUEUE* timerQueue; WINPR_TIMER_QUEUE_TIMER* timer; if (!TimerQueue) return FALSE; timespec_gettimeofday(&CurrentTime); timerQueue = (WINPR_TIMER_QUEUE*) TimerQueue; timer = (WINPR_TIMER_QUEUE_TIMER*) malloc(sizeof(WINPR_TIMER_QUEUE_TIMER)); if (!timer) return FALSE; WINPR_HANDLE_SET_TYPE(timer, HANDLE_TYPE_TIMER_QUEUE_TIMER); *((UINT_PTR*) phNewTimer) = (UINT_PTR)(HANDLE) timer; timespec_copy(&(timer->StartTime), &CurrentTime); timespec_add_ms(&(timer->StartTime), DueTime); timespec_copy(&(timer->ExpirationTime), &(timer->StartTime)); timer->Flags = Flags; timer->DueTime = DueTime; timer->Period = Period; timer->Callback = Callback; timer->Parameter = Parameter; timer->timerQueue = (WINPR_TIMER_QUEUE*) TimerQueue; timer->FireCount = 0; timer->next = NULL; pthread_mutex_lock(&(timerQueue->cond_mutex)); InsertTimerQueueTimer(&(timerQueue->activeHead), timer); pthread_cond_signal(&(timerQueue->cond)); pthread_mutex_unlock(&(timerQueue->cond_mutex)); return TRUE; }
BOOL DeleteTimerQueueEx(HANDLE TimerQueue, HANDLE CompletionEvent) { void* rvalue; WINPR_TIMER_QUEUE* timerQueue; WINPR_TIMER_QUEUE_TIMER* node; WINPR_TIMER_QUEUE_TIMER* nextNode; if (!TimerQueue) return FALSE; timerQueue = (WINPR_TIMER_QUEUE*) TimerQueue; /* Cancel and delete timer queue timers */ pthread_mutex_lock(&(timerQueue->cond_mutex)); timerQueue->bCancelled = TRUE; pthread_cond_signal(&(timerQueue->cond)); pthread_mutex_unlock(&(timerQueue->cond_mutex)); pthread_join(timerQueue->thread, &rvalue); /** * Quote from MSDN regarding CompletionEvent: * If this parameter is INVALID_HANDLE_VALUE, the function waits for * all callback functions to complete before returning. * If this parameter is NULL, the function marks the timer for * deletion and returns immediately. * * Note: The current WinPR implementation implicitly waits for any * callback functions to complete (see pthread_join above) */ { /* Move all active timers to the inactive timer list */ node = timerQueue->activeHead; while (node) { InsertTimerQueueTimer(&(timerQueue->inactiveHead), node); node = node->next; } timerQueue->activeHead = NULL; /* Once all timers are inactive, free them */ node = timerQueue->inactiveHead; while (node) { nextNode = node->next; free(node); node = nextNode; } timerQueue->inactiveHead = NULL; } /* Delete timer queue */ pthread_cond_destroy(&(timerQueue->cond)); pthread_mutex_destroy(&(timerQueue->cond_mutex)); pthread_mutex_destroy(&(timerQueue->mutex)); pthread_attr_destroy(&(timerQueue->attr)); free(timerQueue); if (CompletionEvent && (CompletionEvent != INVALID_HANDLE_VALUE)) SetEvent(CompletionEvent); return TRUE; }