A COO Class:
Extendable Stack

 

 

An extendable Stack is bounded as it can store only SIZE items. But when it is full and receives a push request, it creates an auxiliary Stack, and forwards to it the requests for the push and pop services. Then, this auxiliary Stack is deleted if it becomes empty after a pop request. Thus, a Stack acts as if it was unbounded, or the root of a stack of bounded stacks.

Both the graphical and the textual definition of this class are shown below.

Class Stack specification;
uses ITEM, Boolean, SIZE;
//C++ items defined in the additional code
operations
unheritable empty () : Boolean
//unheritable operation may access private attributes
begincode return (top == 0) endcode;
services
push (i: ITEM) : <>;
pop () : <ITEM>;
end.
 
Class Stack implementation;
invokes Stack;
attributes
top : int;
buf : array [SIZE] of ITEM;
aux : Stack*; //a reference toward another Stack
operations
full () : Boolean
begincode return (top == SIZE); endcode;
Init (n : const OCNAME&) //defines the instances’ initial value
begincode setname (n);
top = 0; aux = NULL;endcode;
OBCS //as edited using MACAO

end.

 

The OBCS of this class features only one place, the type of which is empty: it may contain only raw tokens bearing no value. The t1 and t2 transitions accept the service push, and they are guarded by complementary preconditions. t1 stores the item i and returns an acknowledgement, while t2 creates an auxiliary Stack if it does not yet exist, then requests the push service of the aux Stack, and finally returns an acknowledgement. The syntax of the service call means that no reply is expected for that request, that is t2 sends the acknowledgement without waiting for the result of its request. Concerning the pop service, the t5 transition waits for the reply of its request before to send its own reply to the client.

By default, each service serves requests on a FIFO policy. To ensure that the pop service actually returns the last arrived ITEM, t1 and t2 have an higher priority than t4 and t5.

The t1 and t4 transitions both update the top attribute, and thus they cannot occur concurrently, and the same holds for the t2 and t5 transitions w.r.t. the aux attribute. Since transitions of an OBCS never occur concurrently, this constraint is automatically enforced and it is pointless to add other places to ensure their mutual exclusion.

The textual definition of the class

/* "///" is a shorthand for the begincode and endcode keywords
_S-> is a prefix to acces the Object’s attributes and operations
(it is omitted in the above graphical definition)
*/
Class Stack specification;
uses ITEM, Boolean, SIZE; //C++ types and classes defined by the designer
operations
unheritable empty () : Boolean
/// return (top == 0) ;///;
services
push (i : ITEM);
pop () : <ITEM>;
end.
Class Stack implementation;
invokes Stack;
attributes
top : int;
rep : array [SIZE] of ITEM;
aux : Stack*; //reference toward another Stack
operations
full () : Boolean
/// return (top == SIZE); ///;
Init (n : const OCNAME&) //defines the instances’ initial value
/// setname (n);
top = 0; aux = NULL;
///;
OBCS
Place p1
type = < >; //the default type
Transition t1
Precond = begincode
!(_S->full())
endcode,
Accept = <i>,
Return = <>,
service = push,
if-added = begincode
printf ("Arrival of a new request for %s\n", _S->_name);
endcode,
Order = begincode
if (t1->c1 < t2->c1) return (1);
else return (0);
endcode,
if-removed = begincode
int i = 1;
endcode,
Action = begincode
_S->rep[_S->top] = i;
_S->top++;
printf("the stack %s is :",_S->_name);
for (int ii=0;ii<_S->top;ii++) {
printf(" %d ",_S->rep[ii]);}
printf("\n");
endcode;
Arcto p1
Valuation = <>; //the default valuation
 
Transition t2
Precond = begincode
_S->full ()
endcode,
Action = begincode
if (!(_S->aux)){
char* nom=(char *)malloc(10);
gene_nom("pile",nom);
_S->aux= new Stack;
_S->aux->Init (nom);
}
=_S->aux->push (i)
endcode,
Accept = <i>,
Return = <>,
service = push;
Arcto p1;
 
Transition t5
Precond = begincode
_S->aux!=NULL
endcode,
Accept = <>,
Return = <i>,
service = pop,
Action = begincode
<i> = _S->aux->pop()
if (_S->aux->empty() && _S->aux->codelete==0) {
delete (_S->aux);
_S->aux = NULL;
};
endcode,
trigger = p1;
Arcfrom p1
Valuation = <>;
 
Transition t4
Precond = begincode
_S->aux==NULL
endcode,
Action = begincode
_S->top --;
i =_S->rep[_S->top];
endcode,
Accept = <>,
Return = <i>,
service = pop,
trigger = p1;
Arcfrom p1
Valuation = <>;
End.

Overview of COOs, SYROCO

The Dynamic Philosopher example

Mail to: C. Sibertin-Blanc