19 #include <freerdp/config.h>
21 #include <winpr/assert.h>
22 #include <freerdp/log.h>
25 #define TAG SERVER_TAG("shadow.mcevent")
27 struct rdp_shadow_multiclient_event
32 wArrayList* subscribers;
41 struct rdp_shadow_multiclient_subscriber
43 rdpShadowMultiClientEvent* ref;
47 rdpShadowMultiClientEvent* shadow_multiclient_new(
void)
49 rdpShadowMultiClientEvent*
event =
50 (rdpShadowMultiClientEvent*)calloc(1,
sizeof(rdpShadowMultiClientEvent));
54 event->event = CreateEvent(NULL, TRUE, FALSE, NULL);
58 event->barrierEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
59 if (!event->barrierEvent)
62 event->doneEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
63 if (!event->doneEvent)
64 goto out_free_barrierEvent;
66 event->subscribers = ArrayList_New(TRUE);
67 if (!event->subscribers)
68 goto out_free_doneEvent;
70 if (!InitializeCriticalSectionAndSpinCount(&(event->lock), 4000))
71 goto out_free_subscribers;
76 (void)SetEvent(event->doneEvent);
80 ArrayList_Free(event->subscribers);
82 (void)CloseHandle(event->doneEvent);
83 out_free_barrierEvent:
84 (void)CloseHandle(event->barrierEvent);
86 (void)CloseHandle(event->event);
90 return (rdpShadowMultiClientEvent*)NULL;
93 void shadow_multiclient_free(rdpShadowMultiClientEvent* event)
98 DeleteCriticalSection(&(event->lock));
100 ArrayList_Free(event->subscribers);
101 (void)CloseHandle(event->doneEvent);
102 (void)CloseHandle(event->barrierEvent);
103 (void)CloseHandle(event->event);
107 static void Publish(rdpShadowMultiClientEvent* event)
109 wArrayList* subscribers = NULL;
110 struct rdp_shadow_multiclient_subscriber* subscriber = NULL;
112 subscribers =
event->subscribers;
114 WINPR_ASSERT(event->consuming == 0);
117 ArrayList_Lock(subscribers);
118 for (
size_t i = 0; i < ArrayList_Count(subscribers); i++)
120 subscriber = (
struct rdp_shadow_multiclient_subscriber*)ArrayList_GetItem(subscribers, i);
122 subscriber->pleaseHandle = TRUE;
125 ArrayList_Unlock(subscribers);
127 if (event->consuming > 0)
129 event->eventid = (
event->eventid & 0xff) + 1;
130 WLog_VRB(TAG,
"Server published event %d. %d clients.\n", event->eventid, event->consuming);
131 (void)ResetEvent(event->doneEvent);
132 (void)SetEvent(event->event);
136 static void WaitForSubscribers(rdpShadowMultiClientEvent* event)
138 if (event->consuming > 0)
141 WLog_VRB(TAG,
"Server wait event %d. %d clients.\n", event->eventid, event->consuming);
142 LeaveCriticalSection(&(event->lock));
143 (void)WaitForSingleObject(event->doneEvent, INFINITE);
144 EnterCriticalSection(&(event->lock));
145 WLog_VRB(TAG,
"Server quit event %d. %d clients.\n", event->eventid, event->consuming);
149 WINPR_ASSERT(WaitForSingleObject(event->event, 0) != WAIT_OBJECT_0);
152 void shadow_multiclient_publish(rdpShadowMultiClientEvent* event)
157 EnterCriticalSection(&(event->lock));
159 LeaveCriticalSection(&(event->lock));
161 void shadow_multiclient_wait(rdpShadowMultiClientEvent* event)
166 EnterCriticalSection(&(event->lock));
167 WaitForSubscribers(event);
168 LeaveCriticalSection(&(event->lock));
170 void shadow_multiclient_publish_and_wait(rdpShadowMultiClientEvent* event)
175 EnterCriticalSection(&(event->lock));
177 WaitForSubscribers(event);
178 LeaveCriticalSection(&(event->lock));
181 static BOOL Consume(
struct rdp_shadow_multiclient_subscriber* subscriber, BOOL wait)
183 rdpShadowMultiClientEvent*
event = subscriber->ref;
186 if (WaitForSingleObject(event->event, 0) == WAIT_OBJECT_0 && subscriber->pleaseHandle)
193 WINPR_ASSERT(event->consuming >= 0);
195 if (event->consuming == 0)
198 (void)ResetEvent(event->event);
200 if (event->waiting > 0)
203 (void)SetEvent(event->barrierEvent);
208 (void)SetEvent(event->doneEvent);
221 LeaveCriticalSection(&(event->lock));
222 (void)WaitForSingleObject(event->barrierEvent, INFINITE);
223 EnterCriticalSection(&(event->lock));
225 if (event->waiting == 0)
232 (void)ResetEvent(event->barrierEvent);
233 (void)SetEvent(event->doneEvent);
241 void* shadow_multiclient_get_subscriber(rdpShadowMultiClientEvent* event)
243 struct rdp_shadow_multiclient_subscriber* subscriber = NULL;
248 EnterCriticalSection(&(event->lock));
250 subscriber = (
struct rdp_shadow_multiclient_subscriber*)calloc(
251 1,
sizeof(
struct rdp_shadow_multiclient_subscriber));
255 subscriber->ref = event;
256 subscriber->pleaseHandle = FALSE;
258 if (!ArrayList_Append(event->subscribers, subscriber))
261 WLog_VRB(TAG,
"Get subscriber %p. Wait event %d. %d clients.\n", (
void*)subscriber,
262 event->eventid, event->consuming);
263 (void)Consume(subscriber, TRUE);
264 WLog_VRB(TAG,
"Get subscriber %p. Quit event %d. %d clients.\n", (
void*)subscriber,
265 event->eventid, event->consuming);
267 LeaveCriticalSection(&(event->lock));
274 LeaveCriticalSection(&(event->lock));
284 void shadow_multiclient_release_subscriber(
void* subscriber)
286 struct rdp_shadow_multiclient_subscriber* s = NULL;
287 rdpShadowMultiClientEvent*
event = NULL;
292 s = (
struct rdp_shadow_multiclient_subscriber*)subscriber;
295 EnterCriticalSection(&(event->lock));
297 WLog_VRB(TAG,
"Release Subscriber %p. Drop event %d. %d clients.\n", subscriber, event->eventid,
299 (void)Consume(s, FALSE);
300 WLog_VRB(TAG,
"Release Subscriber %p. Quit event %d. %d clients.\n", subscriber, event->eventid,
303 ArrayList_Remove(event->subscribers, subscriber);
305 LeaveCriticalSection(&(event->lock));
310 BOOL shadow_multiclient_consume(
void* subscriber)
312 struct rdp_shadow_multiclient_subscriber* s = NULL;
313 rdpShadowMultiClientEvent*
event = NULL;
319 s = (
struct rdp_shadow_multiclient_subscriber*)subscriber;
322 EnterCriticalSection(&(event->lock));
324 WLog_VRB(TAG,
"Subscriber %p wait event %d. %d clients.\n", subscriber, event->eventid,
326 ret = Consume(s, TRUE);
327 WLog_VRB(TAG,
"Subscriber %p quit event %d. %d clients.\n", subscriber, event->eventid,
330 LeaveCriticalSection(&(event->lock));
335 HANDLE shadow_multiclient_getevent(
void* subscriber)
340 return ((
struct rdp_shadow_multiclient_subscriber*)subscriber)->ref->event;