QP/C++  7.3.4
Real-Time Embedded Framework
Loading...
Searching...
No Matches
Event Delivery Mechanisms

Active ObjectsEvent Memory Management

Concepts & Definitions

One of the main responsibilities of the QP Framework is to reliably and safely deliver QP events from various producers to Active Objects. The event delivery is asynchronous, meaning that the producers only post events to Active Objects, but don't wait in-line for the processing of the events. Any part of the system can produce events, not necessarily only the Active Objects. For example, ISRs, device drivers, or legacy code running outside the framework can produce events. On the other hand, only Active Objects can consume QP events, because only Active Objects are guaranteed to have event queues.

Event delivery mechanisms can be broadly classified into the following two categories (see Figure SRS-41):

  1. Direct event posting, when the producer of an event directly posts the event to the event queue of the consumer Active Object.
  2. Publish-subscribe, where a producer "publishes" an event to the framework, and the framework then delivers the event to all Active Objects that had "subscribed" to the event.

Figure SRS-41: Event delivery mechanisms in the QP Framework

Direct Event Posting

Direct event posting is the simplest mechanism that allows producers to post events directly to the event queue of the recipient Active Object. Figure SRS-41 illustrates this form of communication as red arrows directly connecting event producers and the consumer Active Objects.

Direct event posting is a "push-style" communication mechanism, in which recipients receive unsolicited events whether they "want" them or not. Direct event posting is well suited for situations where a group of Active Objects, or an Active Object and an ISR, form a subsystem providing a particular service, such as a communication stack, GPS capability, digital camera subsystem in a mobile phone, or the like. This style of event passing requires that the event producers "knows" the recipients and their interests in various events. The "knowledge" that a sender needs is, at a minimum, the handle (e.g., a pointer) to the recipient Active Object.

Direct event posting mechanism might increase the coupling among the components, especially when the recipients of the events are hard-coded inside the event producers. However, one way of reducing the coupling is to allow the recipients to "register" with the producers at runtime (e.g., event producer can store a pointer to the direct consumer of the events). That way the producer does not need to hard-code the recipient(s).

Remarks
QP Framework also provides "raw" thread-safe event queues without Active Objects behind them. Such "raw" thread-safe queues can be also used for direct event posting, but they cannot block (even when QP runs on top of a blocking RTOS kernel) and are mainly intended to directly deliver events to ISRs, that is, provide a communication mechanism from the Active Object level to the ISR level.

Publish-Subscribe

Publish-subscribe event delivery is shown in Figure SRS-41 as a "software bus" into which Active Objects "plug in" through the specified interface. Active Objects interested in certain events subscribe to one or more event signals by the QP framework. When an event producer chooses to publish an event, QP Framework delivers the event to all subscribers, which entails event multicasting the event (sometimes incorrectly called broadcasting). Publication requests can originate asynchronously from many sources, not necessarily just from Active Objects. For example, events can be published from interrupts (ISRs), device drivers, or the "naked" threads (in case QP runs on top of a conventional RTOS/OS).

Publish-subscribe is a "pull-style" communication mechanism in which recipients receive only solicited (subscribed) events. The properties of the publish-subscribe model are:

  • Producers and consumers of events don't need to know each other (loose coupling).
  • The events exchanged via this mechanism must be publicly known and must have the same semantics to all parties.
  • Publish-subscribe implies event multicasting in case a given event signal is subscribed by multiple Active Objects.
  • A "mediator" (QP Framework) is required to accept published events and to deliver them to all interested subscribers.
  • Many-to-many interactions (object-to-object) are replaced with one-to-many (object-to-mediator) interactions.

Event Delivery Guarantee

Traditional sequential systems communicate predominately using synchronous function calls. When module A wants to communicate with module B, module A calls a function in B. The communication is implicitly assumed to be reliable; the programmer takes for granted that the function call mechanism will work, that the parameters will be passed to the callee and that the return value will be delivered to the caller. The programmer does not conceive of any recovery strategy to handle a failure in the function call mechanism. (In fact, any such strategies would complicate the development so much that it would become impractical, while still unreliable.) However, any function call can fail due to insufficient stack space. Consequently, the reliability of synchronous communication is, in fact, predicated on the implicit assumption of adequate stack resources.

Event-driven systems communicate predominately by asynchronous event exchange. When producer A wants to communicate with Active Object B, producer A allocates an event and posts or publishes it to the event queue of Active Object B. As in the case of synchronous communication, the programmer should be able to take for granted that the event delivery mechanism will work. The programmer should not need to devise a recovery strategy to handle a failure in the basic event delivery mechanism. (In fact, such strategies would complicate the development so much that it would become impractical, while still unreliable.) However, asynchronous communication can fail due to insufficient queue capacity (or event-pool capacity; see the Event Memory Management section). Consequently, the reliability of asynchronous communication is, in fact, predicated on the assumption of adequate event queue capacity (and event pool size).

An event-driven framework (like QP) shall detect event queue overruns (and event pool depletion), just like a traditional RTOS detects stack overflows. It is up to the application developer to adequately size all Active Object event queues (and event pools) in the same way, as it is the developer's responsibility to sufficiently size all execution stacks for all threads in a traditional RTOS. Given the adequately sized queues (and event pools), an event-driven framework (like QP) can and should guarantee event delivery. Such a guarantee is essential because only reliable event delivery can be used to build reliable event-driven systems.

Remarks
This discussion is limited to non-distributed systems executing in a single address space. Distributed systems connected with unreliable communication media pose quite different challenges. In this case, neither synchronous communications such as remote procedure call (RPC) nor asynchronous communications via event passing can make strong guarantees.

Requirements

SRS-QP-04_00

SRS-QP-04_00
QP Framework shall provide direct event posting to Active Object instances based on the FIFO policy
Description
The direct event posting mechanism shall post events to the event queue of the recipient Active Object utilizing the FIFO (First-In-First-Out) policy. Direct event posting with the default FIFO policy shall be available to all possible event producers, such as Active Objects, but also interrupts (ISRs), "device drivers", and "naked" threads of an RTOS (if an RTOS is used to run QP).
Dependencies
SRS-QP-03_20, SRS-QP-03_21

SRS-QP-04_01

SRS-QP-04_01
QP Framework shall provide direct event self-posting to Active Object instances based on the LIFO policy
Description
Self-posting means that a given Active Object instance posts event to its own event queue. Such self-posting mechanism shall use the same event queue as the default FIFO policy, but in addition to the default FIFO policy it should provide also the LIFO (Last-In-First-Out) policy. This self-posting with the LIFO policy shall use a distinctly different API than the default direct event posting with the FIFO policy.
Use case
Self-posting of events with the LIFO policy can be useful for recalling events that have been deferred by the Active Object instance.
Dependencies
SRS-QP-03_20, SRS-QP-03_21

SRS-QP-04_10

SRS-QP-04_10
The direct posting mechanism shall be reliable
Description
"Reliable" event posting means that QP Framework provides event delivery guarantee to QP Application. This requirement also means that QP Application is responsible for adequately sizing all event queues (and event pools).
Dependencies
SRS-QP-04_00
Use case
QP Framework can meet this requirement by detecting all conditions that could prevent a posted event from reaching the recipient Active Object (in particular event queue overflow). In case any such condition occurs, QP Framework shall enter a fail-safe state. That way, QP Application does not need to check whether direct event posting was successful (because continuing execution means that it was).

SRS-QP-04_20

SRS-QP-04_20
QP Framework may provide alternative unreliable event posting mechanism without event delivery guarantee
Description
The alterative direct event posting mechanism without event delivery guarantee shall detect that a given event cannot be posted, but QP Framework should pass this information to QP Application instead of entering a fail-safe state. The alterative direct event posting mechanism without event delivery guarantee must use a different API than the default mechanism with delivery guarantee.
Use Case
Event posting without event delivery guarantee is useful for events that the application can afford to occasionally lose and can apply only "best effort" to handle.

SRS-QP-04_21

SRS-QP-04_21
The alternative unreliable event posting mechanism shall not interfere with the default reliable event posting
Description
An example of interference between the two event posting mechanisms is exhausting queue capacity by the unreliable event posting, so that the reliable event posting fails. Consequently, the unreliable event posting mechanism should not exhaust the event queue resource completely, but rather leave a specified number of unused queue entries (a safety margin) for the reliable event delivery.
Dependencies
SRS-QP-04_20
Use Case
When using the unreliable direct event posting mechanism, QP Application shall specify a non-zero safety margin of the event queue to which it posts events that can be lost. The unreliable posting should fail (and convey this failure to QP Application) when the safety margin is reached. That way some space in the queue remains available to the reliable (default) event posting mechanism.

SRS-QP-04_50

SRS-QP-04_50
QP Framework shall provide publish-subscribe event delivery mechanism
Description
Publish-subscribe shall use direct event posting (default, reliable variant based on FIFO policy) as the underlying low-level mechanism to multicast the subscribed events.
Dependencies
SRS-QP-04_00

SRS-QP-04_51

SRS-QP-04_51
The publish-subscribe event delivery mechanism shall be configurable and optional
Description
The QP Application shall initialize and configure the publish-subscribe delivery mechanism by supplying the maximum number of event signals that can be subscribed and a memory buffer to store the subscription information. As a special case, QP Application might choose not to initialize publish-subscribe, in which case the feature shall be inactive and shall not cause any waste of resources (RAM).
Dependencies
SRS-QP-04_50
Use case
QP Application initializes the publish-subscribe event delivery for a given maximum number of event signals and provides memory buffer capable of holding that many signals for the maximum allowed number of Active Objects in QP Application (see SRS-QP-03_01).

SRS-QP-04_52

SRS-QP-04_52
QP Framework shall allow Active Object instances to subscribe to a given event signal at run-time.
Description
QP Framework shall provide API for Active Objects to subscribe one event signal at a time. The API shall be callable multiple times by a given Active Object to subscribe to multiple event signals. Event subscription requires initialization of the publish-subscribe feature and attempts to subscribe without prior initialization shall be treated as a programming error. Similarly, subscribing to an already subscribed signal (by the same Active Object) shall be treated as a programming error.
Dependencies
SRS-QP-04_50

SRS-QP-04_53

SRS-QP-04_53
QP Framework shall allow Active Object instances to unsubscribe from a subscribed event signal at run-time.
Description
QP Framework shall provide API for Active Objects to unsubscribe one event signal at a time. The API shall be callable multiple times by a given Active Object to unsubscribe from multiple event signals. Event un-subscription requires initialization of the publish-subscribe feature and attempts to unsubscribe without prior initialization shall be treated as a programming error. Similarly, unsubscribing from a signal that has not been subscribed shall be treated as a programming error.
Dependencies
SRS-QP-04_50

SRS-QP-04_54

SRS-QP-04_54
QP Framework shall allow Active Object instances to unsubscribe from all subscribed event signals at run-time.
Description
QP Framework shall provide API for Active Objects to unsubscribe from all event signals at ones. Event un-subscription requires initialization of the publish-subscribe feature and attempts to unsubscribe without prior initialization shall be treated as a programming error.

SRS-QP-04_55

SRS-QP-04_55
Event multicasting during publishing shall complete before the processing of the published events.
Description
The purpose of this requirement is to prevent event publishing from creating unexpected event sequences when QP Framework runs on top of a preemptive kernel. As specified in SRS-QP-04_50, event multicasting (required when a given event signal is subscribed by multiple Active Objects) uses the default direct event posting mechanism. However, if the priority of the event producer is lower than the priority of the recipient Active Object, direct event posting would normally lead to preemption (before multicasting completes). Such a preemption would then cause the high-priority Active Object to immediately process the published event, which might produce other events. These other events would then appear in the event queues of Active Objects before the originally published event. This would generate a confusing event sequence.
Dependencies
SRS-QP-04_50
Use Case
QP Framework can fulfill this requirement by preventing preemption during the event multicasting (only needed when QP Framework runs on top of a preemptive kernel). The preemption should be prevented only for the priorities of Active Objects involved in this particular multicasting. An ideal mechanism for that is selective scheduler locking based on priority ceiling protocol. The priority ceiling shall be set to the highest priority subscriber to a given event.

SRS-QP-04_80

SRS-QP-04_80
All event delivery mechanisms shall be free of concurrency hazards.
Description
"Free of concurrency hazards" means free of such hazards as as race conditions and data races. It also means that QP Framework must ensure that the current event does not change (e.g., is not corrupted or prematurely recycled) throughout all RTC steps it is involved in.

SRS-QP-04_81

SRS-QP-04_81
All event delivery mechanism shall be deterministic.
Description
"Deterministic" means that the process of event posting or publishing has a known and constant upper bound of its execution time. In case of event publishing, QP Framework cannot meet this requirement alone because the time of event multicasting depends on the number of subscribers to a given event, so it is not constant. Therefore, QP Application must be designed in such a way that the multicasting time is acceptable.

Active ObjectsEvent Memory Management