Collaborating modules pass data-blocks (payloads) but depending on
the application, the requirements for these payloads could be very
different: some may need asynchronous user events, some may have different
priority levels, some may contain large amounts of data. On the other
hand, sometimes the receiving module operates at a slower rate than
the transmitter, to avoid data loss the receiver must be able to determine
the flow control.
Besides, we must take into account a number of possible problems.
Large payloads make buffering very difficult. Payloads with time-sensitive
data have to be transferred in such a way that no deadlines are violated.
Asynchronous or priorized events are sent from one module to another-
Shared resources for inter-module communication might not be available
or the synchronization overhead not acceptable. And flow control has
to be determined by receiving module.
There are three basic ways to assign flow control among modules that
It must be noted though that having more than one input port complicates
flow control and requires additional policies.
- Pull (functional): The downstream module requests information from
the upstream module with a method call that returns the values as
result. This mechanism can be implemented via a sequential protocol,
may be multithreaded and may process in-place. The receiving module
determines flow control. It is applicable in systems where the sender
operates faster than the receiver. This mechanism cannot deal with
asynchronous or priorized events.
- Push (event driven): The upstream module issues a message whenever
new values are available. The mechanism can be implemented: as procedure
calls containing new data as arguments; as non-returning point to
point messages or broadcast; as priorized interrupts; or as continuation-style
program jumps. Usually the sending module does not know whether the
receiver is ready or not. To prevent data loss the receiver can have
a queue. If there are asynchronous or high-priority events, the queue
must let them pass, else a simple FIFO queue can do.
- Indirect (shared resources): Requires a shared repository accessible
to both modules. When the sender is ready to pass a payload to the
receiver, it writes in the shared repository. When ready to process,
the receiver takes a payload from the repository. The sender and the
receiver can process at different rates. If not all the payloads are
required by the receiver, the upstream module can overwrite data.