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 #include "le_thread.h"
510 
511 
512 //--------------------------------------------------------------------------------------------------
513 /**
514  * Event ID.
515  *
516  * An Event ID ties event reports to event handlers. See @ref c_event_publishSubscribe for
517  * more details.
518  */
519 //--------------------------------------------------------------------------------------------------
520 typedef struct le_event_Id* le_event_Id_t;
521 
522 
523 //--------------------------------------------------------------------------------------------------
524 /**
525  * Initialization event handler function declaration macro.
526  *
527  * Use this macro instead of a normal function prototype to create an Initialization Event Handler
528  * function. E.g.,
529  *
530  * @code
531  * COMPONENT_INIT
532  * {
533  * // Do my initialization here...
534  * }
535  * @endcode
536  *
537  * @return Nothing.
538  */
539 //--------------------------------------------------------------------------------------------------
540 
541 #ifdef __cplusplus
542  #define LE_CI_LINKAGE extern "C"
543 #else
544  #define LE_CI_LINKAGE
545 #endif
546 
547 // This macro is set by the build system. However, if it hasn't been set, use a sensible default.
548 #ifndef LE_COMPONENT_NAME
549 # define LE_COMPONENT_NAME le
550 #endif
551 
552 /// Construct prototype of component init function
553 #define COMPONENT_INIT_PROTOTYPE(name) LE_CI_LINKAGE LE_SHARED void name \
554  ( \
555  __attribute__((unused)) void *param1Ptr, \
556  __attribute__((unused)) void *param2Ptr \
557  )
558 
559 /// Compose component initialization function name
560 #define COMPONENT_INIT_NAME CAT(CAT(_, LE_COMPONENT_NAME), _COMPONENT_INIT)
561 
562 /// Compose component initialization function prototype
563 #define COMPONENT_INIT COMPONENT_INIT_PROTOTYPE(COMPONENT_INIT_NAME)
564 
565 /// Compose one-time component initialization function name
566 #define COMPONENT_INIT_ONCE_NAME CAT(COMPONENT_INIT_NAME, _ONCE)
567 
568 /// Compose one-time component initialization function prototype
569 #define COMPONENT_INIT_ONCE COMPONENT_INIT_PROTOTYPE(COMPONENT_INIT_ONCE_NAME)
570 
571 /// Deprecated name for @ref COMPONENT_INIT.
572 #define LE_EVENT_INIT_HANDLER COMPONENT_INIT
573 
574 
575 //--------------------------------------------------------------------------------------------------
576 /**
577  * Prototype for publish-subscribe event handler functions look like this:
578  *
579  * @param reportPtr [in] Pointer to the event report payload.
580  *
581  * @warning The reportPtr is only valid until the handler function returns.
582  */
583 //--------------------------------------------------------------------------------------------------
584 typedef void (*le_event_HandlerFunc_t)
585 (
586  void* reportPtr
587 );
588 
589 
590 //--------------------------------------------------------------------------------------------------
591 /**
592  * Prototype for the first layer of a layered publish-subscribe event handler function
593  * look like this:
594  *
595  * @param reportPtr [in] Pointer to the event report payload.
596  *
597  * @param secondLayerFunc [in] Address of the second layer handler function.
598  *
599  * @warning The reportPtr is only valid until the handler function returns.
600  */
601 //--------------------------------------------------------------------------------------------------
602 typedef void (*le_event_LayeredHandlerFunc_t)
603 (
604  void* reportPtr,
605  void* secondLayerFunc
606 );
607 
608 
609 //--------------------------------------------------------------------------------------------------
610 /**
611  * Prototype for deferred functions look like this:
612  * @param param1Ptr [in] Value passed in as param1Ptr to le_event_QueueFunction().
613  * @param param2Ptr [in] Value passed in as param2Ptr to le_event_QueueFunction().
614  *
615  * See @ref c_event_deferredFunctionCalls for more information.
616  */
617 //--------------------------------------------------------------------------------------------------
618 typedef void (*le_event_DeferredFunc_t)
619 (
620  void* param1Ptr,
621  void* param2Ptr
622 );
623 
624 
625 //--------------------------------------------------------------------------------------------------
626 /**
627  * Handler reference.
628  *
629  *Used to refer to handlers that have been added for events. Only needed if
630  * you want to set the handler's context pointer or need to remove the handler later.
631  */
632 //--------------------------------------------------------------------------------------------------
633 typedef struct le_event_Handler* le_event_HandlerRef_t;
634 
635 
636 #if LE_CONFIG_EVENT_NAMES_ENABLED
637 //--------------------------------------------------------------------------------------------------
638 /**
639  * Create a new event ID.
640  *
641  * @param[in] name Name of the event ID. (Named for diagnostic purposes.)
642  * @param[in] payloadSize Data payload size (in bytes) of the event reports (can be 0).
643  *
644  * @return Event ID.
645  *
646  * @note Doesn't return on failure, there's no need to check the return value for errors.
647  */
648 //--------------------------------------------------------------------------------------------------
650 (
651  const char *name,
652  size_t payloadSize
653 );
654 #else /* if not LE_CONFIG_EVENT_NAMES_ENABLED */
655 /// @cond HIDDEN_IN_USER_DOCS
656 //--------------------------------------------------------------------------------------------------
657 /**
658  * Internal function used to implement le_event_CreateId().
659  */
660 //--------------------------------------------------------------------------------------------------
661 le_event_Id_t _le_event_CreateId(size_t payloadSize);
662 /// @endcond
663 //--------------------------------------------------------------------------------------------------
664 /**
665  * Create a new event ID.
666  *
667  * @param[in] name Name of the event ID. (Named for diagnostic purposes.)
668  * @param[in] payloadSize Data payload size (in bytes) of the event reports (can be 0).
669  *
670  * @return Event ID.
671  *
672  * @note Doesn't return on failure, there's no need to check the return value for errors.
673  */
674 //--------------------------------------------------------------------------------------------------
676 (
677  const char *name,
678  size_t payloadSize
679 )
680 {
681  LE_UNUSED(name);
682  return _le_event_CreateId(payloadSize);
683 }
684 #endif /* end LE_CONFIG_EVENT_NAMES_ENABLED */
685 
686 
687 #if LE_CONFIG_EVENT_NAMES_ENABLED
688 //--------------------------------------------------------------------------------------------------
689 /**
690  * Create a new event ID to report events where the payload is a pointer to
691  * a reference-counted memory pool object allocated using the @ref c_memory.
692  *
693  * @param[in] name Name of the event ID. (Named for diagnostic purposes.)
694  *
695  * @return Event ID.
696  *
697  * @note Doesn't return on failure, there's no need to check the return value for errors.
698  */
699 //--------------------------------------------------------------------------------------------------
701 (
702  const char *name
703 );
704 #else /* if not LE_CONFIG_EVENT_NAMES_ENABLED */
705 /// @cond HIDDEN_IN_USER_DOCS
706 //--------------------------------------------------------------------------------------------------
707 /**
708  * Internal function used to implement le_event_CreateIdWithRefCounting().
709  */
710 //--------------------------------------------------------------------------------------------------
711 le_event_Id_t _le_event_CreateIdWithRefCounting(void);
712 /// @endcond
713 //--------------------------------------------------------------------------------------------------
714 /**
715  * Create a new event ID to report events where the payload is a pointer to
716  * a reference-counted memory pool object allocated using the @ref c_memory.
717  *
718  * @param[in] name Name of the event ID. (Named for diagnostic purposes.)
719  *
720  * @return Event ID.
721  *
722  * @note Doesn't return on failure, there's no need to check the return value for errors.
723  */
724 //--------------------------------------------------------------------------------------------------
726 (
727  const char *name
728 )
729 {
730  LE_UNUSED(name);
731  return _le_event_CreateIdWithRefCounting();
732 }
733 #endif /* end LE_CONFIG_EVENT_NAMES_ENABLED */
734 
735 
736 #if LE_CONFIG_EVENT_NAMES_ENABLED
737 //--------------------------------------------------------------------------------------------------
738 /**
739  * Adds a handler function for a publish-subscribe event ID.
740  *
741  * Tells the calling thread event loop to call a specified handler function when a defined event
742  * reaches the front of the event queue.
743  *
744  * @param[in] name Handler name.
745  * @param[in] eventId Event ID.
746  * @param[in] handlerFunc Handler function.
747  *
748  * @return
749  * Handler reference, only needed to remove the handler (using
750  * le_event_RemoveHandler() ). Can be ignored if the handler will never be removed.
751  *
752  * @note Doesn't return on failure, there's no need to check the return value for errors.
753  */
754 //--------------------------------------------------------------------------------------------------
756 (
757  const char *name,
758  le_event_Id_t eventId,
759  le_event_HandlerFunc_t handlerFunc
760 );
761 #else /* if not LE_CONFIG_EVENT_NAMES_ENABLED */
762 /// @cond HIDDEN_IN_USER_DOCS
763 //--------------------------------------------------------------------------------------------------
764 /**
765  * Internal function used to implement le_event_AddHandler().
766  */
767 //--------------------------------------------------------------------------------------------------
768 le_event_HandlerRef_t _le_event_AddHandler(le_event_Id_t eventId, le_event_HandlerFunc_t handlerFunc);
769 /// @endcond
770 //--------------------------------------------------------------------------------------------------
771 /**
772  * Adds a handler function for a publish-subscribe event ID.
773  *
774  * Tells the calling thread event loop to call a specified handler function when a defined event
775  * reaches the front of the event queue.
776  *
777  * @param[in] name Handler name.
778  * @param[in] eventId Event ID.
779  * @param[in] handlerFunc Handler function.
780  *
781  * @return
782  * Handler reference, only needed to remove the handler (using
783  * le_event_RemoveHandler() ). Can be ignored if the handler will never be removed.
784  *
785  * @note Doesn't return on failure, there's no need to check the return value for errors.
786  */
787 //--------------------------------------------------------------------------------------------------
789 (
790  const char *name,
791  le_event_Id_t eventId,
792  le_event_HandlerFunc_t handlerFunc
793 )
794 {
795  LE_UNUSED(name);
796  return _le_event_AddHandler(eventId, handlerFunc);
797 }
798 #endif /* end LE_CONFIG_EVENT_NAMES_ENABLED */
799 
800 
801 #if LE_CONFIG_EVENT_NAMES_ENABLED
802 //--------------------------------------------------------------------------------------------------
803 /**
804  * Adds a layered handler function for a publish-subscribe event ID.
805  *
806  * Tells the calling thread event loop to call a specified handler function when a defined event
807  * reaches the front of the event queue. Passes the required handler functions when called.
808  *
809  * This is intended for use in implementing @ref c_event_layeredPublishSubscribe.
810  *
811  * @param[in] name Handler name.
812  * @param[in] name Event ID.
813  * @param[in] name Pointer to first-layer handler func.
814  * @param[in] name Pointer to second-layer handler func.
815  *
816  * @return
817  * Handler reference, only needed for later removal of the handler (using
818  * le_event_RemoveHandler() ). Can be ignored if the handler will never be removed.
819  *
820  * @note Doesn't return on failure, there's no need to check the return value for errors.
821  */
822 //--------------------------------------------------------------------------------------------------
824 (
825  const char *name,
826  le_event_Id_t eventId,
827  le_event_LayeredHandlerFunc_t firstLayerFunc,
828  void* secondLayerFunc
829 );
830 #else /* if not LE_CONFIG_EVENT_NAMES_ENABLED */
831 /// @cond HIDDEN_IN_USER_DOCS
832 //--------------------------------------------------------------------------------------------------
833 /**
834  * Internal function used to implement le_event_AddLayeredHandler().
835  */
836 //--------------------------------------------------------------------------------------------------
837 le_event_HandlerRef_t _le_event_AddLayeredHandler(le_event_Id_t eventId,
838  le_event_LayeredHandlerFunc_t firstLayerFunc,
839  void* secondLayerFunc);
840 /// @endcond
841 //--------------------------------------------------------------------------------------------------
842 /**
843  * Adds a layered handler function for a publish-subscribe event ID.
844  *
845  * Tells the calling thread event loop to call a specified handler function when a defined event
846  * reaches the front of the event queue. Passes the required handler functions when called.
847  *
848  * This is intended for use in implementing @ref c_event_layeredPublishSubscribe.
849  *
850  * @param[in] name Handler name.
851  * @param[in] name Event ID.
852  * @param[in] name Pointer to first-layer handler func.
853  * @param[in] name Pointer to second-layer handler func.
854  *
855  * @return
856  * Handler reference, only needed for later removal of the handler (using
857  * le_event_RemoveHandler() ). Can be ignored if the handler will never be removed.
858  *
859  * @note Doesn't return on failure, there's no need to check the return value for errors.
860  */
861 //--------------------------------------------------------------------------------------------------
863 (
864  const char *name,
865  le_event_Id_t eventId,
866  le_event_LayeredHandlerFunc_t firstLayerFunc,
867  void* secondLayerFunc
868 )
869 {
870  LE_UNUSED(name);
871  return _le_event_AddLayeredHandler(eventId, firstLayerFunc, secondLayerFunc);
872 }
873 #endif /* end LE_CONFIG_EVENT_NAMES_ENABLED */
874 
875 
876 //--------------------------------------------------------------------------------------------------
877 /**
878  * Remove Handler
879  *
880  * Removes a previously added event handler function.
881  */
882 //--------------------------------------------------------------------------------------------------
884 (
885  le_event_HandlerRef_t handlerRef ///< [in] Handler reference.
886 );
887 
888 
889 //--------------------------------------------------------------------------------------------------
890 /**
891  * Report an Event
892  *
893  * Queues an Event Report to any and all event loops that have handlers for that event.
894  *
895  * @note Copies the event report payload, so it is safe to release or reuse the buffer that
896  * payloadPtr points to as soon as le_event_Report() returns.
897  */
898 //--------------------------------------------------------------------------------------------------
899 void le_event_Report
900 (
901  le_event_Id_t eventId, ///< [in] Event ID created using le_event_CreateId().
902  void* payloadPtr, ///< [in] Pointer to the payload bytes to be copied into the report.
903  size_t payloadSize ///< [in] Number of bytes of payload to copy into the report.
904 );
905 
906 
907 //--------------------------------------------------------------------------------------------------
908 /**
909  * Sends an Event Report with a pointer to a reference-counted object as its payload.
910  * The pointer must have been obtained from a memory pool using the @ref c_memory.
911  *
912  * Calling this function passes ownership of the reference to the Event Loop API.
913  * The Event Loop API will ensure that the reference is properly counted while it passes
914  * through the event report dispatching system. Each handler will receive one counted reference
915  * to the object, so the handler is responsible for releasing the object when it is finished with
916  * it.
917  */
918 //--------------------------------------------------------------------------------------------------
920 (
921  le_event_Id_t eventId, ///< [in] Event ID created using le_event_CreateIdWithRefCounting().
922  void* objectPtr ///< [in] Pointer to an object allocated from a memory pool
923  /// (using the @ref c_memory).
924 );
925 
926 
927 //--------------------------------------------------------------------------------------------------
928 /**
929  * Sets the context pointer for a given event handler.
930  *
931  * This can later be retrieved using le_event_GetContextPtr() from within the handler function
932  * when it is called.
933  */
934 //--------------------------------------------------------------------------------------------------
936 (
937  le_event_HandlerRef_t handlerRef, ///< [in] Handler where context pointer is to be set.
938  void* contextPtr ///< [in] Context pointer value.
939 );
940 
941 //--------------------------------------------------------------------------------------------------
942 /**
943  * Fetches the context pointer for a given event handler.
944  *
945  * @return
946  * The context pointer associated to the handlerRef.
947  */
948 //--------------------------------------------------------------------------------------------------
950 (
951  le_event_HandlerRef_t handlerRef ///< [in] Handler whose context pointer is to be set.
952 );
953 
954 //--------------------------------------------------------------------------------------------------
955 /**
956  * Fetches the context pointer for the currently running event handler.
957  *
958  * Can only be called from within an event handler function.
959  *
960  * @return
961  * Context pointer that was set using le_event_SetContextPtr(), or NULL if
962  * le_event_SetContextPtr() was not called.
963  */
964 //--------------------------------------------------------------------------------------------------
966 (
967  void
968 );
969 
970 
971 //--------------------------------------------------------------------------------------------------
972 /**
973  * Queue a function onto the calling thread's Event Queue. When it reaches the head of the
974  * Event Queue, it will be called by the calling thread's Event Loop.
975  */
976 //--------------------------------------------------------------------------------------------------
978 (
979  le_event_DeferredFunc_t func, ///< [in] Function to be called later.
980  void* param1Ptr, ///< [in] Value to be passed to the function when called.
981  void* param2Ptr ///< [in] Value to be passed to the function when called.
982 );
983 
984 
985 //--------------------------------------------------------------------------------------------------
986 /**
987  * Queue a function onto a specific thread's Event Queue. When it reaches the head of that
988  * Event Queue, it will be called by that thread's Event Loop.
989  */
990 //--------------------------------------------------------------------------------------------------
992 (
993  le_thread_Ref_t thread, ///< [in] Thread to queue the function to.
994  le_event_DeferredFunc_t func, ///< [in] The function.
995  void* param1Ptr, ///< [in] Value to be passed to the function when called.
996  void* param2Ptr ///< [in] Value to be passed to the function when called.
997 );
998 
999 //--------------------------------------------------------------------------------------------------
1000 /**
1001  * Queue a function onto a specific thread's Event Queue if it isn't already on the Event
1002  * Queue with the same parameters. When it reaches the head of that Event Queue, it will be
1003  * called by that thread's Event Loop.
1004  *
1005  * Using this function generally indicates poor design.
1006  * It's generally better to ensure the event is only generated once, for example by disabling
1007  * generating the event until the event handler is run.
1008  *
1009  * @return LE_OK if the function was queued to the Event Queue
1010  * @return LE_DUPLICATE if the function was already in the Event Queue
1011  */
1012 //--------------------------------------------------------------------------------------------------
1014 (
1015  le_thread_Ref_t thread, ///< [in] Thread to queue the function to.
1016  le_event_DeferredFunc_t func, ///< [in] The function.
1017  void* param1Ptr, ///< [in] Value to be passed to the function when called.
1018  void* param2Ptr ///< [in] Value to be passed to the function when called.
1019 );
1020 
1021 
1022 //--------------------------------------------------------------------------------------------------
1023 /**
1024  * Runs the event loop for the calling thread.
1025  *
1026  * This starts processing events by the calling thread.
1027  *
1028  * Can only be called once for each thread, and must never be called in
1029  * the process's main thread.
1030  *
1031  * @note
1032  * Function never returns.
1033  */
1034 //--------------------------------------------------------------------------------------------------
1035 void le_event_RunLoop
1036 (
1037  void
1038 )
1039 __attribute__ ((noreturn));
1040 
1041 
1042 //--------------------------------------------------------------------------------------------------
1043 /**
1044  * Fetches a file descriptor that will appear readable to poll(), select(), epoll_wait(), etc.
1045  * when the calling thread's Event Loop needs servicing (via a call to le_event_ServiceLoop()).
1046  *
1047  * @warning Only intended for use when integrating with legacy POSIX-based software
1048  * that cannot be easily refactored to use the Legato Event Loop. The preferred approach is
1049  * to call le_event_RunLoop().
1050  *
1051  * @return The file descriptor.
1052  */
1053 //--------------------------------------------------------------------------------------------------
1055 (
1056  void
1057 );
1058 
1059 
1060 //--------------------------------------------------------------------------------------------------
1061 /**
1062  * Services the calling thread's Event Loop.
1063  *
1064  * @warning Only intended for use when integrating with legacy POSIX-based software
1065  * that can't be easily refactored to use the Legato Event Loop. The preferred approach is
1066  * to call le_event_RunLoop().
1067  *
1068  * See also: le_event_GetFd().
1069  *
1070  * @return
1071  * - LE_OK if there is more to be done. DO NOT GO BACK TO SLEEP without calling
1072  * le_event_ServiceLoop() again.
1073  * - LE_WOULD_BLOCK if there is nothing left to do for now and it is safe to go back to sleep.
1074  */
1075 //--------------------------------------------------------------------------------------------------
1077 (
1078  void
1079 );
1080 
1081 
1082 #endif // LEGATO_EVENTLOOP_INCLUDE_GUARD
struct le_thread * le_thread_Ref_t
Definition: le_thread.h:180
void * le_event_GetContextPtrFromRef(le_event_HandlerRef_t handlerRef)
le_event_Id_t le_event_CreateIdWithRefCounting(const char *name)
void(* le_event_LayeredHandlerFunc_t)(void *reportPtr, void *secondLayerFunc)
Definition: le_eventLoop.h:603
le_result_t
Definition: le_basics.h:46
#define LE_UNUSED(v)
Definition: le_basics.h:369
LE_FULL_API int le_event_GetFd(void)
struct le_event_Handler * le_event_HandlerRef_t
Definition: le_eventLoop.h:633
struct le_event_Id * le_event_Id_t
Definition: le_eventLoop.h:520
void le_event_QueueFunctionToThread(le_thread_Ref_t thread, le_event_DeferredFunc_t func, void *param1Ptr, void *param2Ptr)
le_result_t le_event_QueueFunctionToThreadUnique(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:619
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:585
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:320
void le_event_QueueFunction(le_event_DeferredFunc_t func, void *param1Ptr, void *param2Ptr)