Mstdlib-1.24.0
m_event.h
1/* The MIT License (MIT)
2 *
3 * Copyright (c) 2017 Monetra Technologies, LLC.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to deal
7 * in the Software without restriction, including without limitation the rights
8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 * copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 * THE SOFTWARE.
22 */
23
24#ifndef __M_EVENT_H__
25#define __M_EVENT_H__
26
27/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
28
29#include <mstdlib/base/m_defs.h>
30#include <mstdlib/base/m_types.h>
31#include <mstdlib/io/m_io.h>
32
33/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
34
35__BEGIN_DECLS
36
37/*! \addtogroup m_event Event Subsystem
38 * \ingroup m_eventio
39 *
40 * Cross platform event based processing. A platform specific backend will be used
41 * as the underlying event system but all events will be exposed though this interface.
42 * No platform specific knowledge is needed.
43 *
44 * Developers used to working with macOS event loop style of programming can use
45 * this event system to use that paradigm on other platforms. In this scenario most
46 * events would be triggered as OTHER. Some sort of tracking would be necessary to
47 * determine why an event was triggered if the same callback is used for multiple
48 * situations.
49 *
50 * The event system is thread safe allowing io objects and times can be added
51 * to and moved between different event loops running on different threads.
52 * Triggers can be triggered from different threads. Destruction of an io object
53 * from a different thread will be queued in the event loop it's running on.
54 *
55 * Note: the CONNECTED event will be triggered when a io object is added to an event loop
56 * using M_event_add().
57 *
58 *
59 * Example application that demonstrates read/write events, timers, and queued tasks.
60 *
61 * \code{.c}
62 * #include <mstdlib/mstdlib.h>
63 * #include <mstdlib/mstdlib_io.h>
64 *
65 * typedef struct {
66 * M_buf_t *buf;
67 * M_parser_t *parser;
68 * M_io_t *io; // Necessary for the queued task and timer to have the correct io object.
69 * } ldata_t;
70 *
71 * static void add_queued_data(M_event_t *el, M_event_type_t etype, M_io_t *io, void *thunk)
72 * {
73 * ldata_t *ldata = thunk;
74 *
75 * (void)el;
76 * (void)etype;
77 *
78 * M_buf_add_str(ldata->buf, "STARTING\n");
79 * M_io_write_from_buf(ldata->io, ldata->buf);
80 * }
81 *
82 * static void add_data(M_event_t *el, M_event_type_t etype, M_io_t *io, void *thunk)
83 * {
84 * ldata_t *ldata = thunk;
85 * static int i = 1;
86 *
87 * (void)el;
88 * (void)etype;
89 *
90 * M_buf_add_str(ldata->buf, "TEST ");
91 * M_buf_add_int(ldata->buf, i++);
92 * M_buf_add_byte(ldata->buf, '\n');
93 * M_io_write_from_buf(ldata->io, ldata->buf);
94 * }
95 *
96 * static void stop(M_event_t *el, M_event_type_t etype, M_io_t *io, void *thunk)
97 * {
98 * (void)etype;
99 * (void)io;
100 * (void)thunk;
101 *
102 * M_event_done_with_disconnect(el, 0, 1000);
103 * }
104 *
105 * static void run_cb(M_event_t *el, M_event_type_t etype, M_io_t *io, void *thunk)
106 * {
107 * ldata_t *ldata = thunk;
108 * char *out;
109 *
110 * switch (etype) {
111 * case M_EVENT_TYPE_CONNECTED:
112 * break;
113 * case M_EVENT_TYPE_READ:
114 * M_io_read_into_parser(io, ldata->parser);
115 * out = M_parser_read_strdup(ldata->parser, M_parser_len(ldata->parser));
116 * M_printf("%s", out);
117 * M_free(out);
118 * break;
119 * case M_EVENT_TYPE_WRITE:
120 * // Write any data pending in the buffer.
121 * M_io_write_from_buf(io, ldata->buf);
122 * break;
123 * case M_EVENT_TYPE_DISCONNECTED:
124 * break;
125 * case M_EVENT_TYPE_ACCEPT:
126 * case M_EVENT_TYPE_ERROR:
127 * case M_EVENT_TYPE_OTHER:
128 * M_event_done(el);
129 * break;
130 * }
131 * }
132 *
133 * int main(int argc, char *argv)
134 * {
135 * M_event_t *el;
136 * M_io_t *io;
137 * M_event_timer_t *timer;
138 * ldata_t ldata;
139 *
140 * el = M_event_create(M_EVENT_FLAG_NONE);
141 *
142 * M_io_loopback_create(&io);
143 * ldata.buf = M_buf_create();
144 * ldata.parser = M_parser_create(M_PARSER_FLAG_NONE);
145 * ldata.io = io;
146 *
147 * M_event_add(el, io, run_cb, &ldata);
148 * M_event_queue_task(el, add_queued_data, &ldata);
149 *
150 * timer = M_event_timer_add(el, add_data, &ldata);
151 * M_event_timer_start(timer, 500);
152 * timer = M_event_timer_add(el, stop, NULL);
153 * M_event_timer_start(timer, 5000);
154 *
155 * M_event_loop(el, M_TIMEOUT_INF);
156 *
157 * M_io_destroy(io);
158 * M_event_destroy(el);
159 * M_buf_cancel(ldata.buf);
160 * M_parser_destroy(ldata.parser);
161 * return 0;
162 * }
163 * \endcode
164 *
165 * @{
166 */
167
168/*! Events that can be generated.
169 *
170 * Events are enumerated in priority of delivery order
171 */
173 M_EVENT_TYPE_CONNECTED = 0, /*!< The connection has been completed */
174 M_EVENT_TYPE_ACCEPT, /*!< A new incoming connection is ready to be accepted */
175 M_EVENT_TYPE_READ, /*!< There is available data to be read */
176 M_EVENT_TYPE_DISCONNECTED, /*!< The connection has been successfully disconnected.
177 * This is only triggered after a disconnect request,
178 * Otherwise most failures are determined by a Read
179 * event followed by a read failure. The connection
180 * object should be closed after this. */
181 M_EVENT_TYPE_ERROR, /*!< An error occurred. Most likely during connection
182 establishment by a higher-level protocol. The
183 connection object should be closed after this. */
184 M_EVENT_TYPE_WRITE, /*!< There is room available in the write buffer */
185 M_EVENT_TYPE_OTHER /*!< Some other event occurred, such as a triggered or
186 * timer-based event */
188/*! Events that can be generated. */
190
191
192/*! Opaque structure for event trigger */
193struct M_event_trigger;
194
195/*! Handle for an event trigger */
196typedef struct M_event_trigger M_event_trigger_t;
197
198
199/*! Opaque structure for event timers */
200struct M_event_timer;
201
202/*! Handle for an event timer */
203typedef struct M_event_timer M_event_timer_t;
204
205
206/*! Opaque structure for an event loop or pool handle */
207struct M_event;
208
209/* Handle for an event loop or pool handle */
210typedef struct M_event M_event_t;
211
212
213/*! Definition for a function callback that is called every time an event is triggered by
214 * the event subsystem.
215 *
216 * \param[in] event Internal event object, this is an event-thread specific object which could be
217 * the member of a pool. This object may be used to add new events to the same
218 * event thread, or M_event_get_pool() can be used to retrieve the master pool
219 * handle for distributing events across threads.
220 * \param[in] type The type of event that has been triggered, see M_event_type_t. Always
221 * M_EVENT_TYPE_OTHER for trigger, timer, and queued tasks.
222 * \param[in] io Pointer to the M_io_t object associated with the event, or NULL for trigger,
223 * timer, and queued tasks.
224 * \param[in] cb_arg User-specified callback argument registered when the object was added to the
225 * event handle.
226 */
227typedef void (*M_event_callback_t)(M_event_t *event, M_event_type_t type, M_io_t *io, void *cb_arg);
228
229
230/*! Possible list of flags that can be used when initializing an event loop */
232 M_EVENT_FLAG_NONE = 0, /*!< No specialized flags */
233 M_EVENT_FLAG_NOWAKE = 1 << 0, /*!< We will never need to wake the event loop from another thread. Not
234 * recommended to use as some internal subsystems (like M_dns) may
235 * need to use it without your knowledge. */
236 M_EVENT_FLAG_EXITONEMPTY = 1 << 1, /*!< Exit the event loop when there are no registered events */
237 M_EVENT_FLAG_EXITONEMPTY_NOTIMERS = 1 << 2, /*!< When combined with M_EVENT_FLAG_EXITONEMPTY, will ignore timers */
238 M_EVENT_FLAG_NON_SCALABLE = 1 << 3 /*!< Utilize the 'non-scalable/small' event subsystem, generally
239 * implemented using poll() instead of the more scalable solution
240 * using kqueue() or epoll(). The main reason one might want to use
241 * this is if a large number of event loops are being created such
242 * as when using the blocking APIs, using the scalable solution
243 * generally consumes additional file descriptors which may not be
244 * desirable. Not all systems have different subsystems, in which
245 * case this flag will be ignored.
246 */
248
249/*! Possible values to pass to M_event_get_statistic() */
250typedef enum {
251 M_EVENT_STATISTIC_WAKE_COUNT, /*!< Get the number of times the event loop has woken due to some sort of event */
252 M_EVENT_STATISTIC_OSEVENT_COUNT, /*!< Get the number of OS-delivered events */
253 M_EVENT_STATISTIC_SOFTEVENT_COUNT, /*!< Get the number of soft-events delivered */
254 M_EVENT_STATISTIC_TIMER_COUNT, /*!< Get the number of timer (or queued) events delivered */
255 M_EVENT_STATISTIC_PROCESS_TIME_MS /*!< Get the about of non-idle time spent by the event loop in ms */
257
258
259/*! Create a base event loop object.
260 *
261 * An event loop is typically run in the main process thread and will block until
262 * process termination. IO and timer objects are enqueued into the event loop and
263 * dispatched within the event loop. Event loops are more efficient and scalable
264 * than using a thread per tracked io object.
265 *
266 * \param[in] flags One or more enum M_EVENT_FLAGS
267 *
268 * \return Initialized event loop object.
269 */
270M_API M_event_t *M_event_create(M_uint32 flags);
271
272
273/*! Create a pool of M_event_t objects bound to a master pool handle to distribute load
274 * of event handling across multiple threads.
275 *
276 * One thread per CPU core will be created for handling events, up to the maximum
277 * specified during creationg of the pool. When an object is added to the event
278 * pool handle, an internal search is performed, and the least-loaded thread will
279 * receive the new object.
280 *
281 * Objects bound to the same internal event object will always execute in the same thread
282 * which may be desirable for co-joined objects (otherwise additional locking may be
283 * required since multiple events could fire from different threads for some shared
284 * resource). Typically this co-joined objects will be created based on events that
285 * have been fired, so the M_event_t object returned from the M_event_callback_t callback
286 * should be used to ensure they stay co-joined.
287 *
288 * For non co-joined objects, always ensure the event handle used is the pool by calling
289 * M_event_get_pool() otherwise load will not be distributed at all.
290 *
291 * \param[in] max_threads Artificial limitation on the maximum number of threads, the
292 * actual number of threads will be the lesser of this value
293 * and the number of cpu cores in the system. Use 0 for this
294 * value to simply use the number of cpu cores.
295 *
296 * \return Initialized event pool, or in the case only a single thread would be used,
297 * a normal event object.
298 */
299M_API M_event_t *M_event_pool_create(size_t max_threads);
300
301
302/*! Retrieve the distributed pool handle for balancing the load across an event pool, or
303 * self if not part of a pool.
304 *
305 * This should be called to get the event handle during M_event_add(), M_event_trigger_add(),
306 * M_event_timer_add(), M_event_timer_oneshot(), or M_event_queue_task() as by default
307 * tasks will otherwise not be distributed if using the event handle returned by the M_event_callback_t.
308 * In some cases it is desirable to ensure co-joined objects run within the same event thread
309 * and therefore desirable to enqueue multiple tasks for an internal event loop handle rather
310 * than the distributed pool.
311 *
312 * \param[in] event Pointer to event handle either returned by M_event_create(), M_event_pool_create(),
313 * or from an M_event_callback_t.
314 *
315 * \return Pointer to event pool, or self if not part of a pool (or if a pool object already passed in).
316 */
318
319
320/*! Get the registered event handle for the io object
321 *
322 * \param[in] io IO object.
323 *
324 * \return Event loop object associated with the io object.
325 */
327
328
329/*! Destroy the event loop or pool object
330 *
331 * \param[in] event Pointer to event handle either returned by M_event_create(), M_event_pool_create(),
332 * or from an M_event_callback_t.
333 */
334M_API void M_event_destroy(M_event_t *event);
335
336
337/*! Add an io object to the event loop handle with a registered callback to deliver events to.
338 *
339 * Adding handles to an event handle is threadsafe and can be executed either within an event
340 * callback or from a separate thread.
341 *
342 * \param[in] event Event handle to add the event to. If desirable to ensure this io object
343 * is distributed across a pool, it is recommended to pass the return value
344 * of M_event_get_pool() rather than the event handle returned by an
345 * M_event_callback_t callback.
346 * \param[in] io IO object to bind to the event handle.
347 * \param[in] callback Callback to be called when events occur.
348 * \param[in] cb_data Optional. User-defined callback data that will be passed to the user-defined
349 * callback. Use NULL if no data is necessary.
350 *
351 * \return M_TRUE on success, or M_FALSE on failure (e.g. misuse, or io handle already bound to
352 * an event).
353 */
354M_API M_bool M_event_add(M_event_t *event, M_io_t *io, M_event_callback_t callback, void *cb_data);
355
356
357/*! Edit the callback associated with an io object in the event subsystem.
358 *
359 * Editing allows a user to re-purpose an io object while processing events without
360 * needing to remove and re-add the object which may cause a loss of events.
361 *
362 * \note This will NOT cause a connected event to be triggered like M_event_add() does when
363 * you first add an io object to an event loop for already-established connections.
364 *
365 * \param[in] io IO object to modify the callback for
366 * \param[in] callback Callback to set. NULL will set it to no callback.
367 * \param[in] cb_data Data passed to callback function. NULL will remove the cb_data.
368 * \return M_FALSE on error, such as if the IO object is not currently attached to an
369 * event loop.
370 */
371M_API M_bool M_event_edit_io_cb(M_io_t *io, M_event_callback_t callback, void *cb_data);
372
373
374/*! Retrieve the callback associated with an io object in the event subsystem.
375 *
376 * \param[in] io IO object to modify the callback for
377 * \param[out] cb_data_out Pointer to store callback data registered with callback.
378 * \return registered callback, or NULL if none.
379 */
380M_API M_event_callback_t M_event_get_io_cb(M_io_t *io, void **cb_data_out);
381
382
383/*! Remove an io object from its associated event handle.
384 *
385 * Removing handles is threadsafe and can be executed either within an event
386 * callback or from a separate thread.
387 *
388 * \param[in] io IO object.
389 */
390M_API void M_event_remove(M_io_t *io);
391
392
393/*! Create a user-callable trigger which will call the pre-registered callback. Useful for
394 * cross-thread completion or status update notifications. Triggering events is threadsafe.
395 *
396 * \param[in] event Event handle to add the event to. If desirable to ensure this io object
397 * is distributed across a pool, it is recommended to pass the return value
398 * of M_event_get_pool() rather than the event handle returned by an
399 * M_event_callback_t callback.
400 * \param[in] callback Callback to be called when the trigger is called.
401 * \param[in] cb_data Optional. User-defined callback data that will be passed to the user-defined
402 * callback. Use NULL if no data is necessary.
403 *
404 * \return handle to trigger to be used to execute callback, or NULL on failure
405 */
407
408
409/*! Remove the user-callable trigger, once removed, the trigger is no longer valid and cannot be called.
410 *
411 * \param[in] trigger Trigger returned from M_event_trigger_add()
412 */
414
415
416/*! Edit the callback associated with a trigger object in the event subsystem.
417 *
418 * Editing allows a user to re-purpose a timer object while processing events without
419 * needing to remove and add a new object.
420 *
421 * \param[in] trigger Trigger returned from M_event_trigger_add()
422 * \param[in] callback Callback to set.
423 * \param[in] cb_data Data passed to callback function. NULL will remove the cb_data.
424 *
425 * \return M_FALSE on error, such as if the callback is NULL.
426 */
427M_API M_bool M_event_trigger_edit_cb(M_event_trigger_t *trigger, M_event_callback_t callback, void *cb_data);
428
429
430/*! Signal the registered callback associated with the trigger to be called. This is threadsafe and
431 * may be called cross thread. If multiple signals are delivered before the callback is called, the
432 * duplicate signals will be silently discarded.
433 *
434 * \param[in] trigger Trigger returned from M_event_trigger_add()
435 */
437
438
439/*! Add a timer object to the event loop specified that will call the user-supplied callback
440 * when the timer expires. The timer is created in a stopped state and must be started before
441 * it will fire.
442 *
443 * If the timer is associated with another object (e.g. co-joined) then the same event handle
444 * as the other object should be used.
445 *
446 * \param[in] event Event handle to add the timer to. If the event handle is a pool object,
447 * it will automatically distribute to an event thread.
448 * \param[in] callback User-specified callback to call when the timer expires
449 * \param[in] cb_data Optional. User-specified data supplied to user-specified callback when
450 * executed.
451 *
452 * \return Timer handle on success, NULL on failure.
453 */
454M_API M_event_timer_t *M_event_timer_add(M_event_t *event, M_event_callback_t callback, void *cb_data);
455
456
457/*! Starts the specified timer with timeout specified. When the timeout expires, the
458 * callback associated with the timer will be executed.
459 *
460 * \param[in] timer Timer handle returned by M_event_timer_add()
461 * \param[in] interval_ms Time in milliseconds before the timer will expire. May only be
462 * 0 if the configured "firecount" is 1.
463 *
464 * \return M_TRUE on success, M_FALSE on failure (such as timer already running or invalid use).
465 */
466M_API M_bool M_event_timer_start(M_event_timer_t *timer, M_uint64 interval_ms);
467
468
469/*! Stops the specified timer.
470 *
471 * \param[in] timer Timer handle returned by M_event_timer_add()
472 *
473 * \return M_TRUE on success, M_FALSE if timer not running
474 */
476
477
478/*! Restart the timer.
479 *
480 * If the timer is already stopped, will simply start it again. If the timer
481 * has "autoremove" configured, the removal will be skipped on stop.
482 *
483 * \param[in] timer Timer handle returned by M_event_timer_add()
484 * \param[in] interval_ms Time in milliseconds before the timer will expire.
485 * If specified as 0, will use the same interval_ms as the
486 * original M_event_timer_start() call (NOTE: this is different
487 * behavior than the value of 0 for M_event_timer_start())
488 *
489 * \return M_TRUE on success, M_FALSE on failure.
490 */
491M_API M_bool M_event_timer_reset(M_event_timer_t *timer, M_uint64 interval_ms);
492
493
494/*! Adjust the timer interval_ms.
495 *
496 * \see M_event_timer_reset will stop the timer and schedule it to start again in
497 * interval_ms in the future. Adjusting the time does not stop the timer. It is
498 * used to prevent timers from not being run if the interval_ms is constancy
499 * being adjusted.
500 *
501 * If the remaining time on the timer is > the new interval_ms the timer will
502 * be reset to run after the new interval_ms. If the timer has less time
503 * remaining than the new interval_ms it will be allowed to trigger after the
504 * remaining time and then be scheduled to run using the new interval_ms.
505 *
506 * \param[in] timer Timer handle returned by M_event_timer_add()
507 * \param[in] interval_ms Time in milliseconds before the timer will expire.
508 * 0 is considered an error.
509 *
510 * \return M_TRUE on success, M_FALSE on failure.
511 */
512M_API M_bool M_event_timer_adjust(M_event_timer_t *timer, M_uint64 interval_ms);
513
514
515/*! Set absolute time for first event to be fired.
516 *
517 * This will not take effect until the next call to M_event_timer_start() or M_event_timer_reset().
518 *
519 * \param[in] timer Timer handle returned by M_event_timer_add()
520 * \param[in] start_tv Absolute time of first event to be fired, or NULL to clear.
521 *
522 * \return M_TRUE on success, M_FALSE on failure
523 */
525
526
527/*! Set absolute time for when the timer will automatically stop
528 *
529 * \param[in] timer Timer handle returned by M_event_timer_add()
530 * \param[in] end_tv Absolute time of when to stop the timer, or NULL to clear.
531 *
532 * \return M_TRUE on success, M_FALSE on failure
533 */
535
536
537/*! Set the maximum number of times the timer should fire. Default is unlimited.
538 *
539 * \param[in] timer Timer handle returned by M_event_timer_add()
540 * \param[in] cnt Maximum number of times timer should fire. Use 0 for unlimited.
541 *
542 * \return M_TRUE on success, M_FALSE on failure
543 */
544M_API M_bool M_event_timer_set_firecount(M_event_timer_t *timer, size_t cnt);
545
546
547/*! Set the timer to automatically remove itself and free all used memory when the timer
548 * enters the stopped state. This will happen when exceeding the fire count, exceeding
549 * the configured end_tv or explicitly calling M_event_timer_stop().
550 *
551 * NOTE: Be careful not to attempt to use the timer handle once it has been autoremoved
552 * as it will result in access to uninitialized memory.
553 *
554 * \param[in] timer Timer handle returned by M_event_timer_add()
555 * \param[in] enabled M_TRUE to enable autoremove, M_FALSE to disable autoremove.
556 *
557 * \return M_TRUE on success, M_FALSE on failure.
558 */
559M_API M_bool M_event_timer_set_autoremove(M_event_timer_t *timer, M_bool enabled);
560
561/*! Timer modes of operation */
563 M_EVENT_TIMER_MODE_RELATIVE = 1, /*!< The interval will be added on to the end of the last actual run time */
564 M_EVENT_TIMER_MODE_MONOTONIC = 2 /*!< The interval will be added on to the last scheduled run time, even if that
565 * time has already passed. This means you could have events that run closer
566 * together than the specified interval if it is trying to "catch up" due to a
567 * long running event handler. In general this is more useful for needing an
568 * event to run as close to a certain interval as possible without skewing
569 * the interval between events by the amount of time it takes to handle event
570 * callbacks. */
572/*! Timer modes of operation */
574
575
576/*! Sets the timer mode of operation.
577 *
578 * \param[in] timer Timer handle returned by M_event_timer_add()
579 * \param[in] mode Defaults to M_EVENT_TIMER_MODE_RELATIVE if not specified.
580 *
581 * \return M_TRUE on success, M_FALSE on failure.
582 */
584
585
586/*! Retrieve number of milliseconds remaining on timer.
587 *
588 * \param[in] timer Timer handle returned by M_event_timer_add()
589 *
590 * \return Number of milliseconds remaining on timer, or 0 if stopped.
591 */
593
594
595/*! Retrieve the current millisecond interval the time is using.
596 *
597 * \param[in] timer Timer handle returned by M_event_timer_add()
598 *
599 * \return Number of milliseconds the timer is configured to use.
600 * Set from start, reset, or adjust.
601 */
603
604
605/*! Retrieves if the timer is active(started) or not.
606 *
607 * NOTE: Do not use with auto-destroy timers as the timer handle
608 * may not be valid if you don't already know the status.
609 *
610 * \param[in] timer Timer handle returned by M_event_timer_add()
611 *
612 * \return M_TRUE if timer is started, M_FALSE if timer is stopped.
613 */
615
616
617/*! Create a single-event timer.
618 *
619 * This is a convenience function equivalent to:
620 * M_event_timer_add(event, callback, cbdata) +
621 * M_event_timer_set_firecount(timer, 1) +
622 * M_event_timer_set_autoremove(timer, autoremove) +
623 * M_event_timer_start(timer, interval_ms)
624 *
625 * \param[in] event Event handle to add the timer to. If the event handle is a pool object,
626 * it will automatically distribute to an event thread.
627 * \param[in] interval_ms Time in milliseconds before the timer will expire.
628 * \param[in] autoremove Whether the timer should automatically remove itself when it fires.
629 * \param[in] callback User-specified callback to call when the timer expires
630 * \param[in] cb_data Optional. User-specified data supplied to user-specified callback when
631 * executed.
632 *
633 * \return Timer handle on success, NULL on failure.
634 */
635M_API M_event_timer_t *M_event_timer_oneshot(M_event_t *event, M_uint64 interval_ms, M_bool autoremove, M_event_callback_t callback, void *cb_data);
636
637
638/*! Remove the timer and free all memory used by the timer.
639 *
640 * If the timer isn't already stopped, this will prevent the timer from firing.
641 *
642 * \param[in] timer Timer handle returned by M_event_timer_add()
643 *
644 * \return M_TRUE on success, M_FALSE on failure.
645 */
647
648
649/*! Edit the callback associated with a timer object in the event subsystem.
650 *
651 * Editing allows a user to re-purpose a timer object while processing events without
652 * needing to remove and add a new object.
653 *
654 * \param[in] timer Timer handle returned by M_event_timer_add()
655 * \param[in] callback Callback to set.
656 * \param[in] cb_data Data passed to callback function. NULL will remove the cb_data.
657 *
658 * \return M_FALSE on error, such as if the callback is NULL.
659 */
660M_API M_bool M_event_timer_edit_cb(M_event_timer_t *timer, M_event_callback_t callback, void *cb_data);
661
662
663/*! Queue a task to run in the same thread as the event loop.
664 *
665 * This is threadsafe to call, and convenient when wanting to avoid
666 * additional locks when operating on an object in the event loop.
667 *
668 * This is currently implemented as a oneshot timer set for 0ms.
669 *
670 * \param[in] event Event handle to add task to. Does not make sense to hand an event
671 * pool object since the purpose is to choose the event loop to use.
672 * \param[in] callback User-specified callback to call
673 * \param[in] cb_data Optional. User-specified data supplied to user-specified callback when
674 * executed.
675 *
676 * \return M_TRUE on success, M_FALSE on failure.
677 */
678M_API M_bool M_event_queue_task(M_event_t *event, M_event_callback_t callback, void *cb_data);
679
680/*! Possible event status codes for an event loop or pool */
682 M_EVENT_STATUS_RUNNING = 0, /*!< The event loop is current running and processing events */
683 M_EVENT_STATUS_PAUSED = 1, /*!< The event loop is not running due to not being started or a timeout occurring */
684 M_EVENT_STATUS_RETURN = 2, /*!< The event loop was explicitly told to return using M_event_return() */
685 M_EVENT_STATUS_DONE = 3 /*!< The event loop either exited due to M_event_done() or there were no objects
686 * remaining as the event loop was initialized with M_EVENT_FLAG_EXITONEMPTY */
688
689/*! Possible event status codes for an event loop or pool */
691
692
693/*! Possible return codes for M_event_loop() */
695 M_EVENT_ERR_DONE = 1, /*!< The event loop either exited due to M_event_done() or M_event_done_with_disconnect()
696 * or there were no objects remaining as the event loop was initialized with
697 * M_EVENT_FLAG_EXITONEMPTY */
698 M_EVENT_ERR_TIMEOUT = 2, /*!< The timeout specified in M_event_loop() has expired */
699 M_EVENT_ERR_RETURN = 3, /*!< M_event_return() was explicitly called */
700 M_EVENT_ERR_MISUSE = 4 /*!< Misuse, e.g. NULL event handle */
702
703/*! Possible return codes for M_event_loop() */
705
706
707/*! Start the event loop to start processing events.
708 *
709 * Events will not be delivered unless the event loop is running. If the event
710 * handle is a pool, will spawn threads for each member of the pool except one
711 * which will run and block the thread executing this function.
712 *
713 * \param[in] event Initialized event handle
714 * \param[in] timeout_ms Time in milliseconds to wait for events. Use M_TIMEOUT_INF to
715 * wait until an explicit exit condition has been met, which is
716 * the recommended way to run the event loop.
717 *
718 * \return One of the M_event_err_t conditions.
719 */
720M_API M_event_err_t M_event_loop(M_event_t *event, M_uint64 timeout_ms);
721
722
723/*! Exit the event loop immediately.
724 *
725 * This is safe to call from a thread other than the event loop. Will set
726 * the M_EVENT_ERR_DONE return code for the event loop.
727 *
728 * This will exit all threads for event pools as well, and if an event child
729 * handle is passed instead of the pool handle, it will automatically escalate
730 * to the pool handle.
731 *
732 * This does not clean up the resources for the event loop and it is safe to
733 * re-execute the same event loop handle once it has returned.
734 *
735 * \param[in] event Initialized event handle
736 */
737M_API void M_event_done(M_event_t *event);
738
739
740/*! Exit the event loop immediately.
741 *
742 * This is safe to call from a thread other than the event loop. Will set
743 * the M_EVENT_ERR_RETURN return code for the event loop, this is the only
744 * way this call differs from M_event_done().
745 *
746 * This will exit all threads for event pools as well, and if an event child
747 * handle is passed instead of the pool handle, it will automatically escalate
748 * to the pool handle.
749 *
750 * This does not clean up the resources for the event loop and it is safe to
751 * re-execute the same event loop handle once it has returned.
752 *
753 * \param[in] event Initialized event handle
754 */
755M_API void M_event_return(M_event_t *event);
756
757
758/*! Signal all IO objects in the event loop to start their disconnect sequence
759 * and exit the event loop when all are closed, or the specified timeout
760 * has elapsed.
761 *
762 * This is safe to call from a thread other than the event loop. Will set
763 * the M_EVENT_ERR_DONE return code for the event loop. The only difference
764 * between this and M_event_done() is it attempts to close the IO objects
765 * gracefully, some users may want to use this for program termination.
766 *
767 * This will exit all threads for event pools as well, and if an event child
768 * handle is passed instead of the pool handle, it will automatically escalate
769 * to the pool handle.
770 *
771 * This does not clean up the resources for the event loop and it is safe to
772 * re-execute the same event loop handle once it has returned.
773 *
774 * \param[in] event Initialized event handle
775 * \param[in] timeout_before_disconnect_ms Number of milliseconds to wait for io objects to
776 * exit on their own before issuing a disconnect. May
777 * be set to 0 to immediately start a disconnect sequence
778 * on all IO objects.
779 * \param[in] disconnect_timeout_ms Number of milliseconds to wait on IO handles to close
780 * after issuing a disconnect, before giving up. This should
781 * be set to some reasonable number to accommodate for proper
782 * disconnect sequences. A good starting point may be 5s (5000ms).
783 */
784M_API void M_event_done_with_disconnect(M_event_t *event, M_uint64 timeout_before_disconnect_ms, M_uint64 disconnect_timeout_ms);
785
786
787/*! Get the current running status of the event loop.
788 *
789 * If an event child handle is passed instead of the pool handle, it will
790 * automatically escalate to the pool handle.
791 *
792 * \param[in] event Initialized event handle
793 *
794 * \return one of M_event_status_t results.
795 */
797
798
799/*! Retrieve the specified statistic.
800 *
801 * Will return results for the actual handle passed. If the handle is a child of
802 * an event pool, it will only return the child's processing time. If all processing
803 * time is desired, use M_event_get_pool() to get the pool handle before calling
804 * this function.
805 *
806 * \param[in] event Initialized event handle
807 * \param[in] type Type of statistic to return
808 *
809 * \return statistic as 64bit integer
810 */
812
813
814/*! Retrieve the number of M_io_t objects plus the number of M_event_timer_t objects
815 * associated with an event handle
816 *
817 * Will return results for the actual handle passed. If the handle is a child of
818 * an event pool, it will only return the child's processing time. If all processing
819 * time is desired, use M_event_get_pool() to get the pool handle before calling
820 * this function.
821 *
822 * \param[in] event Initialized event handle
823 *
824 * \return count of objects.
825 */
826M_API size_t M_event_num_objects(M_event_t *event);
827
828/*! Get human readable event type from M_event_type_t
829 *
830 * \param[in] type event type
831 * \return constant human readable string
832 */
833M_API const char *M_event_type_string(M_event_type_t type);
834
835/*! @} */
836
837__END_DECLS
838
839#endif
enum M_event_err M_event_err_t
Definition: m_event.h:704
enum M_event_timer_modes M_event_timer_mode_t
Definition: m_event.h:573
M_bool M_event_timer_set_autoremove(M_event_timer_t *timer, M_bool enabled)
M_bool M_event_timer_adjust(M_event_timer_t *timer, M_uint64 interval_ms)
M_bool M_event_timer_start(M_event_timer_t *timer, M_uint64 interval_ms)
M_event_status_t M_event_get_status(M_event_t *event)
M_event_err
Definition: m_event.h:694
void M_event_return(M_event_t *event)
M_event_timer_modes
Definition: m_event.h:562
M_event_t * M_event_pool_create(size_t max_threads)
void(* M_event_callback_t)(M_event_t *event, M_event_type_t type, M_io_t *io, void *cb_arg)
Definition: m_event.h:227
M_bool M_event_timer_remove(M_event_timer_t *timer)
M_event_trigger_t * M_event_trigger_add(M_event_t *event, M_event_callback_t callback, void *cb_data)
M_event_timer_t * M_event_timer_add(M_event_t *event, M_event_callback_t callback, void *cb_data)
void M_event_trigger_remove(M_event_trigger_t *trigger)
struct M_event_trigger M_event_trigger_t
Definition: m_event.h:196
M_event_type
Definition: m_event.h:172
void M_event_destroy(M_event_t *event)
M_event_timer_t * M_event_timer_oneshot(M_event_t *event, M_uint64 interval_ms, M_bool autoremove, M_event_callback_t callback, void *cb_data)
enum M_event_type M_event_type_t
Definition: m_event.h:189
M_uint64 M_event_timer_get_interval_ms(M_event_timer_t *timer)
M_event_t * M_io_get_event(M_io_t *io)
M_EVENT_FLAGS
Definition: m_event.h:231
struct M_event M_event_t
Definition: m_event.h:210
M_bool M_event_add(M_event_t *event, M_io_t *io, M_event_callback_t callback, void *cb_data)
M_bool M_event_timer_stop(M_event_timer_t *timer)
M_event_statistic_t
Definition: m_event.h:250
M_uint64 M_event_timer_get_remaining_ms(M_event_timer_t *timer)
M_bool M_event_timer_edit_cb(M_event_timer_t *timer, M_event_callback_t callback, void *cb_data)
void M_event_done(M_event_t *event)
M_event_t * M_event_get_pool(M_event_t *event)
M_bool M_event_timer_set_firecount(M_event_timer_t *timer, size_t cnt)
void M_event_remove(M_io_t *io)
size_t M_event_num_objects(M_event_t *event)
M_bool M_event_timer_set_mode(M_event_timer_t *timer, M_event_timer_mode_t mode)
M_bool M_event_timer_set_endtv(M_event_timer_t *timer, M_timeval_t *end_tv)
M_event_err_t M_event_loop(M_event_t *event, M_uint64 timeout_ms)
M_bool M_event_timer_get_status(M_event_timer_t *timer)
M_bool M_event_edit_io_cb(M_io_t *io, M_event_callback_t callback, void *cb_data)
M_bool M_event_timer_set_starttv(M_event_timer_t *timer, M_timeval_t *start_tv)
M_bool M_event_trigger_edit_cb(M_event_trigger_t *trigger, M_event_callback_t callback, void *cb_data)
M_event_callback_t M_event_get_io_cb(M_io_t *io, void **cb_data_out)
M_event_status
Definition: m_event.h:681
M_bool M_event_queue_task(M_event_t *event, M_event_callback_t callback, void *cb_data)
const char * M_event_type_string(M_event_type_t type)
M_event_t * M_event_create(M_uint32 flags)
void M_event_done_with_disconnect(M_event_t *event, M_uint64 timeout_before_disconnect_ms, M_uint64 disconnect_timeout_ms)
enum M_event_status M_event_status_t
Definition: m_event.h:690
struct M_event_timer M_event_timer_t
Definition: m_event.h:203
M_uint64 M_event_get_statistic(M_event_t *event, M_event_statistic_t type)
void M_event_trigger_signal(M_event_trigger_t *trigger)
M_bool M_event_timer_reset(M_event_timer_t *timer, M_uint64 interval_ms)
@ M_EVENT_ERR_TIMEOUT
Definition: m_event.h:698
@ M_EVENT_ERR_RETURN
Definition: m_event.h:699
@ M_EVENT_ERR_MISUSE
Definition: m_event.h:700
@ M_EVENT_ERR_DONE
Definition: m_event.h:695
@ M_EVENT_TIMER_MODE_MONOTONIC
Definition: m_event.h:564
@ M_EVENT_TIMER_MODE_RELATIVE
Definition: m_event.h:563
@ M_EVENT_TYPE_WRITE
Definition: m_event.h:184
@ M_EVENT_TYPE_ACCEPT
Definition: m_event.h:174
@ M_EVENT_TYPE_DISCONNECTED
Definition: m_event.h:176
@ M_EVENT_TYPE_OTHER
Definition: m_event.h:185
@ M_EVENT_TYPE_READ
Definition: m_event.h:175
@ M_EVENT_TYPE_CONNECTED
Definition: m_event.h:173
@ M_EVENT_TYPE_ERROR
Definition: m_event.h:181
@ M_EVENT_FLAG_EXITONEMPTY
Definition: m_event.h:236
@ M_EVENT_FLAG_NOWAKE
Definition: m_event.h:233
@ M_EVENT_FLAG_NON_SCALABLE
Definition: m_event.h:238
@ M_EVENT_FLAG_NONE
Definition: m_event.h:232
@ M_EVENT_FLAG_EXITONEMPTY_NOTIMERS
Definition: m_event.h:237
@ M_EVENT_STATISTIC_SOFTEVENT_COUNT
Definition: m_event.h:253
@ M_EVENT_STATISTIC_TIMER_COUNT
Definition: m_event.h:254
@ M_EVENT_STATISTIC_WAKE_COUNT
Definition: m_event.h:251
@ M_EVENT_STATISTIC_PROCESS_TIME_MS
Definition: m_event.h:255
@ M_EVENT_STATISTIC_OSEVENT_COUNT
Definition: m_event.h:252
@ M_EVENT_STATUS_RETURN
Definition: m_event.h:684
@ M_EVENT_STATUS_PAUSED
Definition: m_event.h:683
@ M_EVENT_STATUS_DONE
Definition: m_event.h:685
@ M_EVENT_STATUS_RUNNING
Definition: m_event.h:682
struct M_io M_io_t
Definition: m_io.h:59
Definition: m_time.h:187