Mstdlib-1.24.0
|
Typedefs | |
typedef enum M_event_type | M_event_type_t |
typedef struct M_event_trigger | M_event_trigger_t |
typedef struct M_event_timer | M_event_timer_t |
typedef struct M_event | M_event_t |
typedef void(* | M_event_callback_t) (M_event_t *event, M_event_type_t type, M_io_t *io, void *cb_arg) |
typedef enum M_event_timer_modes | M_event_timer_mode_t |
typedef enum M_event_status | M_event_status_t |
typedef enum M_event_err | M_event_err_t |
Enumerations | |
enum | M_event_type { M_EVENT_TYPE_CONNECTED = 0 , M_EVENT_TYPE_ACCEPT , M_EVENT_TYPE_READ , M_EVENT_TYPE_DISCONNECTED , M_EVENT_TYPE_ERROR , M_EVENT_TYPE_WRITE , M_EVENT_TYPE_OTHER } |
enum | M_EVENT_FLAGS { M_EVENT_FLAG_NONE = 0 , M_EVENT_FLAG_NOWAKE = 1 << 0 , M_EVENT_FLAG_EXITONEMPTY = 1 << 1 , M_EVENT_FLAG_EXITONEMPTY_NOTIMERS = 1 << 2 , M_EVENT_FLAG_NON_SCALABLE = 1 << 3 } |
enum | M_event_statistic_t { M_EVENT_STATISTIC_WAKE_COUNT , M_EVENT_STATISTIC_OSEVENT_COUNT , M_EVENT_STATISTIC_SOFTEVENT_COUNT , M_EVENT_STATISTIC_TIMER_COUNT , M_EVENT_STATISTIC_PROCESS_TIME_MS } |
enum | M_event_timer_modes { M_EVENT_TIMER_MODE_RELATIVE = 1 , M_EVENT_TIMER_MODE_MONOTONIC = 2 } |
enum | M_event_status { M_EVENT_STATUS_RUNNING = 0 , M_EVENT_STATUS_PAUSED = 1 , M_EVENT_STATUS_RETURN = 2 , M_EVENT_STATUS_DONE = 3 } |
enum | M_event_err { M_EVENT_ERR_DONE = 1 , M_EVENT_ERR_TIMEOUT = 2 , M_EVENT_ERR_RETURN = 3 , M_EVENT_ERR_MISUSE = 4 } |
Cross platform event based processing. A platform specific backend will be used as the underlying event system but all events will be exposed though this interface. No platform specific knowledge is needed.
Developers used to working with macOS event loop style of programming can use this event system to use that paradigm on other platforms. In this scenario most events would be triggered as OTHER. Some sort of tracking would be necessary to determine why an event was triggered if the same callback is used for multiple situations.
The event system is thread safe allowing io objects and times can be added to and moved between different event loops running on different threads. Triggers can be triggered from different threads. Destruction of an io object from a different thread will be queued in the event loop it's running on.
Note: the CONNECTED event will be triggered when a io object is added to an event loop using M_event_add().
Example application that demonstrates read/write events, timers, and queued tasks.
typedef enum M_event_type M_event_type_t |
Events that can be generated.
typedef struct M_event_trigger M_event_trigger_t |
Handle for an event trigger
typedef struct M_event_timer M_event_timer_t |
Handle for an event timer
typedef struct M_event M_event_t |
typedef void(* M_event_callback_t) (M_event_t *event, M_event_type_t type, M_io_t *io, void *cb_arg) |
Definition for a function callback that is called every time an event is triggered by the event subsystem.
[in] | event | Internal event object, this is an event-thread specific object which could be the member of a pool. This object may be used to add new events to the same event thread, or M_event_get_pool() can be used to retrieve the master pool handle for distributing events across threads. |
[in] | type | The type of event that has been triggered, see M_event_type_t. Always M_EVENT_TYPE_OTHER for trigger, timer, and queued tasks. |
[in] | io | Pointer to the M_io_t object associated with the event, or NULL for trigger, timer, and queued tasks. |
[in] | cb_arg | User-specified callback argument registered when the object was added to the event handle. |
typedef enum M_event_timer_modes M_event_timer_mode_t |
Timer modes of operation
typedef enum M_event_status M_event_status_t |
Possible event status codes for an event loop or pool
typedef enum M_event_err M_event_err_t |
Possible return codes for M_event_loop()
enum M_event_type |
Events that can be generated.
Events are enumerated in priority of delivery order
enum M_EVENT_FLAGS |
Possible list of flags that can be used when initializing an event loop
enum M_event_statistic_t |
Possible values to pass to M_event_get_statistic()
enum M_event_timer_modes |
Timer modes of operation
enum M_event_status |
Possible event status codes for an event loop or pool
Enumerator | |
---|---|
M_EVENT_STATUS_RUNNING | The event loop is current running and processing events |
M_EVENT_STATUS_PAUSED | The event loop is not running due to not being started or a timeout occurring |
M_EVENT_STATUS_RETURN | The event loop was explicitly told to return using M_event_return() |
M_EVENT_STATUS_DONE | The event loop either exited due to M_event_done() or there were no objects remaining as the event loop was initialized with M_EVENT_FLAG_EXITONEMPTY |
enum M_event_err |
Possible return codes for M_event_loop()
Enumerator | |
---|---|
M_EVENT_ERR_DONE | The event loop either exited due to M_event_done() or M_event_done_with_disconnect() or there were no objects remaining as the event loop was initialized with M_EVENT_FLAG_EXITONEMPTY |
M_EVENT_ERR_TIMEOUT | The timeout specified in M_event_loop() has expired |
M_EVENT_ERR_RETURN | M_event_return() was explicitly called |
M_EVENT_ERR_MISUSE | Misuse, e.g. NULL event handle |
M_event_t * M_event_create | ( | M_uint32 | flags | ) |
Create a base event loop object.
An event loop is typically run in the main process thread and will block until process termination. IO and timer objects are enqueued into the event loop and dispatched within the event loop. Event loops are more efficient and scalable than using a thread per tracked io object.
[in] | flags | One or more enum M_EVENT_FLAGS |
M_event_t * M_event_pool_create | ( | size_t | max_threads | ) |
Create a pool of M_event_t objects bound to a master pool handle to distribute load of event handling across multiple threads.
One thread per CPU core will be created for handling events, up to the maximum specified during creationg of the pool. When an object is added to the event pool handle, an internal search is performed, and the least-loaded thread will receive the new object.
Objects bound to the same internal event object will always execute in the same thread which may be desirable for co-joined objects (otherwise additional locking may be required since multiple events could fire from different threads for some shared resource). Typically this co-joined objects will be created based on events that have been fired, so the M_event_t object returned from the M_event_callback_t callback should be used to ensure they stay co-joined.
For non co-joined objects, always ensure the event handle used is the pool by calling M_event_get_pool() otherwise load will not be distributed at all.
[in] | max_threads | Artificial limitation on the maximum number of threads, the actual number of threads will be the lesser of this value and the number of cpu cores in the system. Use 0 for this value to simply use the number of cpu cores. |
Retrieve the distributed pool handle for balancing the load across an event pool, or self if not part of a pool.
This should be called to get the event handle during M_event_add(), M_event_trigger_add(), M_event_timer_add(), M_event_timer_oneshot(), or M_event_queue_task() as by default tasks will otherwise not be distributed if using the event handle returned by the M_event_callback_t. In some cases it is desirable to ensure co-joined objects run within the same event thread and therefore desirable to enqueue multiple tasks for an internal event loop handle rather than the distributed pool.
[in] | event | Pointer to event handle either returned by M_event_create(), M_event_pool_create(), or from an M_event_callback_t. |
Get the registered event handle for the io object
[in] | io | IO object. |
void M_event_destroy | ( | M_event_t * | event | ) |
Destroy the event loop or pool object
[in] | event | Pointer to event handle either returned by M_event_create(), M_event_pool_create(), or from an M_event_callback_t. |
M_bool M_event_add | ( | M_event_t * | event, |
M_io_t * | io, | ||
M_event_callback_t | callback, | ||
void * | cb_data | ||
) |
Add an io object to the event loop handle with a registered callback to deliver events to.
Adding handles to an event handle is threadsafe and can be executed either within an event callback or from a separate thread.
[in] | event | Event handle to add the event to. If desirable to ensure this io object is distributed across a pool, it is recommended to pass the return value of M_event_get_pool() rather than the event handle returned by an M_event_callback_t callback. |
[in] | io | IO object to bind to the event handle. |
[in] | callback | Callback to be called when events occur. |
[in] | cb_data | Optional. User-defined callback data that will be passed to the user-defined callback. Use NULL if no data is necessary. |
M_bool M_event_edit_io_cb | ( | M_io_t * | io, |
M_event_callback_t | callback, | ||
void * | cb_data | ||
) |
Edit the callback associated with an io object in the event subsystem.
Editing allows a user to re-purpose an io object while processing events without needing to remove and re-add the object which may cause a loss of events.
[in] | io | IO object to modify the callback for |
[in] | callback | Callback to set. NULL will set it to no callback. |
[in] | cb_data | Data passed to callback function. NULL will remove the cb_data. |
M_event_callback_t M_event_get_io_cb | ( | M_io_t * | io, |
void ** | cb_data_out | ||
) |
Retrieve the callback associated with an io object in the event subsystem.
[in] | io | IO object to modify the callback for |
[out] | cb_data_out | Pointer to store callback data registered with callback. |
void M_event_remove | ( | M_io_t * | io | ) |
Remove an io object from its associated event handle.
Removing handles is threadsafe and can be executed either within an event callback or from a separate thread.
[in] | io | IO object. |
M_event_trigger_t * M_event_trigger_add | ( | M_event_t * | event, |
M_event_callback_t | callback, | ||
void * | cb_data | ||
) |
Create a user-callable trigger which will call the pre-registered callback. Useful for cross-thread completion or status update notifications. Triggering events is threadsafe.
[in] | event | Event handle to add the event to. If desirable to ensure this io object is distributed across a pool, it is recommended to pass the return value of M_event_get_pool() rather than the event handle returned by an M_event_callback_t callback. |
[in] | callback | Callback to be called when the trigger is called. |
[in] | cb_data | Optional. User-defined callback data that will be passed to the user-defined callback. Use NULL if no data is necessary. |
void M_event_trigger_remove | ( | M_event_trigger_t * | trigger | ) |
Remove the user-callable trigger, once removed, the trigger is no longer valid and cannot be called.
[in] | trigger | Trigger returned from M_event_trigger_add() |
M_bool M_event_trigger_edit_cb | ( | M_event_trigger_t * | trigger, |
M_event_callback_t | callback, | ||
void * | cb_data | ||
) |
Edit the callback associated with a trigger object in the event subsystem.
Editing allows a user to re-purpose a timer object while processing events without needing to remove and add a new object.
[in] | trigger | Trigger returned from M_event_trigger_add() |
[in] | callback | Callback to set. |
[in] | cb_data | Data passed to callback function. NULL will remove the cb_data. |
void M_event_trigger_signal | ( | M_event_trigger_t * | trigger | ) |
Signal the registered callback associated with the trigger to be called. This is threadsafe and may be called cross thread. If multiple signals are delivered before the callback is called, the duplicate signals will be silently discarded.
[in] | trigger | Trigger returned from M_event_trigger_add() |
M_event_timer_t * M_event_timer_add | ( | M_event_t * | event, |
M_event_callback_t | callback, | ||
void * | cb_data | ||
) |
Add a timer object to the event loop specified that will call the user-supplied callback when the timer expires. The timer is created in a stopped state and must be started before it will fire.
If the timer is associated with another object (e.g. co-joined) then the same event handle as the other object should be used.
[in] | event | Event handle to add the timer to. If the event handle is a pool object, it will automatically distribute to an event thread. |
[in] | callback | User-specified callback to call when the timer expires |
[in] | cb_data | Optional. User-specified data supplied to user-specified callback when executed. |
M_bool M_event_timer_start | ( | M_event_timer_t * | timer, |
M_uint64 | interval_ms | ||
) |
Starts the specified timer with timeout specified. When the timeout expires, the callback associated with the timer will be executed.
[in] | timer | Timer handle returned by M_event_timer_add() |
[in] | interval_ms | Time in milliseconds before the timer will expire. May only be 0 if the configured "firecount" is 1. |
M_bool M_event_timer_stop | ( | M_event_timer_t * | timer | ) |
Stops the specified timer.
[in] | timer | Timer handle returned by M_event_timer_add() |
M_bool M_event_timer_reset | ( | M_event_timer_t * | timer, |
M_uint64 | interval_ms | ||
) |
Restart the timer.
If the timer is already stopped, will simply start it again. If the timer has "autoremove" configured, the removal will be skipped on stop.
[in] | timer | Timer handle returned by M_event_timer_add() |
[in] | interval_ms | Time in milliseconds before the timer will expire. If specified as 0, will use the same interval_ms as the original M_event_timer_start() call (NOTE: this is different behavior than the value of 0 for M_event_timer_start()) |
M_bool M_event_timer_adjust | ( | M_event_timer_t * | timer, |
M_uint64 | interval_ms | ||
) |
Adjust the timer interval_ms.
If the remaining time on the timer is > the new interval_ms the timer will be reset to run after the new interval_ms. If the timer has less time remaining than the new interval_ms it will be allowed to trigger after the remaining time and then be scheduled to run using the new interval_ms.
[in] | timer | Timer handle returned by M_event_timer_add() |
[in] | interval_ms | Time in milliseconds before the timer will expire. 0 is considered an error. |
M_bool M_event_timer_set_starttv | ( | M_event_timer_t * | timer, |
M_timeval_t * | start_tv | ||
) |
Set absolute time for first event to be fired.
This will not take effect until the next call to M_event_timer_start() or M_event_timer_reset().
[in] | timer | Timer handle returned by M_event_timer_add() |
[in] | start_tv | Absolute time of first event to be fired, or NULL to clear. |
M_bool M_event_timer_set_endtv | ( | M_event_timer_t * | timer, |
M_timeval_t * | end_tv | ||
) |
Set absolute time for when the timer will automatically stop
[in] | timer | Timer handle returned by M_event_timer_add() |
[in] | end_tv | Absolute time of when to stop the timer, or NULL to clear. |
M_bool M_event_timer_set_firecount | ( | M_event_timer_t * | timer, |
size_t | cnt | ||
) |
Set the maximum number of times the timer should fire. Default is unlimited.
[in] | timer | Timer handle returned by M_event_timer_add() |
[in] | cnt | Maximum number of times timer should fire. Use 0 for unlimited. |
M_bool M_event_timer_set_autoremove | ( | M_event_timer_t * | timer, |
M_bool | enabled | ||
) |
Set the timer to automatically remove itself and free all used memory when the timer enters the stopped state. This will happen when exceeding the fire count, exceeding the configured end_tv or explicitly calling M_event_timer_stop().
NOTE: Be careful not to attempt to use the timer handle once it has been autoremoved as it will result in access to uninitialized memory.
[in] | timer | Timer handle returned by M_event_timer_add() |
[in] | enabled | M_TRUE to enable autoremove, M_FALSE to disable autoremove. |
M_bool M_event_timer_set_mode | ( | M_event_timer_t * | timer, |
M_event_timer_mode_t | mode | ||
) |
Sets the timer mode of operation.
[in] | timer | Timer handle returned by M_event_timer_add() |
[in] | mode | Defaults to M_EVENT_TIMER_MODE_RELATIVE if not specified. |
M_uint64 M_event_timer_get_remaining_ms | ( | M_event_timer_t * | timer | ) |
Retrieve number of milliseconds remaining on timer.
[in] | timer | Timer handle returned by M_event_timer_add() |
M_uint64 M_event_timer_get_interval_ms | ( | M_event_timer_t * | timer | ) |
Retrieve the current millisecond interval the time is using.
[in] | timer | Timer handle returned by M_event_timer_add() |
M_bool M_event_timer_get_status | ( | M_event_timer_t * | timer | ) |
Retrieves if the timer is active(started) or not.
NOTE: Do not use with auto-destroy timers as the timer handle may not be valid if you don't already know the status.
[in] | timer | Timer handle returned by M_event_timer_add() |
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 | ||
) |
Create a single-event timer.
This is a convenience function equivalent to: M_event_timer_add(event, callback, cbdata) + M_event_timer_set_firecount(timer, 1) + M_event_timer_set_autoremove(timer, autoremove) + M_event_timer_start(timer, interval_ms)
[in] | event | Event handle to add the timer to. If the event handle is a pool object, it will automatically distribute to an event thread. |
[in] | interval_ms | Time in milliseconds before the timer will expire. |
[in] | autoremove | Whether the timer should automatically remove itself when it fires. |
[in] | callback | User-specified callback to call when the timer expires |
[in] | cb_data | Optional. User-specified data supplied to user-specified callback when executed. |
M_bool M_event_timer_remove | ( | M_event_timer_t * | timer | ) |
Remove the timer and free all memory used by the timer.
If the timer isn't already stopped, this will prevent the timer from firing.
[in] | timer | Timer handle returned by M_event_timer_add() |
M_bool M_event_timer_edit_cb | ( | M_event_timer_t * | timer, |
M_event_callback_t | callback, | ||
void * | cb_data | ||
) |
Edit the callback associated with a timer object in the event subsystem.
Editing allows a user to re-purpose a timer object while processing events without needing to remove and add a new object.
[in] | timer | Timer handle returned by M_event_timer_add() |
[in] | callback | Callback to set. |
[in] | cb_data | Data passed to callback function. NULL will remove the cb_data. |
M_bool M_event_queue_task | ( | M_event_t * | event, |
M_event_callback_t | callback, | ||
void * | cb_data | ||
) |
Queue a task to run in the same thread as the event loop.
This is threadsafe to call, and convenient when wanting to avoid additional locks when operating on an object in the event loop.
This is currently implemented as a oneshot timer set for 0ms.
[in] | event | Event handle to add task to. Does not make sense to hand an event pool object since the purpose is to choose the event loop to use. |
[in] | callback | User-specified callback to call |
[in] | cb_data | Optional. User-specified data supplied to user-specified callback when executed. |
M_event_err_t M_event_loop | ( | M_event_t * | event, |
M_uint64 | timeout_ms | ||
) |
Start the event loop to start processing events.
Events will not be delivered unless the event loop is running. If the event handle is a pool, will spawn threads for each member of the pool except one which will run and block the thread executing this function.
[in] | event | Initialized event handle |
[in] | timeout_ms | Time in milliseconds to wait for events. Use M_TIMEOUT_INF to wait until an explicit exit condition has been met, which is the recommended way to run the event loop. |
void M_event_done | ( | M_event_t * | event | ) |
Exit the event loop immediately.
This is safe to call from a thread other than the event loop. Will set the M_EVENT_ERR_DONE return code for the event loop.
This will exit all threads for event pools as well, and if an event child handle is passed instead of the pool handle, it will automatically escalate to the pool handle.
This does not clean up the resources for the event loop and it is safe to re-execute the same event loop handle once it has returned.
[in] | event | Initialized event handle |
void M_event_return | ( | M_event_t * | event | ) |
Exit the event loop immediately.
This is safe to call from a thread other than the event loop. Will set the M_EVENT_ERR_RETURN return code for the event loop, this is the only way this call differs from M_event_done().
This will exit all threads for event pools as well, and if an event child handle is passed instead of the pool handle, it will automatically escalate to the pool handle.
This does not clean up the resources for the event loop and it is safe to re-execute the same event loop handle once it has returned.
[in] | event | Initialized event handle |
void M_event_done_with_disconnect | ( | M_event_t * | event, |
M_uint64 | timeout_before_disconnect_ms, | ||
M_uint64 | disconnect_timeout_ms | ||
) |
Signal all IO objects in the event loop to start their disconnect sequence and exit the event loop when all are closed, or the specified timeout has elapsed.
This is safe to call from a thread other than the event loop. Will set the M_EVENT_ERR_DONE return code for the event loop. The only difference between this and M_event_done() is it attempts to close the IO objects gracefully, some users may want to use this for program termination.
This will exit all threads for event pools as well, and if an event child handle is passed instead of the pool handle, it will automatically escalate to the pool handle.
This does not clean up the resources for the event loop and it is safe to re-execute the same event loop handle once it has returned.
[in] | event | Initialized event handle |
[in] | timeout_before_disconnect_ms | Number of milliseconds to wait for io objects to exit on their own before issuing a disconnect. May be set to 0 to immediately start a disconnect sequence on all IO objects. |
[in] | disconnect_timeout_ms | Number of milliseconds to wait on IO handles to close after issuing a disconnect, before giving up. This should be set to some reasonable number to accommodate for proper disconnect sequences. A good starting point may be 5s (5000ms). |
M_event_status_t M_event_get_status | ( | M_event_t * | event | ) |
Get the current running status of the event loop.
If an event child handle is passed instead of the pool handle, it will automatically escalate to the pool handle.
[in] | event | Initialized event handle |
M_uint64 M_event_get_statistic | ( | M_event_t * | event, |
M_event_statistic_t | type | ||
) |
Retrieve the specified statistic.
Will return results for the actual handle passed. If the handle is a child of an event pool, it will only return the child's processing time. If all processing time is desired, use M_event_get_pool() to get the pool handle before calling this function.
[in] | event | Initialized event handle |
[in] | type | Type of statistic to return |
size_t M_event_num_objects | ( | M_event_t * | event | ) |
Retrieve the number of M_io_t objects plus the number of M_event_timer_t objects associated with an event handle
Will return results for the actual handle passed. If the handle is a child of an event pool, it will only return the child's processing time. If all processing time is desired, use M_event_get_pool() to get the pool handle before calling this function.
[in] | event | Initialized event handle |
const char * M_event_type_string | ( | M_event_type_t | type | ) |
Get human readable event type from M_event_type_t
[in] | type | event type |