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