My intent with this tutorial was to derive from ACE_Data_Block instead of ACE_Message_Block so that we could leverage the reference counting nature of that object.
Along the way, I sort of got distracted... What I ended up with is a poor excuse for ACE_Stream that implements a simple state machine.
The application is built around a thread pool where the pool's svc() method takes work units from the message queue for processing. As each unit is taken from the queue, the process() method is invoked to do some work. The twist is that after processing the message, we enqueue it into another thread pool to do more work. This continues through a chain of thread pools until the last where the unit's fini() method is called for finishing up any outstanding work.
The chain of thread pools is uni-directional using a singly-linked list of Task derivatives. Each pool has the same number of tasks in order to keep things simple.
Kirthika's abstract:
A task is created with a number of subtasks. Once the message block is obtained from the queue, it is verified to see whether a task has a subtask. If so, it is forwarded to the subtask. Thus the mesage traverses over the whole list. As a safety measure for destroying the block after it goes through the whole list, an effective and simple Memory Leak Detector has been implemented. It is a counter which increments when the object where it resides is created and decrements on its deletion.
Another optimisation from the previous tutorials on Message Queues, is the bundling of the Data block within the Message Block. The Data block provides reference counting, so duplication of data is avoided. It is deleted only when its reference count drops to zero. Now updating this count between threads call for synchronisation and in comes the ACE_Mutex, a lock which takes care that the counting is thread-safe.
Although the example isn't a full-fledged Finite State Machine, i.e. it has to be tweaked to be able to jump states on different inputs, it definitely proves to be a great lesson and introduces us to quite a few new ACE classes and the ways they can be mixed and matched to produce the end-system desired.