Sessions design pattern at Oswego.

I Find Karma (
Fri, 19 Apr 96 11:21:25 PDT

contains some thoughts on a "session" design pattern from
the transaction-systems context. I include part of the
page below; visit the rest if you're interested.



Abstractly, sessions consist of three sets of actions on resources. Call
the kinds of actions B, M, and E (for Beginning, Middle, and End). The
rules are that

A session begins with a single B-Action. A B-action normally
returns a handle (reference, id, pointer, etc) argument, h.

Any number of M-actions may occur after the single B-action.
Each M- action somehow uses the handle h obtained from the B-action.

A session ends with a single E-action that somehow invalidates or
consumes the handle h. An E-action is triggered only when no additional
M-actions are desired or possible.

This simple protocol can be described as the regular expression: (B M* E).


C++ Objects:
B = {new}
M = { [messages to created object] }
E = {delete}
B = {beginTransaction}
M = { [messages to participating objects] }
E = {commit, abort}
B = {acquire}
M = { [messages to locked objects] }
E = {release}
Unix Files:
B = {open, dup, ... }
M = {read, write, ...}
E = {close}
Network Channels and Sockets
B = {connect, ... }
M = {send, accept, ...}
E = {disconnect, ...}
CORBA Services:
B = {create, duplicate}
M = { [messages to service] }
E = {release}


How do you make sure that this protocol is followed? That is:

Exactly one B-action occurs before all M-actions
Exactly one E-action occurs after all M-actions
No M-Action or E-Action occurs otherwise.


Because of the structure of the problem, enforcing sequencing of
M-Actions after B-Actions is usually simple. In most cases, M-actions
require handles that can only have been constructed via B-actions, so
must follow them. (An exception to this is that if B-actions can fail,
you may need a way of preventing other actions from occuring.)

The most central concerns revolve around the conditions under which
E-Actions occur. Arranging that an E-Action occurs in the right way
almost always leads to corresponding policies for B-Actions and
M-Actions. In particular, the following forces may apply:

Resource Consumption

B-actions typically represent resource allocation, and E-actions
resource reclamation. An E-action for handle h may be required before
some other B-action for some other handle h'. For example, in the case
where actions in E release resources (memory, files, etc) they must be
performed soon enough to allow new allocations. You'd like to minimize
the number of resources in use at any time.


Often, an attempt to perform an M-action after an E-action is a
catastrophic failure, for which there is no sensible recovery. Similarly
for multiple E-Actions. Ideally, design policies should provably prevent
such failures. In turn these policies should be enforceable by an
implementation language or other tools.


When multiple objects must invoke the actions in B, M, E, and the
actions in set M are unknown in advance, ensuring that only legal B-M-E
traces occur is a non-local, dynamic problem requiring some kind of
multi-object protocols, policies, or conventions. Designs should
minimize the number of objects involved in such policies.


To avoid error, you'd like to minimize the total number of
associated policies and mechanisms adopted in a system. Ideally,
policies should consist of simple conventions that do not depend on
special actions being performed by a large number of objects.


You'd like to minimize the time and space overhead associated
with the protocols.


Discover or devise the enabling conditions for E-Actions, along with
policies about how these conditions will be tested or otherwise dealt
with. Structure everything else accordingly.

There are two aspects to design: (1) Choosing or determining Policies
surrounding enabling conditions and responsibility for detecting them
and carrying out the corresponding E-Actions. (2) Possibly grouping
resources into Containers managed as a whole rather than individually.