FreeRDP
TestSynchTimerQueue.c
1 
2 #include <winpr/crt.h>
3 #include <winpr/sysinfo.h>
4 #include <winpr/file.h>
5 #include <winpr/synch.h>
6 
7 #define FIRE_COUNT 5
8 #define TIMER_COUNT 5
9 
10 struct apc_data
11 {
12  DWORD TimerId;
13  DWORD FireCount;
14  DWORD DueTime;
15  DWORD Period;
16  UINT32 StartTime;
17  DWORD MaxFireCount;
18  HANDLE CompletionEvent;
19 };
20 typedef struct apc_data APC_DATA;
21 
22 static VOID CALLBACK TimerRoutine(PVOID lpParam, BOOLEAN TimerOrWaitFired)
23 {
24  UINT32 TimerTime = 0;
25  APC_DATA* apcData = NULL;
26  UINT32 expectedTime = 0;
27  UINT32 CurrentTime = GetTickCount();
28 
29  WINPR_UNUSED(TimerOrWaitFired);
30 
31  if (!lpParam)
32  return;
33 
34  apcData = (APC_DATA*)lpParam;
35 
36  TimerTime = CurrentTime - apcData->StartTime;
37  expectedTime = apcData->DueTime + (apcData->Period * apcData->FireCount);
38 
39  apcData->FireCount++;
40 
41  printf("TimerRoutine: TimerId: %" PRIu32 " FireCount: %" PRIu32 " ActualTime: %" PRIu32
42  " ExpectedTime: %" PRIu32 " Discrepancy: %" PRIu32 "\n",
43  apcData->TimerId, apcData->FireCount, TimerTime, expectedTime, TimerTime - expectedTime);
44 
45  Sleep(11);
46 
47  if (apcData->FireCount == apcData->MaxFireCount)
48  {
49  (void)SetEvent(apcData->CompletionEvent);
50  }
51 }
52 
53 int TestSynchTimerQueue(int argc, char* argv[])
54 {
55  HANDLE hTimerQueue = NULL;
56  HANDLE hTimers[TIMER_COUNT];
57  APC_DATA apcData[TIMER_COUNT];
58 
59  WINPR_UNUSED(argc);
60  WINPR_UNUSED(argv);
61 
62  hTimerQueue = CreateTimerQueue();
63 
64  if (!hTimerQueue)
65  {
66  printf("CreateTimerQueue failed (%" PRIu32 ")\n", GetLastError());
67  return -1;
68  }
69 
70  for (DWORD index = 0; index < TIMER_COUNT; index++)
71  {
72  apcData[index].TimerId = index;
73  apcData[index].StartTime = GetTickCount();
74  apcData[index].DueTime = (index * 10) + 50;
75  apcData[index].Period = 100;
76  apcData[index].FireCount = 0;
77  apcData[index].MaxFireCount = FIRE_COUNT;
78 
79  if (!(apcData[index].CompletionEvent = CreateEvent(NULL, TRUE, FALSE, NULL)))
80  {
81  printf("Failed to create apcData[%" PRIu32 "] event (%" PRIu32 ")\n", index,
82  GetLastError());
83  return -1;
84  }
85 
86  if (!CreateTimerQueueTimer(&hTimers[index], hTimerQueue, TimerRoutine, &apcData[index],
87  apcData[index].DueTime, apcData[index].Period, 0))
88  {
89  printf("CreateTimerQueueTimer failed (%" PRIu32 ")\n", GetLastError());
90  return -1;
91  }
92  }
93 
94  for (DWORD index = 0; index < TIMER_COUNT; index++)
95  {
96  if (WaitForSingleObject(apcData[index].CompletionEvent, 2000) != WAIT_OBJECT_0)
97  {
98  printf("Failed to wait for timer queue timer #%" PRIu32 " (%" PRIu32 ")\n", index,
99  GetLastError());
100  return -1;
101  }
102  }
103 
104  for (DWORD index = 0; index < TIMER_COUNT; index++)
105  {
110  if (!DeleteTimerQueueTimer(hTimerQueue, hTimers[index], INVALID_HANDLE_VALUE))
111  {
112  printf("DeleteTimerQueueTimer failed (%" PRIu32 ")\n", GetLastError());
113  return -1;
114  }
115  (void)CloseHandle(apcData[index].CompletionEvent);
116  }
117 
118  if (!DeleteTimerQueue(hTimerQueue))
119  {
120  printf("DeleteTimerQueue failed (%" PRIu32 ")\n", GetLastError());
121  return -1;
122  }
123 
124  return 0;
125 }