diff --git a/winpr/libwinpr/synch/synch.h b/winpr/libwinpr/synch/synch.h index 9be3cc08e..282d3857f 100644 --- a/winpr/libwinpr/synch/synch.h +++ b/winpr/libwinpr/synch/synch.h @@ -107,9 +107,19 @@ struct winpr_timer }; typedef struct winpr_timer WINPR_TIMER; +typedef struct winpr_timer_queue_timer WINPR_TIMER_QUEUE_TIMER; + struct winpr_timer_queue { WINPR_HANDLE_DEF(); + + pthread_t thread; + pthread_attr_t attr; + pthread_cond_t cond; + pthread_mutex_t mutex; + struct sched_param param; + + WINPR_TIMER_QUEUE_TIMER* head; }; typedef struct winpr_timer_queue WINPR_TIMER_QUEUE; @@ -122,8 +132,12 @@ struct winpr_timer_queue_timer DWORD Period; PVOID Parameter; WAITORTIMERCALLBACK Callback; + + WINPR_TIMER_QUEUE* timerQueue; + + WINPR_TIMER_QUEUE_TIMER* prev; + WINPR_TIMER_QUEUE_TIMER* next; }; -typedef struct winpr_timer_queue_timer WINPR_TIMER_QUEUE_TIMER; #endif diff --git a/winpr/libwinpr/synch/test/TestSynchTimerQueue.c b/winpr/libwinpr/synch/test/TestSynchTimerQueue.c index 07efd29f3..3400a863c 100644 --- a/winpr/libwinpr/synch/test/TestSynchTimerQueue.c +++ b/winpr/libwinpr/synch/test/TestSynchTimerQueue.c @@ -48,6 +48,12 @@ int TestSynchTimerQueue(int argc, char* argv[]) CloseHandle(gDoneEvent); + if (!DeleteTimerQueueTimer(hTimerQueue, hTimer, NULL)) + { + printf("DeleteTimerQueueTimer failed (%d)\n", GetLastError()); + return -1; + } + if (!DeleteTimerQueue(hTimerQueue)) { printf("DeleteTimerQueue failed (%d)\n", GetLastError()); diff --git a/winpr/libwinpr/synch/timer.c b/winpr/libwinpr/synch/timer.c index ec5bdb928..e1afedcba 100644 --- a/winpr/libwinpr/synch/timer.c +++ b/winpr/libwinpr/synch/timer.c @@ -320,6 +320,59 @@ BOOL CancelWaitableTimer(HANDLE hTimer) * Timer-Queue Timer */ +/** + * Design, Performance, and Optimization of Timer Strategies for Real-time ORBs: + * http://www.cs.wustl.edu/~schmidt/Timer_Queue.html + */ + +static void* TimerQueueThread(void* arg) +{ + //WINPR_TIMER_QUEUE* timerQueue = (WINPR_TIMER_QUEUE*) arg; + + return NULL; +} + +int StartTimerQueueThread(WINPR_TIMER_QUEUE* timerQueue) +{ + pthread_cond_init(&(timerQueue->cond), NULL); + pthread_mutex_init(&(timerQueue->mutex), NULL); + + pthread_attr_init(&(timerQueue->attr)); + timerQueue->param.sched_priority = sched_get_priority_max(SCHED_FIFO); + pthread_attr_setschedparam(&(timerQueue->attr), &(timerQueue->param)); + pthread_attr_setschedpolicy(&(timerQueue->attr), SCHED_FIFO); + pthread_create(&(timerQueue->thread), &(timerQueue->attr), TimerQueueThread, timerQueue); + + return 0; +} + +int InsertTimerQueueTimer(WINPR_TIMER_QUEUE* timerQueue, WINPR_TIMER_QUEUE_TIMER* timer) +{ + WINPR_TIMER_QUEUE_TIMER* node; + + if (!timerQueue->head) + { + timerQueue->head = timer; + timer->prev = NULL; + timer->next = NULL; + return 0; + } + + node = timerQueue->head; + + do + { + node = node->next; + } + while (node->next); + + node->next = timer; + timer->prev = node; + timer->next = NULL; + + return 0; +} + HANDLE CreateTimerQueue(void) { HANDLE handle = NULL; @@ -331,6 +384,8 @@ HANDLE CreateTimerQueue(void) { WINPR_HANDLE_SET_TYPE(timerQueue, HANDLE_TYPE_TIMER_QUEUE); handle = (HANDLE) timerQueue; + + StartTimerQueueThread(timerQueue); } return handle; @@ -367,11 +422,13 @@ BOOL DeleteTimerQueueEx(HANDLE TimerQueue, HANDLE CompletionEvent) BOOL CreateTimerQueueTimer(PHANDLE phNewTimer, HANDLE TimerQueue, WAITORTIMERCALLBACK Callback, PVOID Parameter, DWORD DueTime, DWORD Period, ULONG Flags) { + WINPR_TIMER_QUEUE* timerQueue; WINPR_TIMER_QUEUE_TIMER* timer; + timerQueue = (WINPR_TIMER_QUEUE*) TimerQueue; timer = (WINPR_TIMER_QUEUE_TIMER*) malloc(sizeof(WINPR_TIMER_QUEUE_TIMER)); - if (!timer) + if (timer || !TimerQueue) return FALSE; WINPR_HANDLE_SET_TYPE(timer, HANDLE_TYPE_TIMER_QUEUE_TIMER); @@ -382,6 +439,8 @@ BOOL CreateTimerQueueTimer(PHANDLE phNewTimer, HANDLE TimerQueue, timer->Period = Period; timer->Callback = Callback; timer->Parameter = Parameter; + + timer->timerQueue = (WINPR_TIMER_QUEUE*) TimerQueue; return TRUE; }