le_eventLoop.h

Go to the documentation of this file.
1 /**
2  * @page c_eventLoop Event Loop API
3  *
4  * @subpage le_eventLoop.h "API Reference"
5  *
6  * <HR>
7  *
8  * The Event Loop API supports the event-driven programming model, which is favoured in Legato
9  * (but not forced). Each thread that uses this system has a central <b>event loop</b>
10  * which calls <b>event handler</b> functions in response to <b>event reports</b>.
11  *
12  * Software components register their event handler functions with the event system (either
13  * directly through the Event Loop API or indirectly through other APIs that use the Event Loop API)
14  * so the central event loop knows the functions to call in response to defined events.
15  *
16  * Every event loop has an <b>event queue</b>, which is a queue of events waiting to be handled by
17  * that event loop.
18  *
19  * @note When the process dies, all events, event loops, queues, reports, and handlers will be
20  * automatically cleared.
21  *
22  * The following different usage patterns are supported by the Event Loop API:
23  *
24  * @ref c_event_deferredFunctionCalls <br>
25  * @ref c_event_dispatchingToOtherThreads <br>
26  * @ref c_event_publishSubscribe <br>
27  * @ref c_event_layeredPublishSubscribe <br>
28  *
29  * Other Legato C Runtime Library APIs using the event loop include:
30  *
31  * @ref c_fdMonitor <br>
32  * @ref c_timer <br>
33  * @ref c_args <br>
34  * @ref c_signals <br>
35  * @ref c_messaging <br>
36  *
37  *
38  * @section c_event_deferredFunctionCalls Deferred Function Calls
39  *
40  * A basic Event Queue usage is to queue a function for the Event Loop to call
41  * later (when that function gets to the head of the Event Queue) by calling l@c e_event_QueueFunction().
42  *
43  * This code sample has a component initialization function queueing another function
44  * to be call later, by the process's main thread when the Event Loop is running. Two
45  * parameters are needed by the deferred function. The third is just filled with NULL and ignored
46  * by the deferred function.
47  *
48  * @code
49  * static void MyDeferredFunction
50  * (
51  * void* param1Ptr,
52  * void* param2Ptr
53  * )
54  * {
55  * // Type cast the parameters to what they really are and do whatever it is that
56  * // I need to do with them.
57  * }
58  *
59  * ...
60  *
61  * COMPONENT_INIT
62  * {
63  * le_event_QueueFunction(MyDeferredFunction, firstParamPtr, secondParamPtr);
64  * }
65  * @endcode
66  *
67  * Deferred function calls are useful when implementing APIs with asynchronous
68  * result call-backs. If an error is detected before the API function returns, it can't just
69  * call the call-back directly, because it could cause re-entrancy problems in the client code
70  * or cause recursive loops. Instead of forcing the API function to return an error code
71  * in special cases (which will increase the client's code complexity and may leak API
72  * implementation details to the client), the API function can defers executing the
73  * call-back until later by queuing an error handling function onto the Event Queue.
74  *
75  * @section c_event_dispatchingToOtherThreads Dispatching Function Execution to Other Threads
76  *
77  * In multi-threaded programs, sometimes the implementor needs
78  * to ask another thread to run a function because:
79  * - The function to be executed takes a long time, but doesn't have to be done at a high priority.
80  * - A call needs to be made into a non-thread-safe API function.
81  * - A blocking function needs to be called, but the current thread can't afford to block.
82  *
83  * To assist with this, the Event Loop API provides @c le_event_QueueFunctionToThread(). It
84  * works the same as le_event_QueueFunction(), except that it queues the function onto a
85  * specific thread's Event Queue.
86  *
87  * If the other thread isn't running the Event Loop, then the queued function will
88  * never be executed.
89  *
90  * This code sample shows two arguments started by the process's main
91  * thread, and executed in the background by a low-priority thread. The result is reported back
92  * to the client through a completion callback running in the same thread that requested that the
93  * computation be performed.
94  *
95  * @code
96  * static le_mem_PoolRef_t ComputeRequestPool;
97  * static le_thread_Ref_t LowPriorityThreadRef;
98  *
99  * typedef struct
100  * {
101  * size_t arg1; // First argument
102  * size_t arg2; // Second argument
103  * ssize_t result; // The result
104  * void (*completionCallback)(ssize_t result); // The client's completion callback
105  * le_thread_Ref_t requestingThreadRef; // The client's thread.
106  * }
107  * ComputeRequest_t;
108  *
109  * // Main function of low-priority background thread.
110  * static void* LowPriorityThreadMain
111  * (
112  * void* contextPtr // not used.
113  * )
114  * {
115  * le_event_RunLoop();
116  * }
117  *
118  * COMPONENT_INIT
119  * {
120  * ComputeRequestPool = le_mem_CreatePool("Compute Request", sizeof(ComputeRequest_t));
121  *
122  * LowPriorityThreadRef = le_thread_Create("Background Computation Thread",
123  * LowPriorityThreadMain,
124  * NULL);
125  * le_thread_SetPriority(LowPriorityThreadRef, LE_THREAD_PRIORITY_IDLE);
126  * le_thread_Start(LowPriorityThreadRef);
127  * }
128  *
129  * // This function gets run by a low-priority, background thread.
130  * static void ComputeResult
131  * (
132  * void* param1Ptr, // request object pointer
133  * void* param2Ptr // not used
134  * )
135  * {
136  * ComputeRequest_t* requestPtr = param1Ptr;
137  *
138  * requestPtr->result = DoSomeReallySlowComputation(requestPtr->arg1, requestPtr->arg2);
139  *
140  * le_event_QueueFunctionToThread(requestPtr->requestingThreadRef,
141  * ProcessResult,
142  * requestPtr,
143  * NULL);
144  * }
145  *
146  * // This function gets called by a component running in the main thread.
147  * static void ComputeResultInBackground
148  * (
149  * size_t arg1,
150  * size_t arg2,
151  * void (*completionCallback)(ssize_t result)
152  * )
153  * {
154  * ComputeRequest_t* requestPtr = le_mem_ForceAlloc(ComputeRequestPool);
155  * requestPtr->arg1 = arg1;
156  * requestPtr->arg2 = arg2;
157  * requestPtr->requestingThreadRef = le_thread_GetCurrent();
158  * requestPtr->completionCallback = completionCallback;
159  * le_event_QueueFunctionToThread(LowPriorityThreadRef,
160  * ComputeResult,
161  * requestPtr,
162  * NULL);
163  * }
164  *
165  * // This function gets run by the main thread.
166  * static void ProcessResult
167  * (
168  * void* param1Ptr, // request object pointer
169  * void* param2Ptr // not used
170  * )
171  * {
172  * ComputeRequest_t* requestPtr = param1Ptr;
173  * completionCallback(requestPtr->result);
174  * le_mem_Release(requestPtr);
175  * }
176  * @endcode
177  *
178  * @section c_event_publishSubscribe Publish-Subscribe Events
179  *
180  * In the publish-subscribe pattern, someone publishes information and if anyone cares about
181  * that information, they subscribe to receive it. The publisher doesn't have to know whether
182  * anything is listening, or how many subscribers might be listening.
183  * Likewise, the subscribers don't have to know whether anything is publishing or how many
184  * publishers there might be. This decouples publishers and subscribers.
185  *
186  * Subscribers @b add handlers for events and wait for those handlers to be executed.
187  *
188  * Publishers @b report events.
189  *
190  * When an event report reaches the front of an Event Queue, the Event Loop will pop it from the
191  * queue and call any handlers that have been registered for that event.
192  *
193  * Events are identified using an <b> Event ID </b> created by calling
194  * @c le_event_CreateId() before registering an handler for that event or report.
195  * Any thread within the process with an Event ID can register a handler or report
196  * events.
197  *
198  * @note These Event IDs are only valid within the process where they were created. The
199  * Event Loop API can't be used for inter-process communication (IPC).
200  *
201  * @code
202  * le_event_Id_t eventId = le_event_CreateId("MyEvent", sizeof(MyEventReport_t));
203  * @endcode
204  *
205  * Event reports can carry a payload. The size and format of the payload depends on the type of
206  * event. For example, reports of temperature changes may need to carry the new temperature.
207  * To support this, @c le_event_CreateId() takes the payload size as a parameter.
208  *
209  * To report an event, the publisher builds their report payload in their own buffer and passes
210  * a pointer to that buffer (and its size) to @c le_event_Report():
211  *
212  * @code
213  * MyEventReport_t report;
214  * ... // Fill in the event report.
215  * le_event_Report(EventId, &report, sizeof(report));
216  * @endcode
217  *
218  * This results in the report getting queued to the Event Queues of all threads with
219  * handlers registered for that event ID.
220  *
221  * To register a handler, the subscriber calls @c le_event_AddHandler().
222  *
223  * @note It's okay to have a payload size of zero, in which case NULL can be passed into
224  * le_event_Report().
225  *
226  * @code
227  * le_event_HandlerRef_t handlerRef = le_event_AddHandler("MyHandler", eventId, MyHandlerFunc);
228  * @endcode
229  *
230  * When an event report reaches the front of a thread's Event Queue, that thread's Event Loop
231  * reads the report and then:
232  * - Calls the handler functions registered by that thread.
233  * - Points to the report payload passed to the handler as a parameter.
234  * - Reports the payload was deleted on return, so the handler
235  * function must copy any contents to keep.
236  *
237  * @code
238  * static void MyHandlerFunc
239  * (
240  * void* reportPayloadPtr
241  * )
242  * {
243  * MyEventReport_t* reportPtr = reportPayloadPtr;
244  * // Process the report.
245  * ...
246  * }
247  * @endcode
248  *
249  * Another opaque pointer, called the <b> context pointer </b> can be set for
250  * the handler using @c le_event_SetContextPtr(). When the handler function is called, it can call
251  * le_event_GetContextPtr() to fetch the context pointer.
252  *
253  * @code
254  * static void MyHandlerFunc
255  * (
256  * void* reportPayloadPtr
257  * )
258  * {
259  * MyEventReport_t* reportPtr = reportPayloadPtr;
260  * MyContext_t* contextPtr = le_event_GetContextPtr();
261  *
262  * // Process the report.
263  * ...
264  * }
265  *
266  * COMPONENT_INIT
267  * {
268  * MyEventId = le_event_CreateId("MyEvent", sizeof(MyEventReport_t));
269  *
270  * MyHandlerRef = le_event_AddHandler("MyHandler", MyEventId, MyHandlerFunc);
271  * le_event_SetContextPtr(MyHandlerRef, sizeof(float));
272  * }
273  * @endcode
274  *
275  * Finally, le_event_RemoveHandler() can be used to remove an event handler registration,
276  * if necessary.
277  *
278  * @code
279  * le_event_RemoveHandler(MyHandlerRef);
280  * @endcode
281  *
282  * If a handler is removed after the report for that event has been added to the event queue, but
283  * before the report reaches the head of the queue, then the handler will not be called.
284  *
285  * @note To prevent race conditions, it's not permitted for one thread to remove another thread's
286  * handlers.
287  *
288  * @section c_event_layeredPublishSubscribe Layered Publish-Subscribe Handlers
289  *
290  * If you need to implement an API that allows clients to register "handler"
291  * functions to be called-back after a specific event occurs, the Event Loop API
292  * provides some special help.
293  *
294  * You can have the Event Loop call your handler function (the first-layer handler),
295  * to unpack specified items from the Event Report and call the client's handler function (the
296  * second-layer handler).
297  *
298  * For example, you could create a "Temperature Sensor API" that allows its clients to register
299  * handler functions to be called to handle changes in the temperature, like this:
300  *
301  * @code
302  * // Temperature change handler functions must look like this.
303  * typedef void (*tempSensor_ChangeHandlerFunc_t)(int32_t newTemperature, void* contextPtr);
304  *
305  * // Opaque type used to refer to a registered temperature change handler.
306  * typedef struct tempSensor_ChangeHandler* tempSensor_ChangeHandlerRef_t;
307  *
308  * // Register a handler function to be called when the temperature changes.
309  * tempSensor_ChangeHandlerRef_t tempSensor_AddChangeHandler
310  * (
311  * tempSensor_ChangeHandlerFunc_t handlerFunc, // The handler function.
312  * void* contextPtr // Opaque pointer to pass to handler function.
313  * );
314  *
315  * // De-register a handler function that was previously registered using
316  * // tempSensor_AddChangeHandler().
317  * void tempSensor_RemoveChangeHandler
318  * (
319  * tempSensor_ChangeHandlerRef_t handlerRef
320  * );
321  * @endcode
322  *
323  * The implementation could look like this:
324  *
325  * @code
326  * COMPONENT_INIT
327  * {
328  * TempChangeEventId = le_event_CreateId("TempChange", sizeof(int32_t));
329  * }
330  *
331  * static void TempChangeHandler
332  * (
333  * void* reportPtr,
334  * void* secondLayerHandlerFunc
335  * )
336  * {
337  * int32_t* temperaturePtr = reportPtr;
338  * tempSensor_ChangeHandlerRef_t clientHandlerFunc = secondLayerHandlerFunc;
339  *
340  * clientHandlerFunc(*temperaturePtr, le_event_GetContextPtr());
341  * }
342  *
343  * tempSensor_ChangeHandlerRef_t tempSensor_AddChangeHandler
344  * (
345  * tempSensor_ChangeHandlerFunc_t handlerFunc,
346  * void* contextPtr
347  * )
348  * {
349  * le_event_HandlerRef_t handlerRef;
350  *
351  * handlerRef = le_event_AddLayeredHandler("TempChange",
352  * TempChangeEventId,
353  * TempChangeHandler,
354  * handlerFunc);
355  * le_event_SetContextPtr(handlerRef, contextPtr);
356  *
357  * return (tempSensor_ChangeHandlerRef_t)handlerRef;
358  * }
359  *
360  * void tempSensor_RemoveChangeHandler
361  * (
362  * tempSensor_ChangeHandlerRef_t handlerRef
363  * )
364  * {
365  * le_event_RemoveHandler((le_event_HandlerRef_t)handlerRef);
366  * }
367  * @endcode
368  *
369  *This approach gives strong type checking of both handler references and handler
370  * function pointers in code that uses this Temperature Sensor API.
371  *
372  *
373  * @section c_event_reportingRefCountedObjects Event Reports Containing Reference-Counted Objects
374  *
375  *Sometimes you need to report an event where the report payload is pointing to a
376  * reference-counted object allocated from a memory pool (see @ref c_memory).
377  * Memory leaks and/or crashes can result if its is sent through the Event Loop API
378  * without telling the Event Loop API it's pointing to a reference counted object.
379  * If there are no subscribers, the Event Loop API iscards the reference without releasing it,
380  * and the object is never be deleted. If multiple handlers are registered,
381  * the reference could be released by the handlers too many times. Also, there are
382  * other, subtle issues that are nearly impossible to solve if threads terminate while
383  * reports containing pointers to reference-counted objects are on their Event Queues.
384  *
385  * To help with this, the functions @c le_event_CreateIdWithRefCounting() and
386  * @c le_event_ReportWithRefCounting() have been provided. These allow a pointer to a
387  * reference-counted memory pool object to be sent as the payload of an Event Report.
388  *
389  * @c le_event_ReportWithRefCounting() passes ownership of one reference to the Event Loop API, and
390  * when the handler is called, it receives ownership for one reference. It then becomes
391  * the handler's responsibility to release its reference (using le_mem_Release()) when it's done.
392  *
393  *
394  * @c le_event_CreateIdWithRefCounting() is used the same way as le_event_CreateId(), except that
395  * it doesn't require a payload size as the payload is always
396  * known from the pointer to a reference-counted memory pool object. Only Event IDs
397  * created using le_event_CreateIdWithRefCounting() can be used with
398  * le_event_ReportWithRefCounting().
399  *
400  * @code
401  * static le_event_Id_t EventId;
402  * le_mem_PoolRef_t MyObjectPoolRef;
403  *
404  * static void MyHandler
405  * (
406  * void* reportPtr // Pointer to my reference-counted object.
407  * )
408  * {
409  * MyObj_t* objPtr = reportPtr;
410  *
411  * // Do something with the object.
412  * ...
413  *
414  * // Okay, I'm done with the object now.
415  * le_mem_Release(objPtr);
416  * }
417  *
418  * COMPONENT_INIT
419  * {
420  * EventId = le_event_CreateIdWithRefCounting("SomethingHappened");
421  * le_event_AddHandler("SomethingHandler", EventId, MyHandler);
422  * MyObjectPoolRef = le_mem_CreatePool("MyObjects", sizeof(MyObj_t));
423  * }
424  *
425  * static void ReportSomethingDetected
426  * (
427  * ...
428  * )
429  * {
430  * MyObj_t* objPtr = le_mem_ForceAlloc(MyObjectPool);
431  *
432  * // Fill in the object.
433  * ...
434  *
435  * le_event_ReportWithRefCounting(EventId, objPtr);
436  * }
437  *
438  * @endcode
439  *
440  * @section c_event_miscThreadingTopics Miscellaneous Multithreading Topics
441  *
442  * All functions in this API are thread safe.
443  *
444  * Each thread can have only one Event Loop.
445  * The main thread in every Legato process will always run an Event Loop after it's run
446  * the component initialization functions. As soon as all component initialization functions
447  * have returned, the main thread will start processing its event queue.
448  *
449  * When a function is called to "Add" an event handler, that handler is associated with the
450  * calling thread's Event Loop. If the calling thread doesn't run its Event Loop, the event
451  * reports will pile up in the queue, never getting serviced and never releasing their memory.
452  * This will appear in the logs as event queue growth warnings.
453  *
454  * If a client starts its own thread (e.g., by calling le_thread_Create() ), then
455  * that thread will @b not automatically run an Event Loop. To make it run an Event Loop, it must
456  * call @c le_event_RunLoop() (which will never return).
457  *
458  * If a thread running an Event Loop terminates, the Legato framework automatically
459  * deregisters any handlers and deletes the thread's Event Loop, its Event
460  * Queue, and any event reports still in that Event Queue.
461  *
462  * @section c_event_integratingLegacyPosix Integrating with Legacy POSIX Code
463  *
464  * Many legacy programs written on top of POSIX APIs will have previously built their own event loop
465  * using poll(), select(), or some other blocking functions. It may be difficult to refactor this type of
466  * event loop to use the Legato event loop instead.
467  *
468  * Two functions are provided to assist integrating legacy code with the Legato
469  * Event Loop:
470  * - @c le_event_GetFd() - Fetches a file descriptor that can be monitored using some variant of
471  * poll() or select() (including epoll). It will appear readable when the
472  * Event Loop needs servicing.
473  * - @c le_event_ServiceLoop() - Services the event loop. This should be called if the file
474  * descriptor returned by le_event_GetFd() appears readable to poll() or
475  * select().
476  *
477  * In an attempt to avoid starving the caller when there are a lot of things that need servicing
478  * on the Event Loop, @c le_event_ServiceLoop() will only perform one servicing step (i.e., call one
479  * event handler function) before returning, regardless of how much work there is to do. It's
480  * the caller's responsibility to check the return code from le_event_ServiceLoop() and keep
481  * calling until it indicates that there is no more work to be done.
482  *
483  * @section c_event_troubleshooting Troubleshooting
484  *
485  * A logging keyword can be enabled to view a given thread's event handling activity. The keyword name
486  * depends on the thread and process name where the thread is located.
487  * For example, the keyword "P/T/events" controls logging for a thread named "T" running inside
488  * a process named "P".
489  *
490  * @todo Add a reference to the Process Inspector and its capabilities for inspecting Event Queues,
491  * Event Loops, Handlers and Event Report statistics.
492 
493  * <HR>
494  *
495  * Copyright (C) Sierra Wireless Inc.
496  */
497 
498 //--------------------------------------------------------------------------------------------------
499 /** @file le_eventLoop.h
500  *
501  * Legato @ref c_eventLoop include file.
502  *
503  * Copyright (C) Sierra Wireless Inc.
504  */
505 
506 #ifndef LEGATO_EVENTLOOP_INCLUDE_GUARD
507 #define LEGATO_EVENTLOOP_INCLUDE_GUARD
508 
509 
510 //--------------------------------------------------------------------------------------------------
511 /**
512  * Event ID.
513  *
514  * An Event ID ties event reports to event handlers. See @ref c_event_publishSubscribe for
515  * more details.
516  */
517 //--------------------------------------------------------------------------------------------------
518 typedef struct le_event_Id* le_event_Id_t;
519 
520 
521 //--------------------------------------------------------------------------------------------------
522 /**
523  * Initialization event handler function declaration macro.
524  *
525  * Use this macro instead of a normal function prototype to create an Initialization Event Handler
526  * function. E.g.,
527  *
528  * @code
529  * COMPONENT_INIT
530  * {
531  * // Do my initialization here...
532  * }
533  * @endcode
534  *
535  * @return Nothing.
536  */
537 //--------------------------------------------------------------------------------------------------
538 
539 #ifdef __cplusplus
540  #define LE_CI_LINKAGE extern "C"
541 #else
542  #define LE_CI_LINKAGE
543 #endif
544 
545 // This macro is set by the build system. However, if it hasn't been set, use a sensible default.
546 #ifndef LE_COMPONENT_NAME
547 # define LE_COMPONENT_NAME le
548 #endif
549 
550 /// Construct prototype of component init function
551 #define COMPONENT_INIT_PROTOTYPE(name) LE_CI_LINKAGE LE_SHARED void name \
552  ( \
553  __attribute__((unused)) void *param1Ptr, \
554  __attribute__((unused)) void *param2Ptr \
555  )
556 
557 /// Compose component initialization function name
558 #define COMPONENT_INIT_NAME CAT(CAT(_, LE_COMPONENT_NAME), _COMPONENT_INIT)
559 
560 /// Compose component initialization function prototype
561 #define COMPONENT_INIT COMPONENT_INIT_PROTOTYPE(COMPONENT_INIT_NAME)
562 
563 /// Compose one-time component initialization function name
564 #define COMPONENT_INIT_ONCE_NAME CAT(COMPONENT_INIT_NAME, _ONCE)
565 
566 /// Compose one-time component initialization function prototype
567 #define COMPONENT_INIT_ONCE COMPONENT_INIT_PROTOTYPE(COMPONENT_INIT_ONCE_NAME)
568 
569 /// Deprecated name for @ref COMPONENT_INIT.
570 #define LE_EVENT_INIT_HANDLER COMPONENT_INIT
571 
572 
573 //--------------------------------------------------------------------------------------------------
574 /**
575  * Prototype for publish-subscribe event handler functions look like this:
576  *
577  * @param reportPtr [in] Pointer to the event report payload.
578  *
579  * @warning The reportPtr is only valid until the handler function returns.
580  */
581 //--------------------------------------------------------------------------------------------------
582 typedef void (*le_event_HandlerFunc_t)
583 (
584  void* reportPtr
585 );
586 
587 
588 //--------------------------------------------------------------------------------------------------
589 /**
590  * Prototype for the first layer of a layered publish-subscribe event handler function
591  * look like this:
592  *
593  * @param reportPtr [in] Pointer to the event report payload.
594  *
595  * @param secondLayerFunc [in] Address of the second layer handler function.
596  *
597  * @warning The reportPtr is only valid until the handler function returns.
598  */
599 //--------------------------------------------------------------------------------------------------
600 typedef void (*le_event_LayeredHandlerFunc_t)
601 (
602  void* reportPtr,
603  void* secondLayerFunc
604 );
605 
606 
607 //--------------------------------------------------------------------------------------------------
608 /**
609  * Prototype for deferred functions look like this:
610  * @param param1Ptr [in] Value passed in as param1Ptr to le_event_QueueFunction().
611  * @param param2Ptr [in] Value passed in as param2Ptr to le_event_QueueFunction().
612  *
613  * See @ref c_event_deferredFunctionCalls for more information.
614  */
615 //--------------------------------------------------------------------------------------------------
616 typedef void (*le_event_DeferredFunc_t)
617 (
618  void* param1Ptr,
619  void* param2Ptr
620 );
621 
622 
623 //--------------------------------------------------------------------------------------------------
624 /**
625  * Handler reference.
626  *
627  *Used to refer to handlers that have been added for events. Only needed if
628  * you want to set the handler's context pointer or need to remove the handler later.
629  */
630 //--------------------------------------------------------------------------------------------------
631 typedef struct le_event_Handler* le_event_HandlerRef_t;
632 
633 
634 #if LE_CONFIG_EVENT_NAMES_ENABLED
635 //--------------------------------------------------------------------------------------------------
636 /**
637  * Create a new event ID.
638  *
639  * @param[in] name Name of the event ID. (Named for diagnostic purposes.)
640  * @param[in] payloadSize Data payload size (in bytes) of the event reports (can be 0).
641  *
642  * @return Event ID.
643  *
644  * @note Doesn't return on failure, there's no need to check the return value for errors.
645  */
646 //--------------------------------------------------------------------------------------------------
648 (
649  const char *name,
650  size_t payloadSize
651 );
652 #else /* if not LE_CONFIG_EVENT_NAMES_ENABLED */
653 /// @cond HIDDEN_IN_USER_DOCS
654 //--------------------------------------------------------------------------------------------------
655 /**
656  * Internal function used to implement le_event_CreateId().
657  */
658 //--------------------------------------------------------------------------------------------------
659 le_event_Id_t _le_event_CreateId(size_t payloadSize);
660 /// @endcond
661 //--------------------------------------------------------------------------------------------------
662 /**
663  * Create a new event ID.
664  *
665  * @param[in] name Name of the event ID. (Named for diagnostic purposes.)
666  * @param[in] payloadSize Data payload size (in bytes) of the event reports (can be 0).
667  *
668  * @return Event ID.
669  *
670  * @note Doesn't return on failure, there's no need to check the return value for errors.
671  */
672 //--------------------------------------------------------------------------------------------------
674 (
675  const char *name,
676  size_t payloadSize
677 )
678 {
679  LE_UNUSED(name);
680  return _le_event_CreateId(payloadSize);
681 }
682 #endif /* end LE_CONFIG_EVENT_NAMES_ENABLED */
683 
684 
685 #if LE_CONFIG_EVENT_NAMES_ENABLED
686 //--------------------------------------------------------------------------------------------------
687 /**
688  * Create a new event ID to report events where the payload is a pointer to
689  * a reference-counted memory pool object allocated using the @ref c_memory.
690  *
691  * @param[in] name Name of the event ID. (Named for diagnostic purposes.)
692  *
693  * @return Event ID.
694  *
695  * @note Doesn't return on failure, there's no need to check the return value for errors.
696  */
697 //--------------------------------------------------------------------------------------------------
699 (
700  const char *name
701 );
702 #else /* if not LE_CONFIG_EVENT_NAMES_ENABLED */
703 /// @cond HIDDEN_IN_USER_DOCS
704 //--------------------------------------------------------------------------------------------------
705 /**
706  * Internal function used to implement le_event_CreateIdWithRefCounting().
707  */
708 //--------------------------------------------------------------------------------------------------
709 le_event_Id_t _le_event_CreateIdWithRefCounting(void);
710 /// @endcond
711 //--------------------------------------------------------------------------------------------------
712 /**
713  * Create a new event ID to report events where the payload is a pointer to
714  * a reference-counted memory pool object allocated using the @ref c_memory.
715  *
716  * @param[in] name Name of the event ID. (Named for diagnostic purposes.)
717  *
718  * @return Event ID.
719  *
720  * @note Doesn't return on failure, there's no need to check the return value for errors.
721  */
722 //--------------------------------------------------------------------------------------------------
724 (
725  const char *name
726 )
727 {
728  LE_UNUSED(name);
729  return _le_event_CreateIdWithRefCounting();
730 }
731 #endif /* end LE_CONFIG_EVENT_NAMES_ENABLED */
732 
733 
734 #if LE_CONFIG_EVENT_NAMES_ENABLED
735 //--------------------------------------------------------------------------------------------------
736 /**
737  * Adds a handler function for a publish-subscribe event ID.
738  *
739  * Tells the calling thread event loop to call a specified handler function when a defined event
740  * reaches the front of the event queue.
741  *
742  * @param[in] name Handler name.
743  * @param[in] eventId Event ID.
744  * @param[in] handlerFunc Handler function.
745  *
746  * @return
747  * Handler reference, only needed to remove the handler (using
748  * le_event_RemoveHandler() ). Can be ignored if the handler will never be removed.
749  *
750  * @note Doesn't return on failure, there's no need to check the return value for errors.
751  */
752 //--------------------------------------------------------------------------------------------------
754 (
755  const char *name,
756  le_event_Id_t eventId,
757  le_event_HandlerFunc_t handlerFunc
758 );
759 #else /* if not LE_CONFIG_EVENT_NAMES_ENABLED */
760 /// @cond HIDDEN_IN_USER_DOCS
761 //--------------------------------------------------------------------------------------------------
762 /**
763  * Internal function used to implement le_event_AddHandler().
764  */
765 //--------------------------------------------------------------------------------------------------
766 le_event_HandlerRef_t _le_event_AddHandler(le_event_Id_t eventId, le_event_HandlerFunc_t handlerFunc);
767 /// @endcond
768 //--------------------------------------------------------------------------------------------------
769 /**
770  * Adds a handler function for a publish-subscribe event ID.
771  *
772  * Tells the calling thread event loop to call a specified handler function when a defined event
773  * reaches the front of the event queue.
774  *
775  * @param[in] name Handler name.
776  * @param[in] eventId Event ID.
777  * @param[in] handlerFunc Handler function.
778  *
779  * @return
780  * Handler reference, only needed to remove the handler (using
781  * le_event_RemoveHandler() ). Can be ignored if the handler will never be removed.
782  *
783  * @note Doesn't return on failure, there's no need to check the return value for errors.
784  */
785 //--------------------------------------------------------------------------------------------------
787 (
788  const char *name,
789  le_event_Id_t eventId,
790  le_event_HandlerFunc_t handlerFunc
791 )
792 {
793  LE_UNUSED(name);
794  return _le_event_AddHandler(eventId, handlerFunc);
795 }
796 #endif /* end LE_CONFIG_EVENT_NAMES_ENABLED */
797 
798 
799 #if LE_CONFIG_EVENT_NAMES_ENABLED
800 //--------------------------------------------------------------------------------------------------
801 /**
802  * Adds a layered handler function for a publish-subscribe event ID.
803  *
804  * Tells the calling thread event loop to call a specified handler function when a defined event
805  * reaches the front of the event queue. Passes the required handler functions when called.
806  *
807  * This is intended for use in implementing @ref c_event_layeredPublishSubscribe.
808  *
809  * @param[in] name Handler name.
810  * @param[in] name Event ID.
811  * @param[in] name Pointer to first-layer handler func.
812  * @param[in] name Pointer to second-layer handler func.
813  *
814  * @return
815  * Handler reference, only needed for later removal of the handler (using
816  * le_event_RemoveHandler() ). Can be ignored if the handler will never be removed.
817  *
818  * @note Doesn't return on failure, there's no need to check the return value for errors.
819  */
820 //--------------------------------------------------------------------------------------------------
822 (
823  const char *name,
824  le_event_Id_t eventId,
825  le_event_LayeredHandlerFunc_t firstLayerFunc,
826  void* secondLayerFunc
827 );
828 #else /* if not LE_CONFIG_EVENT_NAMES_ENABLED */
829 /// @cond HIDDEN_IN_USER_DOCS
830 //--------------------------------------------------------------------------------------------------
831 /**
832  * Internal function used to implement le_event_AddLayeredHandler().
833  */
834 //--------------------------------------------------------------------------------------------------
835 le_event_HandlerRef_t _le_event_AddLayeredHandler(le_event_Id_t eventId,
836  le_event_LayeredHandlerFunc_t firstLayerFunc,
837  void* secondLayerFunc);
838 /// @endcond
839 //--------------------------------------------------------------------------------------------------
840 /**
841  * Adds a layered handler function for a publish-subscribe event ID.
842  *
843  * Tells the calling thread event loop to call a specified handler function when a defined event
844  * reaches the front of the event queue. Passes the required handler functions when called.
845  *
846  * This is intended for use in implementing @ref c_event_layeredPublishSubscribe.
847  *
848  * @param[in] name Handler name.
849  * @param[in] name Event ID.
850  * @param[in] name Pointer to first-layer handler func.
851  * @param[in] name Pointer to second-layer handler func.
852  *
853  * @return
854  * Handler reference, only needed for later removal of the handler (using
855  * le_event_RemoveHandler() ). Can be ignored if the handler will never be removed.
856  *
857  * @note Doesn't return on failure, there's no need to check the return value for errors.
858  */
859 //--------------------------------------------------------------------------------------------------
861 (
862  const char *name,
863  le_event_Id_t eventId,
864  le_event_LayeredHandlerFunc_t firstLayerFunc,
865  void* secondLayerFunc
866 )
867 {
868  LE_UNUSED(name);
869  return _le_event_AddLayeredHandler(eventId, firstLayerFunc, secondLayerFunc);
870 }
871 #endif /* end LE_CONFIG_EVENT_NAMES_ENABLED */
872 
873 
874 //--------------------------------------------------------------------------------------------------
875 /**
876  * Remove Handler
877  *
878  * Removes a previously added event handler function.
879  */
880 //--------------------------------------------------------------------------------------------------
882 (
883  le_event_HandlerRef_t handlerRef ///< [in] Handler reference.
884 );
885 
886 
887 //--------------------------------------------------------------------------------------------------
888 /**
889  * Report an Event
890  *
891  * Queues an Event Report to any and all event loops that have handlers for that event.
892  *
893  * @note Copies the event report payload, so it is safe to release or reuse the buffer that
894  * payloadPtr points to as soon as le_event_Report() returns.
895  */
896 //--------------------------------------------------------------------------------------------------
897 void le_event_Report
898 (
899  le_event_Id_t eventId, ///< [in] Event ID created using le_event_CreateId().
900  void* payloadPtr, ///< [in] Pointer to the payload bytes to be copied into the report.
901  size_t payloadSize ///< [in] Number of bytes of payload to copy into the report.
902 );
903 
904 
905 //--------------------------------------------------------------------------------------------------
906 /**
907  * Sends an Event Report with a pointer to a reference-counted object as its payload.
908  * The pointer must have been obtained from a memory pool using the @ref c_memory.
909  *
910  * Calling this function passes ownership of the reference to the Event Loop API.
911  * The Event Loop API will ensure that the reference is properly counted while it passes
912  * through the event report dispatching system. Each handler will receive one counted reference
913  * to the object, so the handler is responsible for releasing the object when it is finished with
914  * it.
915  */
916 //--------------------------------------------------------------------------------------------------
918 (
919  le_event_Id_t eventId, ///< [in] Event ID created using le_event_CreateIdWithRefCounting().
920  void* objectPtr ///< [in] Pointer to an object allocated from a memory pool
921  /// (using the @ref c_memory).
922 );
923 
924 
925 //--------------------------------------------------------------------------------------------------
926 /**
927  * Sets the context pointer for a given event handler.
928  *
929  * This can later be retrieved using le_event_GetContextPtr() from within the handler function
930  * when it is called.
931  */
932 //--------------------------------------------------------------------------------------------------
934 (
935  le_event_HandlerRef_t handlerRef, ///< [in] Handler where context pointer is to be set.
936  void* contextPtr ///< [in] Context pointer value.
937 );
938 
939 
940 //--------------------------------------------------------------------------------------------------
941 /**
942  * Fetches the context pointer for the currently running event handler.
943  *
944  * Can only be called from within an event handler function.
945  *
946  * @return
947  * Context pointer that was set using le_event_SetContextPtr(), or NULL if
948  * le_event_SetContextPtr() was not called.
949  */
950 //--------------------------------------------------------------------------------------------------
952 (
953  void
954 );
955 
956 
957 //--------------------------------------------------------------------------------------------------
958 /**
959  * Queue a function onto the calling thread's Event Queue. When it reaches the head of the
960  * Event Queue, it will be called by the calling thread's Event Loop.
961  */
962 //--------------------------------------------------------------------------------------------------
964 (
965  le_event_DeferredFunc_t func, ///< [in] Function to be called later.
966  void* param1Ptr, ///< [in] Value to be passed to the function when called.
967  void* param2Ptr ///< [in] Value to be passed to the function when called.
968 );
969 
970 
971 //--------------------------------------------------------------------------------------------------
972 /**
973  * Queue a function onto a specific thread's Event Queue. When it reaches the head of that
974  * Event Queue, it will be called by that thread's Event Loop.
975  */
976 //--------------------------------------------------------------------------------------------------
978 (
979  le_thread_Ref_t thread, ///< [in] Thread to queue the function to.
980  le_event_DeferredFunc_t func, ///< [in] The function.
981  void* param1Ptr, ///< [in] Value to be passed to the function when called.
982  void* param2Ptr ///< [in] Value to be passed to the function when called.
983 );
984 
985 
986 //--------------------------------------------------------------------------------------------------
987 /**
988  * Runs the event loop for the calling thread.
989  *
990  * This starts processing events by the calling thread.
991  *
992  * Can only be called once for each thread, and must never be called in
993  * the process's main thread.
994  *
995  * @note
996  * Function never returns.
997  */
998 //--------------------------------------------------------------------------------------------------
999 void le_event_RunLoop
1000 (
1001  void
1002 )
1003 __attribute__ ((noreturn));
1004 
1005 
1006 //--------------------------------------------------------------------------------------------------
1007 /**
1008  * Fetches a file descriptor that will appear readable to poll(), select(), epoll_wait(), etc.
1009  * when the calling thread's Event Loop needs servicing (via a call to le_event_ServiceLoop()).
1010  *
1011  * @warning Only intended for use when integrating with legacy POSIX-based software
1012  * that cannot be easily refactored to use the Legato Event Loop. The preferred approach is
1013  * to call le_event_RunLoop().
1014  *
1015  * @return The file descriptor.
1016  */
1017 //--------------------------------------------------------------------------------------------------
1019 (
1020  void
1021 );
1022 
1023 
1024 //--------------------------------------------------------------------------------------------------
1025 /**
1026  * Services the calling thread's Event Loop.
1027  *
1028  * @warning Only intended for use when integrating with legacy POSIX-based software
1029  * that can't be easily refactored to use the Legato Event Loop. The preferred approach is
1030  * to call le_event_RunLoop().
1031  *
1032  * See also: le_event_GetFd().
1033  *
1034  * @return
1035  * - LE_OK if there is more to be done. DO NOT GO BACK TO SLEEP without calling
1036  * le_event_ServiceLoop() again.
1037  * - LE_WOULD_BLOCK if there is nothing left to do for now and it is safe to go back to sleep.
1038  */
1039 //--------------------------------------------------------------------------------------------------
1041 (
1042  void
1043 );
1044 
1045 
1046 #endif // LEGATO_EVENTLOOP_INCLUDE_GUARD
le_event_Id_t le_event_CreateIdWithRefCounting(const char *name)
void(* le_event_LayeredHandlerFunc_t)(void *reportPtr, void *secondLayerFunc)
Definition: le_eventLoop.h:601
le_result_t
Definition: le_basics.h:35
#define LE_UNUSED(v)
Definition: le_basics.h:355
LE_FULL_API int le_event_GetFd(void)
struct le_event_Handler * le_event_HandlerRef_t
Definition: le_eventLoop.h:631
struct le_event_Id * le_event_Id_t
Definition: le_eventLoop.h:518
void le_event_QueueFunctionToThread(le_thread_Ref_t thread, le_event_DeferredFunc_t func, void *param1Ptr, void *param2Ptr)
void le_event_Report(le_event_Id_t eventId, void *payloadPtr, size_t payloadSize)
void le_event_RunLoop(void)
void * le_event_GetContextPtr(void)
void(* le_event_DeferredFunc_t)(void *param1Ptr, void *param2Ptr)
Definition: le_eventLoop.h:617
le_event_Id_t le_event_CreateId(const char *name, size_t payloadSize)
#define LE_FULL_API
Definition: le_apiFeatures.h:40
void le_event_SetContextPtr(le_event_HandlerRef_t handlerRef, void *contextPtr)
void le_event_ReportWithRefCounting(le_event_Id_t eventId, void *objectPtr)
void(* le_event_HandlerFunc_t)(void *reportPtr)
Definition: le_eventLoop.h:583
le_event_HandlerRef_t le_event_AddHandler(const char *name, le_event_Id_t eventId, le_event_HandlerFunc_t handlerFunc)
void le_event_RemoveHandler(le_event_HandlerRef_t handlerRef)
le_event_HandlerRef_t le_event_AddLayeredHandler(const char *name, le_event_Id_t eventId, le_event_LayeredHandlerFunc_t firstLayerFunc, void *secondLayerFunc)
LE_FULL_API le_result_t le_event_ServiceLoop(void)
#define LE_DECLARE_INLINE
Definition: le_basics.h:306
void le_event_QueueFunction(le_event_DeferredFunc_t func, void *param1Ptr, void *param2Ptr)