TEAM-ADA Archives

Team Ada: Ada Programming Language Advocacy


Options: Use Classic View

Use Monospaced Font
Show Text Part by Default
Condense Mail Headers

Topic: [<< First] [< Prev] [Next >] [Last >>]

Print Reply
Content-Transfer-Encoding: 7bit
Sender: "Team Ada: Ada Programming Language Advocacy (83 & 95)" <[log in to unmask]>
From: Alan and Carmel Brain <[log in to unmask]>
Date: Thu, 31 Mar 2005 00:33:26 +1000
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
MIME-Version: 1.0
Reply-To: Alan and Carmel Brain <[log in to unmask]>
Parts/Attachments: text/plain (104 lines)
This is a bit cheeky of me - I already have a solution, but would like 
to pick other people's brains for free. I'm sure other people must have 
come across this problem - or one like it - before.

Is there something blindingly obvious about Asynchronous communication 
that I've missed?

I'm looking for a design pattern/basic architecture that has the 
following properties:

Each object with a particular internal state can send messages to other 
objects, including itself.

When a message is received when in a given state, it may result in the 
generation of possibly multiple messages to other objects, and/or 
possibly multiple messages to itself.

When it sends a message, no reply is required, the message just gets 
sent, with no tellback (not even an exception), and certainly no 
blocking if the message can't be processed by the receiver.

Processing of a message to itself must not start until the state has 
changed - possibly to the same state it was in originally. Processing of 
messages to another object may be started at any time, before or after 
the state has changed. There's no guarantee that they will ever be 
processed, but the system will make good attempts to do so.

All messages to a given object are processed FIFO, except that *some* 
messages from an object to itself are processed before any from other 
objects. *some* is defined as follows: a message to the "special" object 
"self" is processed with the higher priority, whereas a message to 
general object O where O happens to have the value of the sending object 
are not.

It is allowed - though not enforced - for the processing of any message 
to any class to be "atomic" - that is, in a system where a number of 
objects O1..On of different classes C1..Cz generate message M1...Mm, 
that Mx is completely processed before any other M1...Mm can be started. 
It is desirable though that if the processing triggered by message to 
one object is blocked, that processing of a message to another object of 
the same or a different class can be started.

Once a message is processed, it is destroyed and cannot be re-processed.

The solution I have is ugly, and involves a class (the set of all 
objects within a class) implemented as a package. The package has a 
"push message on queue" Protected Object entry exposed in the spec, but 
that's all. Within the body, there's the body of the "push" (which 
pushes onto 1 of 2 queues, depending on a parameter in the entry ), plus 
a task only within the body which attempts to pop the priority queue, 
then the non-priority queue if the priority is empty. Upon popping, the 
message is parsed and appropriate actions taken, messages sent, and 
state-transitions triggered, and we loop around to try the priority 
queue again.

The ugly bit is the variant record which is discriminated by a "kind" 
stating what the message kind is, then parameters (all in) if any.

For Object O-1 to query the contents of Object O-2,

O-1 receives a message,
looks at what state it's in,
does appropriate stuff,
sends a message to O-2
does more stuff
sets itself to state "waiting for a reply from O-2"

some time later....

O-1 receives a message from O-2, said message being "here's your data, 
looks at what state it's in,
finds out it's in the "waiting for reply from O-2" state
takes the parameters d1...dn and does something useful with them
sets itself to another state


O-1 receives a message from O-2, said message being "here's your data, 
looks at what state its in
find out it's in the "something more important happened before reply was 
received" state
discards the message as not relevant
sets itself to the same state

My implementation means that we have one queue and one priority queue 
per class of objects, rather than per object. This is permitted, though 
not enforced by the requirement. It does mean that if the processing 
triggered by a message to one object of the class is blocked, then no 
other objects of the same class can start processing - which is not 

If this is as clear as mud... e-mail me and I'll try to explain it better.

Alan & Carmel Brain
mailto:[log in to unmask]