FreeRDP
Loading...
Searching...
No Matches
CountdownEvent.c
1
20#include <winpr/config.h>
21#include <winpr/assert.h>
22
23#include <winpr/crt.h>
24
25#include <winpr/collections.h>
26
27struct CountdownEvent
28{
29 size_t count;
31 HANDLE event;
32 size_t initialCount;
33};
34
48size_t CountdownEvent_CurrentCount(wCountdownEvent* countdown)
49{
50 WINPR_ASSERT(countdown);
51 EnterCriticalSection(&countdown->lock);
52 const size_t rc = countdown->count;
53 LeaveCriticalSection(&countdown->lock);
54 return rc;
55}
56
61size_t CountdownEvent_InitialCount(wCountdownEvent* countdown)
62{
63 WINPR_ASSERT(countdown);
64 EnterCriticalSection(&countdown->lock);
65 const size_t rc = countdown->initialCount;
66 LeaveCriticalSection(&countdown->lock);
67 return rc;
68}
69
74BOOL CountdownEvent_IsSet(wCountdownEvent* countdown)
75{
76 BOOL status = FALSE;
77
78 WINPR_ASSERT(countdown);
79 if (WaitForSingleObject(countdown->event, 0) == WAIT_OBJECT_0)
80 status = TRUE;
81
82 return status;
83}
84
89HANDLE CountdownEvent_WaitHandle(wCountdownEvent* countdown)
90{
91 WINPR_ASSERT(countdown);
92 return countdown->event;
93}
94
103void CountdownEvent_AddCount(wCountdownEvent* countdown, size_t signalCount)
104{
105 WINPR_ASSERT(countdown);
106 EnterCriticalSection(&countdown->lock);
107
108 const BOOL signalSet = countdown->count == 0;
109 countdown->count += signalCount;
110
111 if (signalSet)
112 (void)ResetEvent(countdown->event);
113
114 LeaveCriticalSection(&countdown->lock);
115}
116
122BOOL CountdownEvent_Signal(wCountdownEvent* countdown, size_t signalCount)
123{
124 BOOL status = FALSE;
125 BOOL newStatus = FALSE;
126 BOOL oldStatus = FALSE;
127
128 WINPR_ASSERT(countdown);
129
130 EnterCriticalSection(&countdown->lock);
131
132 if (WaitForSingleObject(countdown->event, 0) == WAIT_OBJECT_0)
133 oldStatus = TRUE;
134
135 if (signalCount <= countdown->count)
136 countdown->count -= signalCount;
137 else
138 countdown->count = 0;
139
140 if (countdown->count == 0)
141 newStatus = TRUE;
142
143 if (newStatus && (!oldStatus))
144 {
145 (void)SetEvent(countdown->event);
146 status = TRUE;
147 }
148
149 LeaveCriticalSection(&countdown->lock);
150
151 return status;
152}
153
158void CountdownEvent_Reset(wCountdownEvent* countdown, size_t count)
159{
160 WINPR_ASSERT(countdown);
161 countdown->initialCount = count;
162}
163
168wCountdownEvent* CountdownEvent_New(size_t initialCount)
169{
170 wCountdownEvent* countdown = (wCountdownEvent*)calloc(1, sizeof(wCountdownEvent));
171
172 if (!countdown)
173 return NULL;
174
175 countdown->count = initialCount;
176 countdown->initialCount = initialCount;
177
178 if (!InitializeCriticalSectionAndSpinCount(&countdown->lock, 4000))
179 goto fail;
180
181 countdown->event = CreateEvent(NULL, TRUE, FALSE, NULL);
182 if (!countdown->event)
183 goto fail;
184
185 if (countdown->count == 0)
186 {
187 if (!SetEvent(countdown->event))
188 goto fail;
189 }
190
191 return countdown;
192
193fail:
194 WINPR_PRAGMA_DIAG_PUSH
195 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
196 CountdownEvent_Free(countdown);
197 WINPR_PRAGMA_DIAG_POP
198 return NULL;
199}
200
201void CountdownEvent_Free(wCountdownEvent* countdown)
202{
203 if (!countdown)
204 return;
205
206 DeleteCriticalSection(&countdown->lock);
207 (void)CloseHandle(countdown->event);
208
209 free(countdown);
210}