20#include <winpr/config.h>
24#include <winpr/collections.h>
27#define TAG WINPR_TAG("pubsub")
48wEventType* PubSub_GetEventTypes(wPubSub* pubSub,
size_t* count)
52 *count = pubSub->count;
54 return pubSub->events;
61void PubSub_Lock(wPubSub* pubSub)
64 if (pubSub->synchronized)
65 EnterCriticalSection(&pubSub->lock);
68void PubSub_Unlock(wPubSub* pubSub)
71 if (pubSub->synchronized)
72 LeaveCriticalSection(&pubSub->lock);
75wEventType* PubSub_FindEventType(wPubSub* pubSub,
const char* EventName)
80 WINPR_ASSERT(EventName);
81 for (
size_t index = 0; index < pubSub->count; index++)
83 if (strcmp(pubSub->events[index].EventName, EventName) == 0)
85 event = &(pubSub->events[index]);
93void PubSub_AddEventTypes(wPubSub* pubSub,
wEventType* events,
size_t count)
96 WINPR_ASSERT(events || (count == 0));
97 if (pubSub->synchronized)
100 const size_t required = pubSub->count + count;
101 WINPR_ASSERT((required >= pubSub->count) && (required >= count));
103 if (required >= pubSub->size)
105 size_t new_size = pubSub->size;
108 WINPR_ASSERT(new_size <= SIZE_MAX - 128ull);
110 }
while (new_size <= required);
115 pubSub->size = new_size;
116 pubSub->events = new_event;
119 CopyMemory(&pubSub->events[pubSub->count], events, count *
sizeof(
wEventType));
120 pubSub->count += count;
123 if (pubSub->synchronized)
124 PubSub_Unlock(pubSub);
127int PubSub_Subscribe(wPubSub* pubSub,
const char* EventName, ...)
131 WINPR_ASSERT(pubSub);
133 va_list ap = WINPR_C_ARRAY_INIT;
134 va_start(ap, EventName);
135 pEventHandler EventHandler = va_arg(ap, pEventHandler);
137 if (pubSub->synchronized)
140 event = PubSub_FindEventType(pubSub, EventName);
146 if (event->EventHandlerCount < MAX_EVENT_HANDLERS)
147 event->EventHandlers[
event->EventHandlerCount++] = EventHandler;
152 if (pubSub->synchronized)
153 PubSub_Unlock(pubSub);
159int PubSub_Unsubscribe(wPubSub* pubSub,
const char* EventName, ...)
163 WINPR_ASSERT(pubSub);
164 WINPR_ASSERT(EventName);
166 va_list ap = WINPR_C_ARRAY_INIT;
167 va_start(ap, EventName);
168 pEventHandler EventHandler = va_arg(ap, pEventHandler);
170 if (pubSub->synchronized)
173 event = PubSub_FindEventType(pubSub, EventName);
179 for (
size_t index = 0; index <
event->EventHandlerCount; index++)
181 if (event->EventHandlers[index] == EventHandler)
183 event->EventHandlers[index] =
nullptr;
184 event->EventHandlerCount--;
185 MoveMemory((
void*)&event->EventHandlers[index],
186 (
void*)&event->EventHandlers[index + 1],
187 (MAX_EVENT_HANDLERS - index - 1) *
sizeof(pEventHandler));
193 if (pubSub->synchronized)
194 PubSub_Unlock(pubSub);
200int PubSub_OnEvent(wPubSub* pubSub,
const char* EventName,
void* context,
const wEventArgs* e)
202 WINPR_ASSERT(pubSub);
203 WINPR_ASSERT(EventName);
208 WLog_ERR(TAG,
"pubSub(%s)=nullptr!", EventName);
212 if (pubSub->synchronized)
216 wEventType*
event = PubSub_FindEventType(pubSub, EventName);
219 for (
size_t index = 0; index <
event->EventHandlerCount; index++)
221 if (event->EventHandlers[index])
223 event->EventHandlers[index](context, e);
228 if (pubSub->synchronized)
229 PubSub_Unlock(pubSub);
238wPubSub* PubSub_New(BOOL
synchronized)
240 wPubSub* pubSub = (wPubSub*)calloc(1,
sizeof(wPubSub));
245 pubSub->synchronized =
synchronized;
247 if (pubSub->synchronized && !InitializeCriticalSectionAndSpinCount(&pubSub->lock, 4000))
259 WINPR_PRAGMA_DIAG_PUSH
260 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
262 WINPR_PRAGMA_DIAG_POP
266void PubSub_Free(wPubSub* pubSub)
270 if (pubSub->synchronized)
271 DeleteCriticalSection(&pubSub->lock);
273 free(pubSub->events);