Motivation Design Patterns and Frameworks for Object-oriented Communication Systems

Design Patterns and Frameworks
for Object-oriented
Communication Systems
Douglas C. Schmidt
http://www.cs.wustl.edu/schmidt/
[email protected]
Washington University, St. Louis
Motivation
Developing ecient, robust, extensible, and
reusable communication software is hard
It is essential to understand successful techniques that have proven eective to solve
common development challenges
Design patterns and frameworks help to capture, articulate, and instantiate these successful techniques
2
1
Observations
Developers of communication software confront recurring challenges that are largely
application-independent
{
Design Patterns
e.g., service initialization and distribution, error
handling, ow control, event demultiplexing, concurrency control
Successful developers resolve these challenges
by applying appropriate design patterns
Design patterns represent solutions to problems that arise when developing software
within a particular context
{
Patterns capture the static and dynamic structure and collaboration among key participants in software designs
{
However, these patterns have traditionally
been either:
1. Locked inside heads of expert developers
2. Buried in source code
3
i.e., \Patterns == problem/solution pairs in a context"
They are particularly useful for articulating how
and why to resolve non-functional forces
Patterns facilitate reuse of successful software architectures and designs
4
Proxy Pattern
Graphical Notation
1: METHOD
: BROKER
CALL
4: METHOD
RETURN
: QUOTER
PROXY
OBJECT
PROCESS
THREAD
2: FORWARD
: CLASS
REQUEST
3: RESPONSE
CLIENT
CLASS
: QUOTER
TEMPLATE
CLASS
CLASS
UTILITY
NETWORK
CLASS
CATEGORY
SERVER
INHERITS
ABSTRACT
CLASS
CONTAINS
A
Intent: provide a surrogate for another object that controls access to it
INSTANTIATES
USES
6
5
Frameworks
More Observations
Patterns enable reuse of architecture and design
knowledge, but not code (directly)
A framework is:
{
Reuse of patterns alone is not sucient
{
\An integrated collection of components that collaborate to produce a reusable architecture for a
family of related applications"
Frameworks dier from conventional class
libraries:
1. Frameworks are \semi-complete" applications
To be productive, developers must also reuse
detailed designs, algorithms, interfaces, implementations, etc.
2. Frameworks address a particular application domain
3. Frameworks provide \inversion of control"
Application frameworks are an eective way
to achieve broad reuse of software
7
Typically, applications are developed by inheriting from and instantiating framework
components
8
Dierences Between Class
Libraries and Frameworks
Tutorial Outline
NETWORKING
APPLICATION
SPECIFIC
LOGIC
MATH
INVOKES
ADTS
USER
INTERFACE
EVENT
LOOP
APPLICATION
SPECIFIC
LOGIC
ADTS
Present the key reusable design patterns in
a distributed medical imaging system
{
NETWORKING
INVOKES
Outline key challenges for developing communication software
DATA
BASE
CLASS
LIBRARIES
MATH
USER
INTERFACE
CALL
BACKS
EVENT
LOOP
Both single-threaded and multi-threaded solutions
are presented
Discuss lessons learned from using patterns
on production software systems
DATABASE
OBJECT-ORIENTED
FRAMEWORK
9
Stand-alone vs. Distributed
Application Architectures
10
Concurrency vs. Parallelism
SERVER
maxfdp1
PRINTER
read_fds
CLIENT
COMPUTER
CD ROM
WORK
REQUEST
FILE
SYSTEM
CLIENT
(1) STAND-ALONE APPLICATION ARCHITECTURE
WORK
REQUEST
WORK
REQUEST
CLIENT
DISPLAY
SERVICES
FI LE
SERVICE
PRINT
SERVICE
CLIENT
CONCURRENT SERVER
CYCLE
SERVICE
WORK
REQUEST
SERVER
CPU1
NETWORK
CPU2
CPU3
CPU4
CLIENT
WORK
REQUEST
PRINTER
CD ROM
FILE SYSTEM
CLIENT
WORK
REQUEST
(2) DISTRIBUTED APPLICATION ARCHITECTURE
WORK
REQUEST
CLIENT
WORK
REQUEST
CLIENT
PARALLEL SERVER
11
12
Sources of Complexity
Distributed application development exhibits
both inherent and accidental complexity
Sources of Complexity (cont'd)
Inherent complexity results from fundamental challenges, e.g.,
{
{
Accidental complexity results from limitations with tools and techniques, e.g.,
{
Distributed systems
. Latency
Low-level tools
.
e.g., Lack of type-secure, portable, re-entrant,
and extensible system call interfaces and component libraries
.
Error handling
{
Inadequate debugging support
.
Service partitioning and load balancing
{
Widespread use of algorithmic decomposition
Concurrent systems
. Race conditions
.
Deadlock avoidance
.
Fair scheduling
.
Performance optimization and tuning
.
{
Fine for explaining network programming concepts and algorithms but inadequate for developing large-scale distributed applications
Continuous rediscovery and reinvention of core concepts and components
13
14
OO Contributions
{
{
{
{
{
Distributed Medical Imaging
Example
Concurrent and distributed programming has
traditionally been performed using low-level
OS mechanisms, e.g.,
fork/exec
Shared memory
Signals
Sockets and select
POSIX pthreads, Solaris threads, Win32 threads
OO design patterns and frameworks elevate
development to focus on application concerns, e.g.,
Service functionality and policies
{ Service conguration
{ Concurrent event demultiplexing and event handler dispatching
{ Service concurrency and synchronization
{
15
This example illustrates the reusable design
patterns and framework components used in
an OO architecture for a distributed medical
imaging system
Application clients uses Blob Servers to store
and retrieve medical images
Clients and Servers communicate via a connectionoriented transport protocol
{
e.g., TCP/IP, IPX/SPX, TP4
16
Distributed Electronic Medical
Imaging Architecture
MODALITIES
BLOB SERVER
LOCAL
STORE
(CT, MR, CR)
Architecture of the Blob Server
svc_run
svc_run
svc_run
svc_run
ATM
LAN
DIAGNOSTIC
STATIONS
NAME
SERVER
ATM
MAN
ROUTING
SERVICE
: Blob
Handler
ATM
LAN
MODALITIES
17
Design Patterns in the Blob
Server
TACTICAL
PATTERNS
Reactor
Proxy
Strategy
Proxy
Service
Configurator
Adapter
Singleton
\Convert the interface of a class into another interface client expects"
Singleton
{
19
\Dene a family of algorithms, encapsulate each
one, and make them interchangeable"
Adapter
{
Double Checked
Locking
\Provide a surrogate or placeholder for another
object to control access to it"
Strategy
{
Connector
STRATEGIC
PATTERNS
: Blob
Acceptor
Tactical Patterns
{
Acceptor
Half-Sync/
Half-Async
: Blob
Handler
* Manage short-term and long-term blob persistence
* Respond to queries from Blob Locators
18
Thread-per
Session
Active Object
Thread
Pool
: Reactor
: Options
LOCATION
SERVICE
SERVICE
(CT, MR, CR)
Thread-per
Request
: Blob
Handler
CLUSTER
STORE
TIME
SERVER
CENTRAL
STORE
: Msg
: Blob
Processor Queue
\Ensure a class only has one instance and provide
a global point of access to it"
20
Concurrency Patterns
Reactor
{
Active Object
{
\Decouples synchronous I/O from asynchronous
I/O in a system to simplify concurrent programming eort without degrading execution eciency"
\Allows each client request to run concurrently"
Thread-Pool
{
\Allows up to N requests to execute concurrently"
Thread-per-Session
{
Double-Checked Locking Pattern
{
Thread-per-Request
{
\Decouples method execution from method invocation and simplies synchronized access to shared
resources by concurrent threads"
Half-Sync/Half-Async
{
Concurrency Architecture
Patterns
\Decouples event demultiplexing and event handler dispatching from application services performed
in response to events"
\Allows each client session to run concurrently"
\Ensures atomic initialization of objects and eliminates unnecessary locking overhead on each access"
21
Service Initialization Patterns
Connector
{
Concurrency Patterns in the Blob
Server
The following example illustrates the design
patterns and framework components in an
OO implementation of a concurrent Blob
Server
There are various architectural patterns for
structuring concurrency in a Blob Server
Acceptor
{
\Decouples active connection establishment from
the service performed once the connection is established"
22
\Decouples passive connection establishment from
the service performed once the connection is established"
2. Thread-per-request
Service Congurator
{
1. Reactive
\Decouples the behavior of network services from
point in time at which services are congured into
an application"
23
3. Thread-per-session
4. Thread-pool
24
Reactive Blob Server Architecture
2: HANDLE INPUT
3: CREATE PROCESSOR
4: ACCEPT CONNECTION
5: ACTIVATE PROCESSOR
BLOB SERVER
: Blob
Processor
6: PROCESS
BLOB SERVER
: Blob
Processor
: Blob
Processor
: Blob
Processor
: Blob
Acceptor
: Blob
Processor
: Reactor
6: PROCESS
1: CONNECT
CLIENT
2: HANDLE INPUT
3: CREATE PROCESSOR
4: ACCEPT CONNECTION
5: SPAWN THREAD
: Blob
Acceptor
: Reactor
BLOB REQUEST
CLIENT
Thread-per-Request Blob Server
Architecture
BLOB REQUEST
SERVER
1: CONNECT
CLIENT
CLIENT
CLIENT
SERVER
CLIENT
25
Thread-per-Session Blob Server
Architecture
BLOB SERVER
3: SPAWN
2: CREATE,
ACCEPT,
AND ACTIVATE
BLOB_PROCESSOR
THREAD
: Blob
: Blob
Processor Processor : Blob
Processor
: Blob
Acceptor
: Reactor
4: PROCESS
26
Thread-Pool Blob Server
Architecture
BLOB SERVER
worker
thread
worker
thread
: Msg
: Blob Queue
Processor
5: DEQUEUE &
PROCESS
REQUEST
worker
thread
worker
thread
2: HANDLE INPUT
3: ENQUEUE REQUEST
: Blob
Handler : Blob
Handler
: Blob
Handler
: Blob
Acceptor
: Reactor
BLOB REQUEST
1: BIND
CLIENT
CLIENT
SERVER
6: PROCESS
BLOB REQUEST
1: BLOB
REQUEST
SERVER
CLIENT
CLIENT
CLIENT
27
CLIENT
28
The ADAPTIVE Communication
Environment (ACE)
The Reactor Pattern
GATEWAY
SERVER
DISTRIBUTED
SERVICES
FRAMEWORKS
AND CLASS
ACCEPTOR
CATEGORIES
C++
WRAPPERS
TOKEN
SERVER
THREAD
MANAGER
LOG
MSG
SPIPE
SAP
SOCK_SAP/
TLI_SAP
STREAM
PIPES
SOCKETS/
TLI
PROCESS/THREAD
SUBSYSTEM
UNIX
AND
{
CORBA
HANDLER
SERVICE
CONFIGURATOR
REACTOR
SHARED
MALLOC
SYSV
MEM
MAP
WRAPPERS
ADAPTATION LAYER
NAMED
PIPES
Intent
\Decouples event demultiplexing and event handler dispatching from the services performed in response to events"
(ASX)
SELECT/
POLL
COMMUNICATION
SUBSYSTEM
GENERAL
TIME
SERVER
FIFO
SAP
OS
THREAD
LIBRARY
NAME
SERVER
SERVICE
HANDLER
CONNECTOR
ADAPTIVE SERVICE EXECUTIVE
SYNCH
WRAPPERS
C
APIS
LOGGING
SERVER
DYNAMIC
LINKING
MEMORY
MAPPING
SYSTEM
V IPC
This pattern resolves the following forces
for event-driven software:
{
How to demultiplex multiple types of events from
multiple sources of events eciently within a single
thread of control
{
How to extend application behavior without requiring changes to the event dispatching framework
VIRTUAL MEMORY
SUBSYSTEM
WIN32
SERVICES
A set of C++ wrappers and frameworks
based on common design patterns
29
Structure of the Reactor Pattern
select (handles);
foreach h in handles {
if (h is output handler)
table[h]->handle_output () ;
if (h is input handler)
table[h]->handle_input ();
if (h is signal handler)
table[h]->handle_signal ();
}
this->expire_timers ();
Reactor
n
n
1
1
1
Timer_Queue
schedule_timer(h)
cancel_timer(h)
expire_timer(h)
Handles
1
n
Participants in the Reactor pattern
INITIALIZATION
MODE
AP
P
IN LICA
DE
PE TION
ND
EN
T
EVENT HANDLING
MODE
handle_input()
handle_output()
handle_signal()
handle_timeout()
get_handle()
A
1
AP
PL
DE ICA
T
PE
ND IONEN
T
Event_Handler
1
1
Collaboration in the Reactor
Pattern
Concrete
Event_Handler
n
handle_events()
register_handler(h)
remove_handler(h)
expire_timers()
30
main
program
INITIALIZE
REGISTER HANDLER
EXTRACT HANDLE
START EVENT LOOP
FOREACH EVENT DO
DATA ARRIVES
OK TO SEND
SIGNAL ARRIVES
TIMER EXPIRES
REMOVE HANDLER
CLEANUP
31
callback :
reactor
Concrete
: Reactor
Event_Handler
Reactor()
register_handler(callback)
get_handle()
handle_events()
select()
handle_input()
handle_output()
handle_signal()
handle_timeout()
remove_handler(callback)
handle_close()
32
Using the Reactor in the Blob
Server
4: getq(msg)
5:svc(msg)
svc_run
The Blob Handler is the Proxy for communicating with clients
{
svc_run
svc_run
: Blob
Handler
: Blob
Handler
: Message
: Blob
: Event : Blob
Queue
Handler
Processor
Handler
: Event
Handler
: Event 2: recv_request(msg)
Handler3: putq(msg)
Together with Reactor, it implements the asynchronous task portion of the Half-Sync/Half-Async
pattern
// Reusable Svc Handler.
class Blob_Handler : public Event_Handler
{
public:
// Entry point into Blob Handler.
virtual int open (void) {
// Register with Reactor to handle client input.
Reactor::instance ()->register_handler
(this, READ_MASK);
}
1: handle_input()
: Handle
Table
protected:
// Notified by Reactor when client requests arrive.
virtual int handle_input (void);
: Reactor
OS EVENT DEMULTIPLEXING INTERFACE
KERNEL
LEVEL
FRAMEWORK
LEVEL
APPLICATION
LEVEL
REGISTERED
OBJECTS
The Blob Handler Interface
// Receive and frame client requests.
int recv_request (Message_Block &*);
SOCK_Stream peer_stream_; // IPC endpoint.
};
33
34
Structure of the Active Object
Pattern
The Active Object Pattern
Intent
{
\Decouples method execution from method invocation and simplies synchronized access to shared
resources by concurrent threads"
This pattern resolves the following forces
for concurrent communication software:
{
ResultHandle m1()
ResultHandle m2()
ResultHandle m3()
VISIBLE
TO
CLIENTS
How to allow blocking read and write operations
on one endpoint that do not detract from the quality of service of other endpoints
{
How to simplify concurrent access to shared state
{
How to simplify composition of independent services
35
loop {
m = actQueue.remove()
dispatch (m)
}
Client
Interface
INVISIBLE
TO
CLIENTS
Scheduler
dispatch()
m1'()
m2'()
m3'()
1
1
1
Resource
Representation
1
Activation
Queue
insert()
remove()
1
n
Method
Objects
The Scheduler determines the sequence that
Method Objects are executed
36
Using the Active Object Pattern
in the Blob Server
Collaboration in the Active
Object Pattern
m1()
INVOKE
CREATE METHOD
OBJECT
RETURN RESULT
HANDLE
cons(m1')
future()
INSERT IN
PRIORITY QUEUE
insert(m1')
DEQUEUE NEXT
METHOD OBJECT
remove(m1')
EXECUTE
dispatch(m1')
reply_to_future()
KERNEL
LEVEL
RETURN RESULT
APPLICATION
LEVEL
CONSTRUCTION
: Client
: Activation : Represent: Scheduler
Interface
Queue
ation
FRAMEWORK
LEVEL
METHOD OBJECT
EXECUTION
COMPLETION
SCHEDULING/
client
REGISTERED
OBJECTS
4: getq(msg)
5:svc(msg)
svc_run
svc_run
svc_run
: Blob
: Message
: Blob
: Blob
Handler
Queue
Handler
Processor
: Blob
: Event Handler
: Event
Handler
2: recv_request(msg)
Handler
: Event
3: putq(msg)
Handler
1: handle_input()
: Handle
Table
: Reactor
OS EVENT DEMULTIPLEXING INTERFACE
37
38
The Blob Processor Class
Processes Blob requests using the \ThreadPool" concurrency model
{
Implement the synchronous task portion of the
Half-Sync/Half-Async pattern
Using the Singleton Pattern
The Blob Processor is implemented as a Singleton that is created \on demand"
Blob_Processor *
Blob_Processor::instance (void) {
// Beware race conditions!
if (instance_ == 0) {
instance_ = new Blob_Processor;
}
return instance_;
}
class Blob_Processor : public Task {
public:
// Singleton access point.
static Blob_Processor *instance (void);
// Pass a request to the thread pool.
virtual put (Message_Block *);
// Event loop for the pool thread
virtual int svc (int) {
Message_Block *mb = 0; // Message buffer.
// Wait for messages to arrive.
for (;;) {
getq (mb); // Inherited from class Task;
// Identify and perform Blob Server
// request processing here...
protected:
Blob_Processor (void); // Constructor.
39
Constructor creates the thread pool
Blob_Processor::Blob_Processor (void) {
Thread_Manager::instance ()->spawn_n
(num_threads, THR_FUNC (svc_run),
(void *) this, THR_NEW_LWP);
}
40
The Double-Checked Locking
Pattern
Intent
{
Using the Double-Checked
Locking Pattern for the Blob
Server
\Ensures atomic initialization of objects and eliminates unnecessary locking overhead on each access"
if (instance_ == NULL) {
mutex_.acquire ();
if (instance_ == NULL)
instance_ = new Blob_Processor;
mutex_.release ();
}
return instance_;
This pattern resolves the following forces:
1. Ensures atomic initialization or access to objects,
regardless of thread scheduling order
2. Keeps locking overhead to a minimum
{
Blob Processor
static instance()
static instance_
e.g., only lock on rst access
Mutex
Note, this pattern assumes atomic memory
access
:::
42
41
{
\Decouples synchronous I/O from asynchronous
I/O in a system to simplify programming eort
without degrading execution eciency"
This pattern resolves the following forces
for concurrent communication systems:
{
How to simplify programming for higher-level communication tasks
.
{
These are performed synchronously
How to ensure ecient lower-level I/O communication tasks
.
These are performed asynchronously
43
SYNCHRONOUS
TASK LAYER
Intent
QUEUEING
LAYER
ASYNCHRONOUS
TASK LAYER
Half-Sync/Half-Async Pattern
Structure of the
Half-Sync/Half-Async Pattern
SYNC
SYNC
TASK 3
TASK 1
SYNC
TASK 2
1, 4: read(data)
MESSAGE QUEUES
3: enqueue(data)
ASYNC
TASK
2: interrupt
EXTERNAL
EVENT SOURCES
44
Using the Half-Sync/Half-Async
Pattern in the Blob Server
RECV MSG
PROCESS MSG
ENQUEUE MSG
Message
Queue
Sync
Task
notification()
read(msg)
4: getq(msg)
5:svc(msg)
work()
QUEUEING
LEVEL
EXTERNAL EVENT
Async
Task
svc_run
enqueue(msg)
DEQUEUE MSG
EXECUTE TASK
read(msg)
work()
ASYNC TASK
LEVEL
SYNC QUEUEING ASYNC
PHASE PHASE
PHASE
External
Event Source
SYNCH TASK
LEVEL
Collaborations in the
Half-Sync/Half-Async Pattern
This illustrates input processing (output processing is similar)
svc_run
svc_run
: Blob
Processor
: Blob
Handler
: Message
: Blob
Queue
Handler
: Event
: Blob
Handler Handler
2: recv_request(msg)
: Event
3: putq(msg)
Handler
: Event
Handler
1: handle_input()
: Reactor
46
45
Joining Async and Sync Tasks in
the Blob Server
The following methods form the boundary
between the Async and Sync layers
int
Blob_Handler::handle_input (void)
{
Message_Block *mb = 0;
}
The Acceptor Pattern
Intent
{
\Decouples passive initialization of a service from
the tasks performed once the service is initialized"
This pattern resolves the following forces
for network servers using interfaces like sockets or TLI:
// Receive and frame message
// (uses peer_stream_).
recv_request (mb);
1. How to reuse passive connection establishment code
for each new service
// Insert message into the Queue.
Blob_Processor::instance ()->put (mb);
2. How to make the connection establishment code
portable across platforms that may contain sockets but not TLI, or vice versa
// Task entry point.
Blob_Processor::put (Message_Block *msg)
{
// Insert the message on the Message_Queue
// (inherited from class Task).
putq (msg);
}
47
3. How to ensure that a passive-mode descriptor is
not accidentally used to read or write data
4. How to enable exible policies for creation, connection establishment, and concurrency
48
Collaboration in the Acceptor
Pattern
Svc Handler
Svc Handler
peer_stream_
open()
Acceptor
ES
IVAT
ACT
peer_acceptor_
handle_input()
Reactor
handle_input()
SERVICE
SERVICE
ENDPOINT
PROCESSING INITIALIZATION INITIALIZATION
PHASE
PHASE
PHASE
Structure of the Acceptor Pattern
peer_acceptor_
acc :
sh:
reactor :
: SOCK
Acceptor
Svc_Handler Reactor
Acceptor
open()
open()
Server
INITIALIZE PASSIVE
ENDPOINT
REGISTER HANDLER
EXTRACT HANDLE
START EVENT LOOP
register_handler(acc)
get_handle()
handle_events()
select()
handle_input()
FOREACH EVENT DO
CONNECTION EVENT
CREATE, ACCEPT,
AND ACTIVATE OBJECT
REGISTER HANDLER
FOR CLIENT I/O
sh = make_svc_handler()
accept_svc_handler (sh)
activate_svc_handler (sh)
register_handler(sh)
EXTRACT HANDLE
DATA EVENT
PROCESS MSG
get_handle()
handle_input()
svc()
CLIENT SHUTDOWN
handle_close()
SERVER SHUTDOWN
handle_close()
is a factory that creates, connects,
and activates a Svc Handler
Acceptor
49
Using the Acceptor Pattern in the
Blob Server
: Blob
Acceptor
: Blob
Handler
: Acceptor
: Svc
Handler
1: handle_input()
2: sh = make_svc_handler()
3: accept_svc_handler(sh)
4: activate_svc_handler(sh)
PASSIVE LISTENER
: Blob
Handler
: Svc
Handler
ACTIVE
CONNECTIONS
: Reactor
: Blob
Handler
: Svc
Handler
: Blob
Handler
: Svc
Handler
50
The Acceptor Class
The Acceptor class implements the Acceptor
pattern
// Reusable Factor
template <class SVC_HANDLER>
class Acceptor :
public Service_Object // Subclass of Event_Handler.
{
public:
// Notified by Reactor when clients connect.
virtual int handle_input (void)
{
// The strategy for initializing a SVC_HANDLER.
SVC_HANDLER *sh = new SVC_HANDLER;
peer_acceptor_.accept (*sh);
sh->open ();
}
// ...
protected:
// IPC connection factory.
SOCK_Acceptor peer_acceptor_;
}
51
52
The Service Congurator Pattern
The Blob Acceptor Class
Interface
Intent
{
The Blob Acceptor class accepts connections
and initializes Blob Handlers
class Blob_Acceptor
: public Acceptor<Blob_Handler>
// Inherits handle_input() strategy from Acceptor.
{
public:
// Called when Blob_Acceptor is dynamically linked.
virtual int init (int argc, char *argv);
// Called when Blob_Acceptor is dynamically unlinked.
virtual int fini (void);
\Decouples the behavior of communication services from the point in time at which these services
are congured into an application or system"
This pattern resolves the following forces
for highly exible communication software:
{
How to defer the selection of a particular type, or
a particular implementation, of a service until very
late in the design cycle
.
i.e., at installation-time or run-time
{
How to build complete applications by composing
multiple independently developed services
{
How to optimize, recongure, and control the behavior of the service at run-time
54
53
APPLICATION
LAYER
Structure of the Service
Congurator Pattern
Collaboration in the Service
Congurator Pattern
Concrete
Service Object
main()
suspend()
resume()
init() A
fini()
info()
1
1
1
n
1
Event
Handler n
FOREACH SVC ENTRY DO
DYNAMICALLY LINK
SERVICE
INITIALIZE SERVICE
REGISTER SERVICE
EXTRACT HANDLE
: Reactor
: Service : Service
Config Repository
Service_Config()
process_directives()
link_service()
init(argc, argv)
register_handler(svc)
get_handle()
insert()
STORE IN REPOSITORY
START EVENT LOOP
Service
Repository
1
CONFIGURATION
MODE
Service
Config
Service
Object
EVENT HANDLING
MODE
REACTIVE
LAYER
CONFIGURATION
LAYER
CONFIGURE
svc :
Service_Object
FOREACH EVENT DO
INCOMING EVENT
SHUTDOWN EVENT
CLOSE SERVICE
UNLINK SERVICE
run_event_loop()
handle_events()
handle_input()
handle_close()
remove_handler(svc)
fini()
unlink_service()
remove()
Reactor
55
56
Using the Service Congurator
Pattern in the Blob Server
The Blob Acceptor Class
Implementation
// Initialize service when dynamically linked.
SERVICE
CONFIGURATOR
RUNTIME
: Service
Repository
: Service
Config
: Reactive
Blob Server
: TP
Blob Server
: Service
Object
: Reactor
SHARED
OBJECTS
: Service
Object
int Blob_Acceptor::init (int argc, char *argv[])
{
Options::instance ()->parse_args (argc, argv);
// Set the endpoint into listener mode.
Acceptor::open (local_addr);
: TPR
Blob Server
: Service
Object
}
// Initialize the communication endpoint.
Reactor::instance ()->register_handler
(this, READ_MASK)
// Terminate service when dynamically unlinked.
Existing service is based on Half-Sync/HalfAsync pattern
Other versions could be single-threaded or
use other concurrency strategies
:::
int Blob_Acceptor::fini (void)
{
// Unblock threads in the pool so they will
// shutdown correctly.
Blob_Processor::instance ()->close ();
}
// Wait for all threads to exit.
Thread_Manager::instance ()->wait ();
57
58
Conguring the Blob Server with
the Service Congurator
The concurrent Blob Server is congured
and initialized via a conguration script
% cat ./svc.conf
dynamic TP_Blob_Server Service_Object *
blob_server.dll:make_TP_Blob_Server()
"-p $PORT -t $THREADS"
Main Program for Blob Server
Dynamically congure and execute the Blob
Server
{
Note that this is totally generic!
int main (int argc, char *argv[])
{
Service_Config daemon;
// Initialize the daemon and dynamically
// configure the service.
daemon.open (argc, argv);
Factory function that dynamically allocates
a Half-Sync/Half-Async Blob Server object
// Loop forever, running services and handling
// reconfigurations.
extern "C" Service_Object *make_TP_Blob_Server (void);
Service_Object *make_TP_Blob_Server (void)
{
return new Blob_Acceptor;
// ACE dynamically unlinks and deallocates this object.
}
59
daemon.run_event_loop ();
}
/* NOTREACHED */
60
The Connector Pattern
{
Structure of the Connector
Pattern
Intent
\Decouples active initialization of a service from
the task performed once a service is initialized"
Service
Handler
This pattern resolves the following forces
for network clients that use interfaces like
sockets or TLI:
Service Handler
Connector
peer_stream_
open()
n
1. How to reuse active connection establishment code
for each new service
ACTIVATES
1
connect(sh, addr)
complete()
HANDLE ASYNC
CONNECTION COMPLETION
2. How to make the connection establishment code
portable across platforms that may contain sockets but not TLI, or vice versa
Reactor
3. How to enable exible service concurrency policies
4. How to actively establish connections with large
number of peers eciently
62
61
Collaboration in the Connector
Pattern
connect_svc_handler(sh, addr)
INITIATE CONNECTION
SYNC CONNECT
reactor :
Reactor
connect()
activate_svc_handler(sh)
ACTIVATE OBJECT
open()
INSERT IN REACTOR
EXTRACT HANDLE
START EVENT LOOP
FOREACH EVENT DO
DATA ARRIVES
PROCESS DATA
register_handler(sh)
get_handle()
handle_events()
select()
handle_input()
svc()
CONNECTION
INITIATION
PHASE
FOREACH CONNECTION
peer_stream_
con :
sh:
: SOCK Svc_Handler
Connector
Connector
connect(sh, addr)
SERVICE
INITIALIZATION
PHASE
Client
Client
SERVICE
PROCESSING
PHASE
SERVICE
PROCESSING
PHASE
CONNECTION INITIATION/
INITIATION/
SEVICE INITIALIZATION
PHASE
Collaboration in the Connector
Pattern
FOREACH CONNECTION
peer_stream_
con :
sh:
Connector : SOCK Svc_Handler
Connector
connect(sh, addr)
connect_svc_handler(sh, addr)
INITIATE CONNECTION
ASYNC CONNECT
connect()
INSERT IN REACTOR
select()
handle_output()
activate_svc_handler(sh)
FOREACH EVENT DO
CONNECTION COMPLETE
ACTIVATE OBJECT
EXTRACT HANDLE
DATA ARRIVES
PROCESS DATA
register_handler(con)
handle_events()
START EVENT LOOP
INSERT IN REACTOR
reactor :
Reactor
open()
register_handler(sh)
get_handle()
handle_input()
svc()
Synchronous mode
63
Asynchronous mode
64
Using the Connector in the Blob
Clients
: Blob
Handler: Blob : Blob
Handler
Handler
: Svc
Handler: Svc : Svc
Handler
Handler
PENDING
CONNECTIONS
: Blob
Handler
: Blob
Handler
: Svc
Handler
: Svc
Handler
A
C TIVE
CONNECTIONS
: Blob
Connector
: Connector
: Reactor
: Blob
Handler
Benets of Design Patterns
Design patterns enable large-scale reuse of
software architectures
Patterns explicitly capture expert knowledge
and design tradeos
Patterns help improve developer communication
Patterns help ease the transition to objectoriented technology
: Svc
Handler
: Blob
Handler
: Svc
Handler
65
66
Suggestions for Using Patterns
Eectively
Drawbacks to Design Patterns
Patterns do not lead to direct code reuse
Patterns are deceptively simple
Teams may suer from pattern overload
Patterns are validated by experience and discussion rather than by automated testing
Integrating patterns into a software development process is a human-intensive activity
67
Do not recast everything as a pattern
{
Instead, develop strategic domain patterns and reuse
existing tactical patterns
Institutionalize rewards for developing patterns
Directly involve pattern authors with application developers and domain experts
Clearly document when patterns apply and
do not apply
Manage expectations carefully
68
Books and Magazines on Patterns
Books
{
Gamma et al., \Design Patterns: Elements of
Reusable Object-Oriented Software" Addison-Wesley,
Reading, MA, 1994.
{
\Pattern Languages of Program Design," editors
James O. Coplien and Douglas C. Schmidt, AddisonWesley, Reading, MA, 1995
Special Issues in Journals
{
\Theory and Practice of Object Systems" (guest
editor: Stephen P. Berczuk)
{
\Communications of the ACM" (guest editors: Douglas C. Schmidt, Ralph Johnson, and Mohamed
Fayad)
Magazines
{
C++ Report and Journal of Object-Oriented Programming, columns by Coplien, Vlissides, and De
Souza
69
Obtaining ACE
The ADAPTIVE Communication Environment (ACE) is an OO toolkit designed according to key network programming patterns
All source code for ACE is freely available
{
Anonymously ftp to wuarchive.wustl.edu
{
Transfer the les /languages/c++/ACE/*.gz and
gnu/ACE-documentation/*.gz
Mailing lists
* [email protected]stl.edu
* [email protected]
* [email protected]
* [email protected]
WWW URL
{
http://www.cs.wustl.edu/~schmidt/ACE.html
71
Conferences and Workshops on
Patterns
1st EuroPLoP
{
3rd Pattern Languages of Programs Conference
{
July 10,14, 1996, Kloster Irsee, Germany
September 4,6, 1996, Monticello, Illinois, USA
Relevant WWW URLs
http://www.cs.wustl.edu/~schmidt/jointPLoP,96.html/
http://st-www.cs.uiuc.edu/users/patterns/patterns.html
70