In QP Framework, as in any event-driven system, events are frequently passed from producers to consumers. The exchanged event instances can be either immutable or mutable.
Immutable events are event instances that never change at runtime. Such immutable events can be pre-allocated statically (typically and preferably in ROM) and can be shared safely among any number of concurrent entities (Active Objects, ISRs, "naked" threads, etc.) rather than being created and recycled dynamically every time. QP Framework does not need to manage memory for immutable events, but needs to clearly distinguish them from mutable events, precisely to avoid any memory management for them.
Many event instances, especially events with parameters cannot be easily made immutable because their main function is specifically to deliver information produced at runtime. Consequently, such mutable events must be dynamically created, filled with information (mutated), passed around, and eventually recycled. The management of these processes at runtime is one of the most valuable services QP Framework can provide to QP Application.
The main challenge of managing mutable events is to guarantee that once a mutable event gets posted or published (which might involve event multicasting), it does not change and does not get recycled until all Active Objects have finished their Run-to-Completion processing of that event. In fact, changing or premature recycling the current event constitutes a violation of the RTC semantics.
Every dynamically created mutable event must be eventually recycled, or the memory would leak. Some event-driven systems leave the event recycling to the application, but in the safety-related context, this is considered unreliable and unsafe. Therefore, the event memory management in QP Framework must also include automatic event recycling.
From the safety point of view, the ideal would be to copy entire mutable events into and out of the event queues, as it is often done with the message queues of a traditional RTOS. Unfortunately, it is prohibitively expensive in RAM and nondeterministic in CPU cycles for larger event instances (events with large parameters). However, an event-driven framework, like QP, can be far more sophisticated than a traditional RTOS because, due to inversion of control, the framework manages an event's whole life cycle. The framework extracts an event from the Active Object's event queue and dispatches it for processing. After the Run-to-Completion processing, the framework regains control of the event and can automatically recycle the event.
An event-driven framework can also easily control the dynamic allocation of mutable events (e.g., the QP Framework provides API for this purpose). All this permits the framework to implement controlled, concurrency-safe sharing of mutable events, which, from the application standpoint, is almost indistinguishable from copying entire events. Such event management is called zero-copy event management.
The whole event memory management must also carefully avoid concurrency hazards around the shared mutable events. Failure in any of those aspects results in defects (bugs) that are the hardest to detect, isolate, and fix.
To manage the memory for mutable events, QP Framework needs deterministic, efficient, and concurrency-safe method of dynamically allocating and recycling the event memory. The general-purpose, variable-block-size heap does not fit this bill and is inappropriate for safety-related applications, anyway. However, simpler, higher-performance, and safer options exist to the general-purpose heap. A well-known alternative, commonly supported by RTOSs, is a fixed-block-size heap, also known as a memory partition or memory pool. Memory pools are a much better choice for a real-time event framework like QP to manage mutable event memory than the general-purpose heap. Unlike the conventional (variable-block-size) heap, a memory pool is deterministic, has guaranteed capacity, and is not subject to fragmentation because all blocks are exactly the same size.
The most obvious drawback of a memory pool is that it does not support variable-sized blocks. Consequently, the blocks have to be oversized to handle the biggest possible allocation. Such a policy is often too wasteful if the actual sizes of allocated objects (mutable events, in this case) vary a lot. A good compromise is often to use not one but multiple memory pools with memory blocks of different sizes. QP Framework chooses that option to implement event pools, which are multiple memory pools specialized to hold mutable events.
QP Framework shall support immutable events.
QP Framework shall support mutable events.
QP Framework shall support up to 15 event pools for mutable events.
QP Framework shall provide a method of allocating mutable events at runtime.
QP Framework shall support automatic recycling of mutable events according to the "zero-copy" memory management policy.
QP Framework shall provide a method of explicitly recycling mutable events.