le_eventLoop.h

Go to the documentation of this file.
1 /**
2  * @page c_eventLoop Event Loop API
3  *
4  * @ref 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. Use of this work is subject to license.
496  */
497 
498 //--------------------------------------------------------------------------------------------------
499 /** @file le_eventLoop.h
500  *
501  * Legato @ref c_eventLoop include file.
502  *
503  * Copyright (C) Sierra Wireless Inc. Use of this work is subject to license.
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 // TODO: Remove this.
547 #ifndef COMPONENT_INIT
548  /**
549  * Initialization event handler function.
550  */
551  #define COMPONENT_INIT LE_CI_LINKAGE LE_SHARED void _le_event_InitializeComponent(void)
552 #endif
553 
554 /// Deprecated name for @ref COMPONENT_INIT.
555 #define LE_EVENT_INIT_HANDLER COMPONENT_INIT
556 
557 
558 //--------------------------------------------------------------------------------------------------
559 /**
560  * Prototype for publish-subscribe event handler functions look like this:
561  *
562  * @param reportPtr [in] Pointer to the event report payload.
563  *
564  * @warning The reportPtr is only valid until the handler function returns.
565  */
566 //--------------------------------------------------------------------------------------------------
567 typedef void (*le_event_HandlerFunc_t)
568 (
569  void* reportPtr
570 );
571 
572 
573 //--------------------------------------------------------------------------------------------------
574 /**
575  * Prototype for the first layer of a layered publish-subscribe event handler function
576  * look like this:
577  *
578  * @param reportPtr [in] Pointer to the event report payload.
579  *
580  * @param secondLayerFunc [in] Address of the second layer handler function.
581  *
582  * @warning The reportPtr is only valid until the handler function returns.
583  */
584 //--------------------------------------------------------------------------------------------------
585 typedef void (*le_event_LayeredHandlerFunc_t)
586 (
587  void* reportPtr,
588  void* secondLayerFunc
589 );
590 
591 
592 //--------------------------------------------------------------------------------------------------
593 /**
594  * Prototype for deferred functions look like this:
595  * @param param1Ptr [in] Value passed in as param1Ptr to le_event_QueueFunction().
596  * @param param2Ptr [in] Value passed in as param2Ptr to le_event_QueueFunction().
597  *
598  * See @ref c_event_deferredFunctionCalls for more information.
599  */
600 //--------------------------------------------------------------------------------------------------
601 typedef void (*le_event_DeferredFunc_t)
602 (
603  void* param1Ptr,
604  void* param2Ptr
605 );
606 
607 
608 //--------------------------------------------------------------------------------------------------
609 /**
610  * Handler reference.
611  *
612  *Used to refer to handlers that have been added for events. Only needed if
613  * you want to set the handler's context pointer or need to remove the handler later.
614  */
615 //--------------------------------------------------------------------------------------------------
616 typedef struct le_event_Handler* le_event_HandlerRef_t;
617 
618 
619 //--------------------------------------------------------------------------------------------------
620 /**
621  * Create a new event ID.
622  *
623  * @return
624  * Event ID.
625  *
626  * @note Doesn't return on failure, there's no need to check the return value for errors.
627  */
628 //--------------------------------------------------------------------------------------------------
630 (
631  const char* name, ///< [in] Name of the event ID. (Named for diagnostic purposes.)
632  size_t payloadSize ///< [in] Data payload size (in bytes) of the event reports (can be 0).
633 );
634 
635 
636 //--------------------------------------------------------------------------------------------------
637 /**
638  * Create a new event ID to report events where the payload is a pointer to
639  * a reference-counted memory pool object allocated using the @ref c_memory.
640  *
641  * @return
642  * 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 ///< [in] Name of the event ID. (Named for diagnostic purposes.)
650 );
651 
652 
653 //--------------------------------------------------------------------------------------------------
654 /**
655  * Adds a handler function for a publish-subscribe event ID.
656  *
657  * Tells the calling thread event loop to call a specified handler function when a defined event
658  * reaches the front of the event queue.
659  *
660  * @return
661  * Handler reference, only needed to remove the handler (using
662  * le_event_RemoveHandler() ). Can be ignored if the handler will never be removed.
663  *
664  * @note Doesn't return on failure, there's no need to check the return value for errors.
665  */
666 //--------------------------------------------------------------------------------------------------
668 (
669  const char* name, ///< [in] Handler name.
670  le_event_Id_t eventId, ///< [in] Event ID.
671  le_event_HandlerFunc_t handlerFunc ///< [in] Handler function.
672 );
673 
674 
675 //--------------------------------------------------------------------------------------------------
676 /**
677  * Adds a layered handler function for a publish-subscribe event ID.
678  *
679  * Tells the calling thread event loop to call a specified handler function when a defined event
680  * reaches the front of the event queue. Passes the required handler functions when called.
681  *
682  * This is intended for use in implementing @ref c_event_layeredPublishSubscribe.
683  *
684  * @return
685  * Handler reference, only needed for later removal of the handler (using
686  * le_event_RemoveHandler() ). Can be ignored if the handler will never be removed.
687  *
688  * @note Doesn't return on failure, there's no need to check the return value for errors.
689  */
690 //--------------------------------------------------------------------------------------------------
692 (
693  const char* name, ///< [in] Handler name.
694  le_event_Id_t eventId, ///< [in] Event ID.
695  le_event_LayeredHandlerFunc_t firstLayerFunc, ///< [in] Pointer to first-layer handler func.
696  void* secondLayerFunc ///< [in] Pointer to second-layer handler func.
697 );
698 
699 
700 //--------------------------------------------------------------------------------------------------
701 /**
702  * Remove Handler
703  *
704  * Removes a previously added event handler function.
705  */
706 //--------------------------------------------------------------------------------------------------
708 (
709  le_event_HandlerRef_t handlerRef ///< [in] Handler reference.
710 );
711 
712 
713 //--------------------------------------------------------------------------------------------------
714 /**
715  * Report an Event
716  *
717  * Queues an Event Report to any and all event loops that have handlers for that event.
718  *
719  * @note Copies the event report payload, so it is safe to release or reuse the buffer that
720  * payloadPtr points to as soon as le_event_Report() returns.
721  */
722 //--------------------------------------------------------------------------------------------------
723 void le_event_Report
724 (
725  le_event_Id_t eventId, ///< [in] Event ID created using le_event_CreateId().
726  void* payloadPtr, ///< [in] Pointer to the payload bytes to be copied into the report.
727  size_t payloadSize ///< [in] Number of bytes of payload to copy into the report.
728 );
729 
730 
731 //--------------------------------------------------------------------------------------------------
732 /**
733  * Sends an Event Report with a pointer to a reference-counted object as its payload.
734  * The pointer must have been obtained from a memory pool using the @ref c_memory.
735  *
736  * Calling this function passes ownership of the reference to the Event Loop API.
737  * The Event Loop API will ensure that the reference is properly counted while it passes
738  * through the event report dispatching system. Each handler will receive one counted reference
739  * to the object, so the handler is responsible for releasing the object when it is finished with
740  * it.
741  */
742 //--------------------------------------------------------------------------------------------------
744 (
745  le_event_Id_t eventId, ///< [in] Event ID created using le_event_CreateIdWithRefCounting().
746  void* objectPtr ///< [in] Pointer to an object allocated from a memory pool
747  /// (using the @ref c_memory).
748 );
749 
750 
751 //--------------------------------------------------------------------------------------------------
752 /**
753  * Sets the context pointer for a given event handler.
754  *
755  * This can later be retrieved using le_event_GetContextPtr() from within the handler function
756  * when it is called.
757  */
758 //--------------------------------------------------------------------------------------------------
760 (
761  le_event_HandlerRef_t handlerRef, ///< [in] Handler where context pointer is to be set.
762  void* contextPtr ///< [in] Context pointer value.
763 );
764 
765 
766 //--------------------------------------------------------------------------------------------------
767 /**
768  * Fetches the context pointer for the currently running event handler.
769  *
770  * Can only be called from within an event handler function.
771  *
772  * @return
773  * Context pointer that was set using le_event_SetContextPtr(), or NULL if
774  * le_event_SetContextPtr() was not called.
775  */
776 //--------------------------------------------------------------------------------------------------
778 (
779  void
780 );
781 
782 
783 //--------------------------------------------------------------------------------------------------
784 /**
785  * Queue a function onto the calling thread's Event Queue. When it reaches the head of the
786  * Event Queue, it will be called by the calling thread's Event Loop.
787  */
788 //--------------------------------------------------------------------------------------------------
790 (
791  le_event_DeferredFunc_t func, ///< [in] Function to be called later.
792  void* param1Ptr, ///< [in] Value to be passed to the function when called.
793  void* param2Ptr ///< [in] Value to be passed to the function when called.
794 );
795 
796 
797 //--------------------------------------------------------------------------------------------------
798 /**
799  * Queue a function onto a specific thread's Event Queue. When it reaches the head of that
800  * Event Queue, it will be called by that thread's Event Loop.
801  */
802 //--------------------------------------------------------------------------------------------------
804 (
805  le_thread_Ref_t thread, ///< [in] Thread to queue the function to.
806  le_event_DeferredFunc_t func, ///< [in] The function.
807  void* param1Ptr, ///< [in] Value to be passed to the function when called.
808  void* param2Ptr ///< [in] Value to be passed to the function when called.
809 );
810 
811 
812 //--------------------------------------------------------------------------------------------------
813 /**
814  * Runs the event loop for the calling thread.
815  *
816  * This starts processing events by the calling thread.
817  *
818  * Can only be called once for each thread, and must never be called in
819  * the process's main thread.
820  *
821  * @note
822  * Function never returns.
823  */
824 //--------------------------------------------------------------------------------------------------
825 void le_event_RunLoop
826 (
827  void
828 )
829 __attribute__ ((noreturn));
830 
831 
832 //--------------------------------------------------------------------------------------------------
833 /**
834  * Fetches a file descriptor that will appear readable to poll(), select(), epoll_wait(), etc.
835  * when the calling thread's Event Loop needs servicing (via a call to le_event_ServiceLoop()).
836  *
837  * @warning Only intended for use when integrating with legacy POSIX-based software
838  * that cannot be easily refactored to use the Legato Event Loop. The preferred approach is
839  * to call le_event_RunLoop().
840  *
841  * @return The file descriptor.
842  */
843 //--------------------------------------------------------------------------------------------------
844 int le_event_GetFd
845 (
846  void
847 );
848 
849 
850 //--------------------------------------------------------------------------------------------------
851 /**
852  * Services the calling thread's Event Loop.
853  *
854  * @warning Only intended for use when integrating with legacy POSIX-based software
855  * that can't be easily refactored to use the Legato Event Loop. The preferred approach is
856  * to call le_event_RunLoop().
857  *
858  * See also: le_event_GetFd().
859  *
860  * @return
861  * - LE_OK if there is more to be done. DO NOT GO BACK TO SLEEP without calling
862  * le_event_ServiceLoop() again.
863  * - LE_WOULD_BLOCK if there is nothing left to do for now and it is safe to go back to sleep.
864  */
865 //--------------------------------------------------------------------------------------------------
867 (
868  void
869 );
870 
871 
872 #endif // LEGATO_EVENTLOOP_INCLUDE_GUARD
struct le_thread * le_thread_Ref_t
Definition: le_thread.h:178
void(* le_event_DeferredFunc_t)(void *param1Ptr, void *param2Ptr)
Definition: le_eventLoop.h:602
void le_event_ReportWithRefCounting(le_event_Id_t eventId, void *objectPtr)
le_result_t
Definition: le_basics.h:35
void le_event_RunLoop(void)
struct le_event_Id * le_event_Id_t
Definition: le_eventLoop.h:518
le_result_t le_event_ServiceLoop(void)
le_event_Id_t le_event_CreateIdWithRefCounting(const char *name)
void le_event_Report(le_event_Id_t eventId, void *payloadPtr, size_t payloadSize)
void le_event_SetContextPtr(le_event_HandlerRef_t handlerRef, void *contextPtr)
le_event_HandlerRef_t le_event_AddLayeredHandler(const char *name, le_event_Id_t eventId, le_event_LayeredHandlerFunc_t firstLayerFunc, void *secondLayerFunc)
void(* le_event_LayeredHandlerFunc_t)(void *reportPtr, void *secondLayerFunc)
Definition: le_eventLoop.h:586
int le_event_GetFd(void)
le_event_HandlerRef_t le_event_AddHandler(const char *name, le_event_Id_t eventId, le_event_HandlerFunc_t handlerFunc)
void le_event_QueueFunction(le_event_DeferredFunc_t func, void *param1Ptr, void *param2Ptr)
struct le_event_Handler * le_event_HandlerRef_t
Definition: le_eventLoop.h:616
void * le_event_GetContextPtr(void)
le_event_Id_t le_event_CreateId(const char *name, size_t payloadSize)
void le_event_QueueFunctionToThread(le_thread_Ref_t thread, le_event_DeferredFunc_t func, void *param1Ptr, void *param2Ptr)
void(* le_event_HandlerFunc_t)(void *reportPtr)
Definition: le_eventLoop.h:568
void le_event_RemoveHandler(le_event_HandlerRef_t handlerRef)