Realtime systems are generally designed as a sequence of message interactions
between tasks. This article describes different types of task design patterns.
A simple task is composed of a single state machine handled by the only
thread in the task. Messages received by the task are dispatched to the
currently active state. In such tasks the state machine state and task state are
one. The V5.2
Call task in Xenon is a good example of a task of this type.
Here, a single task manages many state machines within a single thread of
execution. Messages received by the task are first dispatched to the appropriate
state machine. The messages are further routed to the appropriate state of the
state machine. Since the task is single threaded, the next message can be
dispatched only after the processing of the current message has been finished. The E1
Manger in Xenon exemplifies such a task.
A multi threaded manager task manages many state machines, each state machine
handled in a separate thread. Messages received by the task are first dispatched
to the appropriate thread. The message is then handled in the appropriate
thread's state machine. Here, the next message can be dispatched immediately
after dispatching the current message since the message handling is taken care
by a separate thread.
Multi Task Manager is similar to the Multi Thread Manager. The main
difference is that the managed state machines are in different tasks, thus no
data can be shared between state machines. Messages are the only means of
communication and synchronization. The V5.2
Manager task is a good example of a task of this category.
Different Task Design Patterns are compared for different attributes in the
following matrix:
| |
Simple
Task |
Single
Threaded Manager |
Multi
Threaded Manager |
Multi
Task Manager |
| Complexity |
Simple. A single state machine has
to be handled. |
More complicated as state machine
creation, deletion and message dispatching have to be managed. |
More complicated than Single
Threaded Manager as thread concurrency issues need to be addressed when
sharing data. |
Most complicated as all
communication has to be managed via messages. |
| Message
Routing |
Simple. Messages just need to be
routed to the current state's handler. |
More Complicated. Message needs to
be dispatched to the appropriate state machine object. All the state
machines share a single message queue, so the dispatching overhead will be
incurred for every message exchange |
Complicated. Initial messages need
to be dispatched to the thread handling the state machine. Subsequent
messages might be received directly by the thread. |
Most complicated. Initial messages
need to be dispatched by the task managing the state machines.
Subsequent messages will be received directly by the task. |
| Heap
and Stack |
A single heap and stack is used. |
All state machines share a single
heap and stack. |
All state machine threads share a
single heap. Each thread has its own stack. |
All state machine tasks have their
own stack and heap. |
| Reliability |
Reliable. Heap and stack are not
shared. |
Low Reliability. Crash in a single
state machine will cause the entire task to crash. Stack and heap
corruption will affect all state machines. |
Medium Reliability. Crash in a
single state machine thread will have minimal impact on other threads.
Corruption of a thread's stack will only impact that thread. Heap
corruption, overflow however will impact the complete task. Memory wild
writes by one state machine can impact the complete task. |
High Reliability. Each state
machine has its own stack and heap. Memory wild writes in one task will
have no impact on the other task. |
| Means
of Communication |
Messaging and memory access. |
Messaging and memory access. |
Messaging and memory access.
Memory access however needs to take care of concurrency. |
Messaging only. |
| Performance |
High. |
High. As a single thread with a
single stack is used. This gives a better locality of reference on the
processor cache. |
Medium. Thread switching overheads
lower performance. Poorer locality of reference due to separate
stacks. |
Low. Task switching overheads are
much higher than thread switching overheads. Poorest locality of reference
as a separate stack and heap are used for every task. |
| Multi-
processor Scalability |
None. Complete execution is in a
single thread so performance of this task cannot be improved by adding
processors. |
None. Complete execution is in a
single thread so performance of this task cannot be improved by adding
processors. |
Medium. Each state machine is
implemented as a separate thread, so adding more processors will allow
multiple threads to run concurrently on different processors. Heap
contention will however limit scalability. |
High. Tasks have their individual
threads, stacks and heaps. No resources are shared between different tasks
so the system will scale well with addition of processors. |