9.9 The Rendezvous Pattern


The rendezvous pattern is a simplified form of the guarded call pattern and is used to synchronize a set of threads or permit data sharing among a set of threads. It reifies the synchronization of two threads as an object itself. There are many subtle variants of this pattern. The Rendezvous object may contain data to be shared as the threads synchronize, or it may simply provide a means for synchronizing an arbitrary number of threads at a synchronization point with some synchronization policy or precondition before allowing them all to continue independently. The simplest of these preconditions is that a certain number of threads have registered at their synchronization points. This special case is called the thread barrier pattern.

9.9.1 Abstract

A precondition is something that is specified to be true prior to an action or activity. Preconditions are a type of constraint that is usually generative; that is, they can be used to generate code either to force the precondition to be true or to check that a precondition is true. In fact, the most common way to ensure preconditions in UML or virtually any design language is through the use of state machines. A state is a precondition for the transitions exiting it.

The rendezvous pattern is concerned with modeling the preconditions for synchronization or rendezvous of threads. It is a general pattern and easy to apply to ensure that arbitrarily complex sets of preconditions can be met at runtime. The basic behavioral model is that as each thread becomes ready to rendezvous, it registers with the Rendezvous class and blocks until the Rendezvous class releases it to run. Once the set of preconditions is met, the registered tasks are released to run using whatever scheduling policy is currently in force.

9.9.2 Problem

The problem addressed by this pattern is to codify a collaboration structure that allows any arbitrary set of precondition invariants to be met for thread synchronization, independent of task phasings, scheduling policies, and priorities.

9.9.3 Pattern Structure

The basic behavioral model, shown in Figure 9-16, is that as each thread becomes ready to rendezvous, it registers with the Rendezvous class and then blocks until the Rendezvous class releases it to run. Once the set of preconditions is met, the registered tasks are released to run using whatever scheduling policy is currently in force. The rendezvous itself is abstracted into a class, as is the set of preconditions. This approach provides a great deal of flexibility in modeling arbitrarily complex precondition invariants.

Figure 9-16. Rendezvous Pattern Structure

graphics/09fig16.gif

9.9.4 Collaboration Roles

  • Callback: The Callback object holds the address of the ClientThread object. This is so the Rendezvous object can notify all the threads that have registered when the preconditions are met. This callback may be an object address, a URL, or any other means that enables the Rendezvous object to unambiguously signal the ClientThread when the preconditions are met.

  • ClientThread: There are at least two ClientThread objects. When they reach their synchronization point, they register with the Rendezvous object and pass their callback. The notify() operation is called by dereferencing the callback; this signals the Client Thread that the preconditions have been met and thus it is now free to continue.

  • Rendezvous: The Rendezvous object manages the ThreadSynchronization object. It has a register(callback: address) operation that the ClientThreads invoke to indicate that they have reached their synchronization point.

  • SynchPolicy: The SynchPolicy object reifies the set of preconditions into a single concept. The simplest Synch Policy is nothing more than the registration count reaching some predetermined, expected value; that is, it counts the threads that have registered, and when the registration count reaches a set value, the precondition is met. This is called the thread boundary pattern. For more complex synchronization policies, the SynchPolicy object may employ a statechart to capture the richness of the required policy.

9.9.5 Consequences

This is a simple pattern that can be widely applied for various policies for thread synchronization. It scales up well to arbitrary number of threads and to arbitrarily complex synchronization policies.

9.9.6 Implementation Strategies

The SynchPolicy and Rendezvous classes are stateful, and most likely be implemented as statecharts. In the case of the thread barrier pattern specialization, it is enough simply to implement a counting machine. Figure 9-17 shows a simple counting machine statechart that counts object registrations. It begins to synch (i.e., to process evSynch events) in its Counting state. After each event, it increments its Count attribute. If it equals or exceeds the expected number of threads waiting to rendezvous, then the else clause is taken, and the Synch Policy object sends a evReleaseAll event to the Rendezvous object.

Figure 9-17. Thread Barrier Synch Policy Statechart

graphics/09fig17.gif

The Rendezvous class accepts register messages from the associated ClientThread objects; when it receives a register message, it sends an evSynch event to the SynchPolicy object. When the Rendezvous object receives an evReleaseAll event, it iterates over the list of Callback objects, sending each a notify message, informing it that the synchronization is complete, and the thread is free to continue.

The Callback class is little more than that the storage of an address of some kind. In some cases, it will literally be the address of the notify operation, to be called directly, or in a thread-safe way, using the guarded call pattern. In other cases, the notify message will be sent to that thread's event queue to be processed when the thread is scheduled to run by the operating system. In still other cases, such as when a component infrastructure is used, perhaps COM or CORBA, the Callback will contain the object ID which the component infrastructure will dereference to locate the proper object.

9.9.7 Related Patterns

This pattern can be mixed with the other thread management patterns, such as the message queue and guarded call patterns, as well as the other nonconcurrency model architectural patterns, such as the component and layered patterns.

9.9.8 Sample Model

Figure 9-18a shows an example with three threads, each of which controls a different aspect of a robot arm: two joints and a manipulator. When each of the three threads is ready, they are all allowed to proceed. Figure 9-18b shows the flow of a scenario. Note how each thread (other than the last) is blocked until the Rendezvous object releases them all. Then they will be scheduled by the OS according to its scheduling policy.

Figure 9-18a. Rendezvous

graphics/09fig18.gif

Figure 9-18b. Rendezvous Pattern Scenario Example

graphics/09fig18_01.gif



Real Time UML. Advances in The UML for Real-Time Systems
Real Time UML: Advances in the UML for Real-Time Systems (3rd Edition)
ISBN: 0321160762
EAN: 2147483647
Year: 2003
Pages: 127

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net