next up previous contents
Next: Requirement four Up: Bounded Buffer Example Previous: Requirement two

Requirement three

The word ``always'' in requirement three suggests that the requirement is a simple invariant property. Following the methodology of Figure 5.5.1, we examine the code and see that the notion of indices in range can be expressed by an appropriate constraint on the BoundedBuffer instance variables head_, tail_, and bound_. Thus, we define the range notion as in instance predicate by inserting the following declaration to the header of the BoundedBuffer class.

  /**
   * @observable
   *   EXP IndexRange: (head_ >= 0 && tail_ >= 0 && head_ < bound_ && tail_ < bound_);
   */
The tag @observable indicates that a predicate for a temporal property is being defined. The label EXP is used to define a location insensitive predicate, i.e., a predicate that only defines some constraint on data without mentioning a particular control point. The predicate above is an instance predicate (and thus must be quantified in the temporal property) because it refers to instance variables in the BoundedBuffer class. Typically, an invariant is defined using EXP predicates since by the very nature of an invariant the property should hold across multiple control points. Now we can specify the temporal property that will use IndexRange predicate. Positive invariants correspond to the universal temporal pattern. Since the invariant is to hold through the entire execution of the program, the scope of the property is global. We also need to quantify the property for all instances of the BoundedBuffer. The final version of the property expressed in BSL is as follows:
   IndexRange: forall[b:BoundedBuffer].
             {IndexRange(b)} is universal globally;



Roby Joehanes
Wed Mar 7 18:30:51 CST 2001