EM-ODP  3.7.0
Event Machine on ODP
Event group

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)
 

Detailed Description

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:

Sender originated (original):

  1. an event group is allocated with em_event_group_create().
  2. the number of parallel events and the notifications are set with em_event_group_apply().
  3. the (parallel) events are sent normally but using em_send_group() instead of em_send(). This tags the event with the given event group.
  4. once received by a core the tag is used to switch core specific current event group to the one in the tag. The receiver EO handles the event normally (does not see any difference).
  5. as the receive function returns the count of the current event group is decremented. If the count reaches zero (last event) the related notification event(s) are sent automatically and can trigger the next operation for the application.
  6. the sequence can continue from step 2 for a new set of events if the event group is to be reused.

Receiver originated (API 1.2):

  1. an event group is created with em_event_group_create().
  2. the number of parallel events and the notifications are set with em_event_group_apply().
  3. during the processing of any received event that is not already tagged to belong to an event group, em_event_group_assign() can be used to set the current event group (a core local value). The rest is then equivalent to as if the event was originally sent to an event group.
  4. as the receive function returns the count of the current event group is decremented. If the count reaches zero (last event) the related notification event(s) are sent automatically and can trigger the next operation for the application.
  5. the sequence can continue from step 2 for a new set of events if the event group is to be reused.

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.

Function Documentation

◆ em_event_group_abort()

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.

Attention
Related notification events will not be automatically freed in any case and must be handled by the application.
Parameters
event_groupEvent group to abort and reset
Returns
EM_OK if the call was made early enough to cleanly abort, i.e. before the last event was processed. EM_OK also means the notifications will not be sent.
Examples
event_group.c, event_group_abort.c, event_group_assign_end.c, event_group_chaining.c, fractal.c, and queue_group.c.

Definition at line 685 of file event_machine_event_group.c.

◆ em_event_group_apply()

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.

Attention
em_event_group_apply() can only be used on a newly created event group or when the previous cycle is completed or successfully aborted. Application can use em_event_group_is_ready() to detect whether apply is allowed but would normally use a notification to setup a new cycle (implementation must make sure that when any of the notifications is received the group is ready for new apply).

Apply should only be called once per group cycle.

Parameters
event_groupEvent group
countNumber of events in the group (positive integer)
num_notifNumber of notification events to send
notif_tblTable of notifications (events and target queues)
Returns
EM_OK if successful.
See also
em_event_group_create(), em_send_group(), em_event_group_is_ready(), em_notif_t
Examples
event_group.c, event_group_abort.c, event_group_assign_end.c, event_group_chaining.c, fractal.c, queue_group.c, and queue_groups.c.

Definition at line 93 of file event_machine_event_group.c.

◆ em_event_group_assign()

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.

Parameters
event_groupAn applied event group to assign to
Returns
EM_OK if assignment was successful
Examples
event_group_abort.c, and event_group_assign_end.c.

Definition at line 644 of file event_machine_event_group.c.

◆ em_event_group_create()

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.

Returns
The new event group or EM_EVENT_GROUP_UNDEF if no event group is available.
See also
em_event_group_delete(), em_event_group_apply()
Examples
event_group.c, event_group_abort.c, event_group_assign_end.c, event_group_chaining.c, fractal.c, queue_group.c, and queue_groups.c.

Definition at line 37 of file event_machine_event_group.c.

◆ em_event_group_current()

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.

Returns
Current event group or EM_EVENT_GROUP_UNDEF
See also
em_event_group_create()
Examples
event_group.c, event_group_abort.c, event_group_assign_end.c, and event_group_chaining.c.

Definition at line 245 of file event_machine_event_group.c.

◆ em_event_group_delete()

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.

Parameters
event_groupEvent group to delete
Returns
EM_OK if successful.
See also
em_event_group_create(), em_event_group_abort()
Examples
event_group.c, event_group_abort.c, event_group_assign_end.c, event_group_chaining.c, fractal.c, queue_group.c, and queue_groups.c.

Definition at line 57 of file event_machine_event_group.c.

◆ em_event_group_get_first()

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.

unsigned int num;
em_event_group_t eg = em_event_group_get_first(&num);
while (eg != EM_EVENT_GROUP_UNDEF) {
}
Parameters
[out]numPointer to an unsigned int to store the amount of event groups into
Returns
The first event group handle or EM_EVENT_GROUP_UNDEF if none exist
See also
em_event_group_get_next()
Examples
event_group.c, and event_group_chaining.c.

Definition at line 782 of file event_machine_event_group.c.

◆ em_event_group_get_next()

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.

Returns
The next event group handle or EM_EVENT_GROUP_UNDEF if the event group iteration is completed (i.e. no more event groups available).
See also
em_event_group_get_first()
Examples
event_group.c, and event_group_chaining.c.

Definition at line 811 of file event_machine_event_group.c.

◆ em_event_group_get_notif()

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).

Attention
This is not a synchronization point, which means em_event_group_get_notif() could return notifications which are just going to be sent and thus should not be touched.
Parameters
event_groupEvent group
max_notifMaximum number of notifications to return
[out]notif_tblTable for notifications to fill
Returns
Number of returned notifications
See also
em_event_group_apply(), em_event_group_abort()
Examples
event_group.c, event_group_abort.c, event_group_assign_end.c, event_group_chaining.c, fractal.c, and queue_group.c.

Definition at line 735 of file event_machine_event_group.c.

◆ em_event_group_increment()

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.

Parameters
countNumber of events to add to the event group (positive integer)
Returns
EM_OK if successful.
See also
em_send_group(), em_event_group_apply()
Examples
event_group.c, event_group_abort.c, event_group_assign_end.c, and event_group_chaining.c.

Definition at line 151 of file event_machine_event_group.c.

◆ em_event_group_is_ready()

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.

Parameters
event_groupEvent group
Returns
EM_TRUE if the given event group is ready for apply
See also
em_event_group_create(), em_event_group_apply()
Examples
event_group.c, event_group_abort.c, event_group_assign_end.c, event_group_chaining.c, fractal.c, and queue_group.c.

Definition at line 212 of file event_machine_event_group.c.

◆ em_event_group_processing_end()

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.

Examples
event_group_abort.c, and event_group_assign_end.c.

Definition at line 625 of file event_machine_event_group.c.

◆ em_event_group_to_u64()

uint64_t em_event_group_to_u64 ( em_event_group_t  event_group)

Convert an event group handle to an unsigned integer

Parameters
event_groupEvent group handle to be converted
Returns
uint64_t value that can be used to print/display the handle
Note
This routine is intended to be used for diagnostic purposes to enable applications to e.g. generate a printable value that represents an em_event_group_t handle.

Definition at line 834 of file event_machine_event_group.c.

◆ em_send_group()

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.

Parameters
eventEvent to send
queueDestination queue
event_groupEvent group
Returns
EM_OK if successful.
See also
em_send(), em_event_group_create(), em_event_group_apply(), em_event_group_increment()
Examples
event_group.c, event_group_abort.c, event_group_assign_end.c, event_group_chaining.c, fractal.c, and queue_group.c.

Definition at line 474 of file event_machine_event_group.c.

◆ em_send_group_multi()

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.

Parameters
eventsList of events to send (i.e. ptr to array of events)
numNumber of events
queueDestination queue
event_groupEvent group
Returns
number of events successfully sent (equal to num if all successful)
See also
em_send_group()
Examples
event_group_assign_end.c.

Definition at line 556 of file event_machine_event_group.c.

em_event_group_get_first
em_event_group_t em_event_group_get_first(unsigned int *num)
Definition: event_machine_event_group.c:782
em_event_group_get_next
em_event_group_t em_event_group_get_next(void)
Definition: event_machine_event_group.c:811
EM_EVENT_GROUP_UNDEF
#define EM_EVENT_GROUP_UNDEF
Definition: event_machine_types.h:141