EM-ODP
3.7.0
Event Machine on ODP
|
Event Machine fork-join helper. More...
Functions | |
em_event_group_t | em_event_group_create (void) |
em_status_t | em_event_group_delete (em_event_group_t event_group) |
em_status_t | em_event_group_apply (em_event_group_t event_group, int count, int num_notif, const em_notif_t notif_tbl[]) |
em_status_t | em_event_group_increment (int count) |
int | em_event_group_is_ready (em_event_group_t event_group) |
em_event_group_t | em_event_group_current (void) |
em_status_t | em_send_group (em_event_t event, em_queue_t queue, em_event_group_t event_group) |
int | em_send_group_multi (const em_event_t events[], int num, em_queue_t queue, em_event_group_t event_group) |
void | em_event_group_processing_end (void) |
em_status_t | em_event_group_assign (em_event_group_t event_group) |
em_status_t | em_event_group_abort (em_event_group_t event_group) |
int | em_event_group_get_notif (em_event_group_t event_group, int max_notif, em_notif_t notif_tbl[]) |
em_event_group_t | em_event_group_get_first (unsigned int *num) |
em_event_group_t | em_event_group_get_next (void) |
uint64_t | em_event_group_to_u64 (em_event_group_t event_group) |
Event Machine fork-join helper.
An event group can be used to trigger a join of parallel operations in the form of notification events. The number of parallel operations needs to be known in advance by the event group creator, but the separate event handlers don't necessarily need to know anything about the other related events. An event group is functionally a shared atomic counter decremented when each related event has been handled (EO-receive() returns). The notification events are automatically sent once the count reaches zero.
There are two separate main usage patterns:
From an application (EO) point of view, an event group can get activated either by entering the EO receive with an event tagged to an event group or by explicitly calling em_event_group_assign. The current event group is core local and only one event group can be active (current) at a time. Assigning a received event that already is tagged to an event group, e.g. sent with em_send_group(), is not allowed unless the event group is deactivated first with em_event_group_processing_end(). The current event group gets deactivated by exiting the EO receive function or by explicitly calling em_event_group_processing_end(). Deactivation means the count of the event group is decremented and if the count reaches zero the notification events are sent. The current event group is local to a core (dispatcher) and exists only within the EO receive function.
Note, that event groups may only work with events that are to be handled by an EO, i.e. SW events.
OpenEM implementation should internally use a generation count or other technique to make sure that em_event_group_abort() can stop a problem propagation, i.e. after a group is aborted (and applied a new count) any potential delayed event(s) from the previous cycle will not cause the new count to be decremented. The same should be valid for excess group events, i.e. when sending more than the applied count. To make it possible for the application to properly handle such problems, the implementation should pre-check incoming events and call error handler before giving the event to an EO. This makes it possible for the application to choose whether to drop those events (at the error handler) or let them be processed.
It is not allowed to use event references with event groups since assigning an event that has references to an event group would assign all the references to the event group resulting in undefined behaviour. E.g. using em_send_group()/em_send_group_multi() to send a reference is wrong.
em_status_t em_event_group_abort | ( | em_event_group_t | event_group | ) |
Abort the ongoing event group.
This is a recovery operation to abort an ongoing event group in case it does not get completed. This will reset the group back to a state ready for a new apply. Note, that there is a potential race as the group could get completed on another thread while executing this (e.g. a delayed event is finally received and processed). Implementation will synchronize internal state changes, but this call may succeed or fail depending on timing so abort should be done with care for recovery purpose only.
Notification events related to the ongoing (to be aborted) cycle can be managed as follows 1) save possible related notifications using em_event_group_get_notif() 2) call em_event_group_abort() 3) IF em_event_group_abort() returns EM_OK the operation was successfully completed meaning the earlier notifications will not be sent thus the saved notifications can be freed or re-used. Otherwise the call was made too late and the saved notifications must not be touched as they are to be sent.
This means the synchronization point is em_event_group_abort(), not em_event_group_get_notif() which might return notifications that will still be sent.
event_group | Event group to abort and reset |
Definition at line 685 of file event_machine_event_group.c.
em_status_t em_event_group_apply | ( | em_event_group_t | event_group, |
int | count, | ||
int | num_notif, | ||
const em_notif_t | notif_tbl[] | ||
) |
Apply event group configuration.
This function sets the event count and notification parameters for the event group. After it returns, events sent or assigned to the event group are counted against the current count value. Notification events are sent when all (counted) events have been processed (count is decremented at EO receive return or by calling em_event_group_processing_end()). A new apply call is needed to re-use the event group for another cycle (with a new count and notifications).
Notification events can optionally be sent to/tagged with another event group but not with the same event group that triggered the notifications, see em_notif_t for more.
Apply should only be called once per group cycle.
event_group | Event group |
count | Number of events in the group (positive integer) |
num_notif | Number of notification events to send |
notif_tbl | Table of notifications (events and target queues) |
Definition at line 93 of file event_machine_event_group.c.
em_status_t em_event_group_assign | ( | em_event_group_t | event_group | ) |
Assign core local current event group.
The assign functionality can be used to set the core local current event group. The event group handling after the assign call is identical to the handling of an event group that was originally set by sending an event tagged to that event group, i.e. the core local current event group is active and will be operated on in a normal way. Assign will fail if there already is an active current event group, i.e. only one event group can be active at a time (per core).
This needs to be used with care, i.e. match the amount of events applied and assigned.
event_group | An applied event group to assign to |
Definition at line 644 of file event_machine_event_group.c.
em_event_group_t em_event_group_create | ( | void | ) |
Create a new event group for fork-join.
The amount of simultaneous event groups can be limited.
Definition at line 37 of file event_machine_event_group.c.
em_event_group_t em_event_group_current | ( | void | ) |
Return the currently active event group.
Returns the current event group or EM_EVENT_GROUP_UNDEF if an event group is not active (i.e. never activated or deactivated using em_event_group_processing_end()).
Can only be used within an EO receive function.
Definition at line 245 of file event_machine_event_group.c.
em_status_t em_event_group_delete | ( | em_event_group_t | event_group | ) |
Delete (unallocate) an event group.
An event group must not be deleted before it has been completed (count reached zero) or aborted. A created but never applied event group can be deleted.
event_group | Event group to delete |
Definition at line 57 of file event_machine_event_group.c.
em_event_group_t em_event_group_get_first | ( | unsigned int * | num | ) |
Initialize event group iteration and return the first event group handle.
Can be used to initialize the iteration to retrieve all created event groups for debugging or management purposes. Use em_event_group_get_next() after this call until it returns EM_EVENT_GROUP_UNDEF. A new call to em_event_group_get_first() resets the iteration, which is maintained per core (thread). The operation should be completed in one go before returning from the EO's event receive function (or start/stop).
The number of event groups (output arg 'num') may not match the amount of event groups actually returned by iterating using em_event_group_get_next() if event groups are added or removed in parallel by another core. The order of the returned event group handles is undefined.
[out] | num | Pointer to an unsigned int to store the amount of event groups into |
Definition at line 782 of file event_machine_event_group.c.
em_event_group_t em_event_group_get_next | ( | void | ) |
Return the next event group handle.
Continues the event group iteration started by em_event_group_get_first() and returns the next event group handle.
Definition at line 811 of file event_machine_event_group.c.
int em_event_group_get_notif | ( | em_event_group_t | event_group, |
int | max_notif, | ||
em_notif_t | notif_tbl[] | ||
) |
Return notification events currently related to an applied event group.
This returns the current notifications or none (0) if they were already sent (event group completed).
event_group | Event group | |
max_notif | Maximum number of notifications to return | |
[out] | notif_tbl | Table for notifications to fill |
Definition at line 735 of file event_machine_event_group.c.
em_status_t em_event_group_increment | ( | int | count | ) |
Increment the current event group count.
Increments the event count of the currently active event group (received or assigned event). Enables sending new events into the current event group. The event count cannot be decremented and this will fail if there is no current event group.
count | Number of events to add to the event group (positive integer) |
Definition at line 151 of file event_machine_event_group.c.
int em_event_group_is_ready | ( | em_event_group_t | event_group | ) |
Checks if the event group is ready for 'apply'.
Returns EM_TRUE (1) if the given event group is ready, i.e. the user can do em_event_group_apply() again. A better alternative to this is to use a related notification event to re-use the event group (apply can always be used when handling a notification event from the event group).
An event group that has been applied a count but no events sent is not considered 'ready for apply'. If a change is needed the group has to be aborted and then re-applied.
Return value EM_TRUE does not guarantee all notifications are received nor handled, but the event group count has reached zero and the event group is ready for a new apply.
event_group | Event group |
Definition at line 212 of file event_machine_event_group.c.
void em_event_group_processing_end | ( | void | ) |
Signal early end of processing of the current event group
This is an optional call that can be used to move the implicit event group handling (decrementing the count) from exiting event receive function to the point of this call - the current event group count is decremented immediately and if it reaches zero the notifications are also sent. In that case the group will be ready for a new apply after this returns.
This impacts the current event group the same way whether it was activated by receiving a tagged event or EO called em_event_group_assign().
This call does not change potential atomicity or ordering for the current event and is a no-operation if called while an event group is not active (no current group).
Can only be used within the EO receive function.
Definition at line 625 of file event_machine_event_group.c.
uint64_t em_event_group_to_u64 | ( | em_event_group_t | event_group | ) |
Convert an event group handle to an unsigned integer
event_group | Event group handle to be converted |
Definition at line 834 of file event_machine_event_group.c.
em_status_t em_send_group | ( | em_event_t | event, |
em_queue_t | queue, | ||
em_event_group_t | event_group | ||
) |
Send event associated with/tagged to an event group.
Any valid event and destination queue parameters can be used. The event group indicates which event group the event is tagged to. The event group has to first be created and applied a count. One should always send the correct amount of events to an event group, i.e. matching the applied count.
Event group is not supported with unscheduled queues.
It is not allowed to use event references with event groups since assigning an event that has references to an event group would assign all the references to the event group resulting in undefined behaviour. E.g. using em_send_group() to send a reference is wrong.
event | Event to send |
queue | Destination queue |
event_group | Event group |
Definition at line 474 of file event_machine_event_group.c.
int em_send_group_multi | ( | const em_event_t | events[], |
int | num, | ||
em_queue_t | queue, | ||
em_event_group_t | event_group | ||
) |
Send multiple events associated with/tagged to an event group.
This is like em_send_group, but multiple events can be sent with one call for potential performance gain. The call returns the number of events actually sent. A return value equal to 'num' means that all events were sent. A value less than 'num' means the events at the end of the given event list were not sent and must be handled by the application. The function will not modify the given list of events.
Event group is not supported with unscheduled queues.
It is not allowed to use event references with event groups since assigning an event that has references to an event group would assign all the references to the event group resulting in undefined behaviour. E.g. using em_send_group_multi() to send references is wrong.
events | List of events to send (i.e. ptr to array of events) |
num | Number of events |
queue | Destination queue |
event_group | Event group |
Definition at line 556 of file event_machine_event_group.c.