Online Book Reader

Home Category

Beautiful Code [293]

By Root 5279 0
subclasses, as each addition to any dimension could generate another implementation for each possible combination of the other dimensions. A pure Template Method design, therefore, would not be substantially better than handcrafting one-off implementations of a logging server for each variant.

A more effective and scalable design could leverage the fact that our variability dimensions are largely independent. The choice of a different IPC mechanism, for instance, is unlikely to require changes in the concurrency or synchronization mechanisms used. Moreover, there is a high-level commonality in how different types of IPC and synchronization mechanisms function—e.g., IPC mechanisms can initiate/accept connections and send/receive data on connections, whereas synchronization mechanisms have operations to acquire and release locks. The design challenge is to encapsulate the accidental complexities in these APIs so that they can be used interchangeably.

A solution to this challenge is to use the Wrapper Facade pattern, which presents a single unified OO interface for the underlying non-OO IPC and synchronization mechanisms provided by system functions in an OS. Wrapper facades are particularly useful for enhancing portability by hiding accidental complexities between mechanisms, as well as making it less tedious and error-prone to work with these APIs. For instance, a wrapper facade can define a higher-level type system that ensures that only correct operations are called on the underlying non-OO (and less type-safe) OS IPC and synchronization data structures. The role of a wrapper facade is shown in Figure 26-5.

Figure 26-5. Wrapper facade design pattern

ACE is a widely used example of host infrastructure middleware that defines unified OO interfaces using wrapper facades for both IPC and synchronization mechanisms. We base the wrapper facades in this chapter on simplified versions of those provided by ACE. Figure 26-6 shows some of the ACE wrapper facades.

Figure 26-6. Some ACE wrapper facades for passive connection establishment and synchronization

The Acceptor wrapper facade provides the means to create passive-mode connections and provides "traits" to represent aspects of a mechanism that work essentially the same way across different implementations, just with different APIs. For instance, PEER_STREAM and PEER_ADDR designate dependent wrapper facades appropriate for sending/receiving data and for addressing by the IPC mechanism, respectively. SOCK_Acceptor is a subclass of Acceptor used in this chapter to implement a factory for passively establishing connections implemented using the socket API.

The Mutex wrapper facade provides an interface whose methods acquire and release locks, including a Recursive_Mutex implemented using a mutex that will not deadlock when acquired multiple times by the same thread, a RW_Lock that implements readers/writer semantics, and a Null_Mutex whose acquire( )/release( ) methods are inline no-ops. The last class mentioned is an example of the Null Object pattern [##]and is useful for eliminating synchronization without changing application code. Figure 26-6 makes it appear as if each family of classes is related by inheritance, but they are actually implemented by classes unrelated by inheritance that have a common interface and can be used as type parameters to C++ templates. We made this design choice to avoid virtual method call overhead.

[##] "The Null Object Pattern," Bobby Woolf, in Pattern Languages of Program Design, Volume 3, Robert C. Martin, Dirk Riehle, and Frank Buschmann, Addison-Wesley, 1997.

26.2.3. Tying It All Together

Another design challenge is how to associate a concurrency strategy with an IPC and synchronization mechanism. One approach would be to use the Strategy pattern, [***]which encapsulates algorithms as objects so they can be swapped at runtime. This approach would provide the Logging_Server with a pointer to abstract base classes of Acceptor and Mutex, and then rely on dynamic binding and polymorphism to dispatch the virtual methods to the

Return Main Page Previous Page Next Page

®Online Book Reader