Re: Patterns in my project. Suggestion Needed Also.

From: H. S. Lahman (h.lahman_at_verizon.net)
Date: 01/03/04


Date: Fri, 02 Jan 2004 23:45:54 GMT

Responding to Pandy.song...

> I am now a engineer , doing job relative to realtime system.
> In the module I worked with, I need to manage some resources.
> The module receives message from above layer. As module receives
> message , it will call under-layer driver. The driver will
> synchronously return immediately or asynchronously call our
> callback function in another task/thread later. If it is asynchronous,
> The module need to init a timer. If driver have not call our
> callback in a certain period, Timer task will call time-out callback.
>
> Here there are more than tree task/thread : (1) the main task/thread,
> receiving message, calling driver : (2) Driver's task/thread, calling
> callback function. (3)Timer task, calling our time-out callback function.
>
> The old module is written by C language and difficult to maintain and read.
> I am now try to implement this using design pattern in C++ in a clear way.
>
> There are basicly four operations relative to a certain resouce :Alloc,
> Start, Stop, Free. And there are different kinds of resources. For different
> resources, four operations have different meaning.
>
> Follwing is my scheme :
>
> CCommand <--> CResouce <--> CFSM
> |
> |
> CTimer
>
> The class CCommand, CResource and CFsm are abstract classes. The CCommand
> will
> use composition design pattern, because one messages from above layer may
> mean
> some operations relative to a certain resource. For example, One message may
> let
> our moudle first allocate a resouce and then start it.
>
>
> CResouce will manage different kinds of resource, there are four the virtual
> funcions
> in it called alloc(), start(), stop(), free().
>
> Every Resouce have a CFSM , representing current state. Different state that
> resouce
> is in means different concrete operation for alloc(), start(), stop, free().

This sounds like you are using the GoF State pattern to emulate an FSM?
  If so, I would be inclined not to do that. I would use a real state
machine with an event queue manager. This is especially true if you are
having RTOS problems in doing work in other threads (I would expect
instantiating the relationship to the right 'current state' would be be
a problem).

> Resouce
> have four virtual funtions also.
> The asyn-call sequence is showed as bellow :
>
> Driver return in a certain time :
>
> Command Resouce FSM Driver Timer
> | | | | |
> |-- Alloc -> | | | |
> | |---Alloc-> | | |
> | | | ---Alloc--> | |
> |--StartTimer---------------------------------------> |
> | | | | |
> | <-----------Alloc OK-------------- | |
> |--StopTimer----------------------------------------> |
> | | | | |
> | | | | |
> | | | | |
>
>
>
>
> Driver does not return in a certain time :
>
> Command Resouce FSM Driver Timer
> | | | | |
> |-- Alloc ->| | | |
> | |---Alloc-> | | |
> | | | ---Alloc--> | |
> |--StartTimer--------------------------------------->|
> | | | | |
> | | | | |
> |<--TimerOut---------------------------------------- |
> |--Stop Timer--------------------------------------> |
> | | | | |
> | | | | |
>
>
>
> The problem is here:
>
>
> (1) When CCommand gets notified by driver or timer, it will
> call next child command or reply to above layer.But Main
> task and Timer task , Driver task are in different
> running context. The arthitecture of our system do not
> allow do much work in another module's context, for example
> driver's context. So one mothed is send message to some
> message queue in CCommand->OnDriverCallBack() and main task
> receive this internal-message from the queue, and do relative
> job in its one one context.

What I am not clear about is where start(), stop() and free() enter the
picture. For example, it seems like if there is a time out, somebody
has to do some housekeeping to shut down the Driver thread. (I also
envision a race condition unless Command keeps track of which Driver
threads have timed out so that it can ignore Allo*** if the driver
thread invokes it just after the Timer issued the time-out.) Is Command
taking care of all that?

Rather than a separate message queue, have you considered putting an
event queue manager in each thread and performing thread activities
through interacting state machines? That would allow minimal
communication between threads and would be inherently asynchronous. The
event queue itself could prioritize the events internally. Then state
machines for Command, etc. could deal with race conditions via Ignore
(e.g., the TimerOut event would transition to a state where Allo*** is
ignored). This would lead to more complicated state machines and more
event traffic, but it might be a lot more robust.

*************
There is nothing wrong with me that could
not be cured by a capful of Drano.

H. S. Lahman
hsl@pathfindermda.com
Pathfinder Solutions -- Put MDA to Work
http://www.pathfindermda.com
(888)-OOA-PATH