FreeRDP
Loading...
Searching...
No Matches
PubSub.c
1
20#include <winpr/config.h>
21
22#include <winpr/crt.h>
23
24#include <winpr/collections.h>
25
31struct s_wPubSub
32{
34 BOOL synchronized;
35
36 size_t size;
37 size_t count;
38 wEventType* events;
39};
40
45wEventType* PubSub_GetEventTypes(wPubSub* pubSub, size_t* count)
46{
47 WINPR_ASSERT(pubSub);
48 if (count)
49 *count = pubSub->count;
50
51 return pubSub->events;
52}
53
58void PubSub_Lock(wPubSub* pubSub)
59{
60 WINPR_ASSERT(pubSub);
61 if (pubSub->synchronized)
62 EnterCriticalSection(&pubSub->lock);
63}
64
65void PubSub_Unlock(wPubSub* pubSub)
66{
67 WINPR_ASSERT(pubSub);
68 if (pubSub->synchronized)
69 LeaveCriticalSection(&pubSub->lock);
70}
71
72wEventType* PubSub_FindEventType(wPubSub* pubSub, const char* EventName)
73{
74 wEventType* event = NULL;
75
76 WINPR_ASSERT(pubSub);
77 WINPR_ASSERT(EventName);
78 for (size_t index = 0; index < pubSub->count; index++)
79 {
80 if (strcmp(pubSub->events[index].EventName, EventName) == 0)
81 {
82 event = &(pubSub->events[index]);
83 break;
84 }
85 }
86
87 return event;
88}
89
90void PubSub_AddEventTypes(wPubSub* pubSub, wEventType* events, size_t count)
91{
92 WINPR_ASSERT(pubSub);
93 WINPR_ASSERT(events || (count == 0));
94 if (pubSub->synchronized)
95 PubSub_Lock(pubSub);
96
97 while (pubSub->count + count >= pubSub->size)
98 {
99 size_t new_size = 0;
100 wEventType* new_event = NULL;
101
102 new_size = pubSub->size * 2;
103 new_event = (wEventType*)realloc(pubSub->events, new_size * sizeof(wEventType));
104 if (!new_event)
105 goto fail;
106 pubSub->size = new_size;
107 pubSub->events = new_event;
108 }
109
110 CopyMemory(&pubSub->events[pubSub->count], events, count * sizeof(wEventType));
111 pubSub->count += count;
112
113fail:
114 if (pubSub->synchronized)
115 PubSub_Unlock(pubSub);
116}
117
118int PubSub_Subscribe(wPubSub* pubSub, const char* EventName, ...)
119{
120 wEventType* event = NULL;
121 int status = -1;
122 WINPR_ASSERT(pubSub);
123
124 va_list ap = { 0 };
125 va_start(ap, EventName);
126 pEventHandler EventHandler = va_arg(ap, pEventHandler);
127
128 if (pubSub->synchronized)
129 PubSub_Lock(pubSub);
130
131 event = PubSub_FindEventType(pubSub, EventName);
132
133 if (event)
134 {
135 status = 0;
136
137 if (event->EventHandlerCount < MAX_EVENT_HANDLERS)
138 event->EventHandlers[event->EventHandlerCount++] = EventHandler;
139 else
140 status = -1;
141 }
142
143 if (pubSub->synchronized)
144 PubSub_Unlock(pubSub);
145
146 va_end(ap);
147 return status;
148}
149
150int PubSub_Unsubscribe(wPubSub* pubSub, const char* EventName, ...)
151{
152 wEventType* event = NULL;
153 int status = -1;
154 WINPR_ASSERT(pubSub);
155 WINPR_ASSERT(EventName);
156
157 va_list ap = { 0 };
158 va_start(ap, EventName);
159 pEventHandler EventHandler = va_arg(ap, pEventHandler);
160
161 if (pubSub->synchronized)
162 PubSub_Lock(pubSub);
163
164 event = PubSub_FindEventType(pubSub, EventName);
165
166 if (event)
167 {
168 status = 0;
169
170 for (size_t index = 0; index < event->EventHandlerCount; index++)
171 {
172 if (event->EventHandlers[index] == EventHandler)
173 {
174 event->EventHandlers[index] = NULL;
175 event->EventHandlerCount--;
176 MoveMemory((void*)&event->EventHandlers[index],
177 (void*)&event->EventHandlers[index + 1],
178 (MAX_EVENT_HANDLERS - index - 1) * sizeof(pEventHandler));
179 status = 1;
180 }
181 }
182 }
183
184 if (pubSub->synchronized)
185 PubSub_Unlock(pubSub);
186
187 va_end(ap);
188 return status;
189}
190
191int PubSub_OnEvent(wPubSub* pubSub, const char* EventName, void* context, const wEventArgs* e)
192{
193 wEventType* event = NULL;
194 int status = -1;
195
196 if (!pubSub)
197 return -1;
198 WINPR_ASSERT(e);
199
200 if (pubSub->synchronized)
201 PubSub_Lock(pubSub);
202
203 event = PubSub_FindEventType(pubSub, EventName);
204
205 if (pubSub->synchronized)
206 PubSub_Unlock(pubSub);
207
208 if (event)
209 {
210 status = 0;
211
212 for (size_t index = 0; index < event->EventHandlerCount; index++)
213 {
214 if (event->EventHandlers[index])
215 {
216 event->EventHandlers[index](context, e);
217 status++;
218 }
219 }
220 }
221
222 return status;
223}
224
229wPubSub* PubSub_New(BOOL synchronized)
230{
231 wPubSub* pubSub = (wPubSub*)calloc(1, sizeof(wPubSub));
232
233 if (!pubSub)
234 return NULL;
235
236 pubSub->synchronized = synchronized;
237
238 if (pubSub->synchronized && !InitializeCriticalSectionAndSpinCount(&pubSub->lock, 4000))
239 goto fail;
240
241 pubSub->count = 0;
242 pubSub->size = 64;
243
244 pubSub->events = (wEventType*)calloc(pubSub->size, sizeof(wEventType));
245 if (!pubSub->events)
246 goto fail;
247
248 return pubSub;
249fail:
250 WINPR_PRAGMA_DIAG_PUSH
251 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
252 PubSub_Free(pubSub);
253 WINPR_PRAGMA_DIAG_POP
254 return NULL;
255}
256
257void PubSub_Free(wPubSub* pubSub)
258{
259 if (pubSub)
260 {
261 if (pubSub->synchronized)
262 DeleteCriticalSection(&pubSub->lock);
263
264 free(pubSub->events);
265 free(pubSub);
266 }
267}