ACE Tutorial
ACE Tutorial
Douglas C. Schmidt
Professor [email protected] www.cs.wustl.edu/schmidt/ Department of EECS Vanderbilt University (615) 343-8197
Sponsors
NSF, DARPA, ATD, BBN, Boeing, Cisco, Comverse, GDIS, Experian, Global MT, Hughes, Kodak, Krones, Lockheed, Lucent, Microsoft, Mitre, Motorola, NASA, Nokia, Nortel, OCI, Oresis, OTI, QNX, Raytheon, SAIC, Siemens SCR, Siemens MED, Siemens ZT, Sprint, Telcordia, USENIX
Douglas C. Schmidt
Observations
WTS
EVENT CHANNEL
Cons
Cons Cons
DISTRIBUTION MIDDLEWARE
Historically, apps built atop OS Today, apps built atop middleware Middleware has multiple layers Just like network protocol stacks
www.cs.wustl.edu/schmidt/PDF/ middleware-chapter.pdf
Vanderbilt University 1
Douglas C. Schmidt
maxfdp1
CLIENT
Leverage hardware/software
e.g., multi-processors and OS thread support
read_fds
WORK REQUEST WORK REQUEST WORK REQUEST
CLIENT
CLIENT
WORK REQUEST
CLIENT
Increase performance
e.g., overlap computation and communication
Improve response-time
CLIENT
CLIENT
Vanderbilt University
Douglas C. Schmidt
CD ROM
Extensibility dynamic conguration and reconguration Cost effectiveness open systems and resource sharing
Vanderbilt University
Douglas C. Schmidt
Vanderbilt University
Douglas C. Schmidt
Caveats
OO is not a panacea Though when used properly it helps minimize accidental complexity and improve software quality factors Its also essential to understand advanced OS features to enhance functionality and performance, e.g.,
Multi-threading Multi-processing Synchronization Shared memory Explicit dynamic linking Communication protocols and IPC mechanisms
Vanderbilt University
Douglas C. Schmidt
Tutorial Outline
Brief overview of key OO networking and concurrency concepts and OS platform mechanisms Emphasis is on practical solutions Examine a range of examples in detail
Networked Logging Service Concurrent Web Server Application-level Telecom Gateway Call Center Manager Event Server
Discuss general concurrent programming strategies Provide URLs for further reading on the topic
Vanderbilt University
Douglas C. Schmidt
Vanderbilt University
Douglas C. Schmidt
Sources of Complexity
PRINTER
Inherent complexity
FILE SYSTEM
COMPUTER
CD ROM
Accidental Complexity Low-level APIs Poor debugging tools Algorithmic decomposition Continuous re-invention
8
Vanderbilt University
Douglas C. Schmidt
Vanderbilt University
Douglas C. Schmidt
Douglas C. Schmidt
fork/exec Shared memory and semaphores Memory-mapped les Signals sockets/select Low-level thread APIs
Service functionality and policies Service conguration Concurrent event demultiplexing and event handler dispatching Service concurrency and synchronization
11
Vanderbilt University
Douglas C. Schmidt
Overview of Patterns
Patterns represent solutions to problems that arise when developing software within a particular context i.e., Patterns == problem/solution pairs within a context Patterns capture the static and dynamic structure and collaboration among key participants in software designs They are particularly useful for articulating how and why to resolve non-functional forces Patterns facilitate reuse of successful software architectures and designs
Vanderbilt University
12
Do
3: CLIENT
RESPONSE
2: FORWARD
REQUEST
NETWORK
: QUOTER
SERVER
Vanderbilt University
Douglas C. Schmidt
Vanderbilt University
14
Douglas C. Schmidt
MATH CLASSES
Key distinctions
ADT
CLASSES DATABASE CLASSES
Class libraries
Reusable building blocks Domain-independent Limited in scope Passive
EVENT LOOP
GLUE CODE
GUI
CLASSES
NETWORK
IPC
CLASSES
(A) CLASS
LIBRARY ARCHITECTURE
NETWORKING
EVENT LOOP
ADT
CLASSES INVOKES MATH CLASSES
Frameworks
GUI
EVENT LOOP
APPLICATIONSPECIFIC FUNCTIONALITY
CALL BACKS
DATABASE
EVENT LOOP
(B) FRAMEWORK
Vanderbilt University
ARCHITECTURE
Douglas C. Schmidt
STANDARDS BASED MIDDLEWARE
THE ACE ORB (TAO)
The ADAPTIVE Communication Environment (ACE) TOKEN SERVER NAME SERVER GATEWAY SERVER TIME SERVER LOGGING SERVER
FRAMEWORK LAYER
SERVICE HANDLER
ACCEPTOR
CONNECTOR
CORBA HANDLER
C++
WRAPPER FACADE LAYER
STREAMS
REACTOR/ PROACTOR
SERVICE CONFIGURATOR
OS ADAPTATION LAYER
C APIS
PROCESSES/ THREADS
SOCKETS/
TLI
UNIX FIFOS
SELECT/ IO COMP
DYNAMIC LINKING
SHARED MEMORY
PROCESS/THREAD SUBSYSTEM
COMMUNICATION SUBSYSTEM
www.cs.wustl.edu/schmidt/ACE.html
Vanderbilt University
16
Douglas C. Schmidt
ACE Statistics
ACE library contains 250,000 lines of C++ Over 40 person-years of effort Ported to UNIX, Windows, MVS, and RT/embedded platforms e.g., VxWorks, LynxOS, Chorus Large user and open-source developer community schmidt/ACE-users.html Currently used by dozens of companies Bellcore, BBN, Boeing, Ericsson, Hughes, Kodak, Lockheed, Lucent, Motorola, Nokia, Nortel, Raytheon, SAIC, Siemens, etc. Supported commercially by Riverace www.riverace.com
Vanderbilt University 17
Douglas C. Schmidt
Streams
Task
ACE contains a number of frameworks that can be used separately or together This design permits ne-grained subsetting of ACE components Subsetting helps minimize ACEs memory footprint $ACE_ROOT/doc/ACE-subsets.html
Vanderbilt University 18
Douglas C. Schmidt
Observation
Failures rarely result from unknown scientic principles, but from failing to apply proven engineering practices and patterns
Benets of Patterns Facilitate design reuse Preserve crucial design information Guide design choices
19
Event Patterns
Vanderbilt University
Douglas C. Schmidt
CLIENT
OBJ REF
operation()
out args + return value
TAO Overview ! A real-time, high-performance ORB Leverages ACE Runs on POSIX, Windows, RTOSs Related efforts ! QuO at BBN MIC/GME at Vanderbilt XOTS
20
STUBS
IDL
ORB RUN-TIME
SCHEDULER
SKELETON
IOP
IOP
COMPONENTS
ACE
NETWORK
www.cs.wustl.edu/schmidt/TAO. html
Vanderbilt University
Douglas C. Schmidt
TAO Statistics
TAO order of magnitude Core ORB 300,000 LOC IDL compiler 200,000 LOC CORBA Object Services 250,000 LOC Leverages ACE heavily Ported to UNIX, Windows, & RT/embedded platforms e.g., VxWorks, LynxOS, Chorus, WinCE
50 person-years of effort
Currently used by many companies e.g., Boeing, BBN, Lockheed, Lucent, Motorola, Raytheon, SAIC, Siemens, etc. Supported commercially by OCI and PrismTech www.ociweb.com www.prismtechnologies.com
Vanderbilt University
21
Douglas C. Schmidt
WWW
SERVER
JAWS Overview A high-performance Web server Flexible concurrency and dispatching mechanisms Leverages the ACE framework Ported to most OS platforms Used commercially by CacheFlow www.cacheow.com
HTML
PARSER
PROTOCOL HANDLERS
GUI
REQUESTER
DISPATCHER
GRAPHICS ADAPTER
OS KERNEL
OS I/O SUBSYSTEM NETWORK ADAPTERS
OS KERNEL
OS I/O SUBSYSTEM NETWORK ADAPTERS
NETWORK
www.cs.wustl.edu/jxh/ research/
Vanderbilt University
22
Douglas C. Schmidt
Java ACE
DISTRIBUTED SERVICES AND COMPONENTS TOKEN SERVER LOGGING SERVER NAME SERVER TIME SERVER
Java ACE Overview A Java version of ACE Used for medical imaging prototype
ACCEPTOR
CONNECTOR
SERVICE HANDLER
JAVA
SYNCH
WRAPPERS WRAPPERS
SOCK_SAP
THREAD MANAGER
LOG MSG
TIMER QUEUE
SERVICE CONFIGURATOR
23
Do
P1 P2
LOCAL
IPC
CONSOLE
P3
RE MO TE
IPC
HOST
CLIENT
SERVER
NETWORK
HOST
RE MO TE
IPC
STORAGE DEVICE
CLIENT P2
P1
LOCAL
IPC
P3
Intent: Server logging daemon collects, formats, and outputs logging records forwarded from client logging daemons residing throughout a network or Internet
Vanderbilt University
Douglas C. Schmidt
and
ACE_DEBUG ((LM_DEBUG, "(%t) sending to server %s", server_host));
Douglas C. Schmidt
Vanderbilt University
26
Do
NETWORK
CLIENT CONNECTION REQUEST
LOGGING RECORDS
LOGGING RECORDS
LOGGING RECORDS
CLIENT
CLIENT
CLIENT
Vanderbilt University
Do
Vanderbilt University
Do
Vanderbilt University
Do
Do
Vanderbilt University
Do
Vanderbilt University
Do
Vanderbilt University
Do
Do
Vanderbilt University
Douglas C. Schmidt
Douglas C. Schmidt
Vanderbilt University
37
Douglas C. Schmidt
OO Contributions to Software
Patterns facilitate the large-scale reuse of software architecture
Even when reuse of algorithms, detailed designs, and implementations is not feasible
Vanderbilt University
38
Douglas C. Schmidt
Acceptor Reactor
Adapter
Iterator
Factory Method
Template Method
Wrapper Facade
Strategic and tactical are relative to the context and abstraction level
Vanderbilt University 39
Douglas C. Schmidt
Wrapper Facade ! Encapsulates the functions and data provided by existing non-OO APIs within more concise, robust, portable, maintainable, and cohesive OO class interfaces Reactor ! Demultiplexes and dispatches requests that are delivered concurrently to an application by one or more clients Acceptor ! Decouple the passive connection and initialization of a peer service in a distributed system from the processing performed once the peer service is connected and initialized Component Congurator ! Decouples the implementation of services from the time when they are congured Active Object ! Decouples method execution from method invocation to enhance concurrency and simplify synchronized access to an object that resides in its own thread of control
Vanderbilt University 40
Douglas C. Schmidt
Do
Logging Acceptor
n
<<activates>>
Logging Handler
CONNECTIONORIENTED COMPONENTS
SVC_HANDLER PEER_ACCEPTOR
PEER_STREAM SYNCH_STRAT
Acceptor
Svc Handler
PEER ACCEPTOR
PEER STREAM
Connection IPC_SAP
Stream
Service Configurator
Concurrency
Reactor
Vanderbilt University
Douglas C. Schmidt
Vanderbilt University
43
Douglas C. Schmidt
Encapsulates the functions and data provided by existing lower-level, non-OO APIs within more concise, robust, portable, maintainable, and cohesive higher-level OO class interfaces
client
1: method_k()
Wrapper Facade
method_1() ... method_m()
2: function_k()
Functions
function_1() ... function_n()
Forces Resolved Avoid tedious, error-prone, and non-portable system APIs Create cohesive abstractions
Vanderbilt University 44
Do
1: PASSIVE
ROLE
3: SERVICE
CLIENT
NETWORK
SERVER
Sockets are the most common network programming API and are available on most OS platforms
Vanderbilt University
Douglas C. Schmidt
Douglas C. Schmidt
Vanderbilt University
47
Douglas C. Schmidt
Vanderbilt University
Douglas C. Schmidt
Limitations Socket API is linear rather than hierarchical There is no consistency among names... Non-portable
Vanderbilt University
socket() bind() connect() listen() accept() read() write() readv() writev() recv() send() recvfrom() sendto() recvmsg() sendmsg() setsockopt() getsockopt() getpeername() getsockname() gethostbyname() getservbyname()
49
Do
Socket Taxonomy
N/ TIO ION EC AT E NN NIC SIV S CO MU LE PA M RO ER CO XF IVE CT A
COMMUNICATION DOMAIN LOCAL LOCAL/REMOTE
DATA GRAM
socket(PF_INET)/bind() sendto()/recvfrom()
socket(PF_INET)/bind()
socket(PF_UNIX) socket(PF_INET) bind()/connect() bind()/connect() send()/recv() send()/recv() socket(PF_UNIX) socket(PF_INET) bind()/connect() bind()/connect()
bind()/listen()/accept()
socket(PF_UNIX)
bind()/listen()/accept()
socket(PF_INET)
The Socket API can be classied along three dimensions 1. Connection role 2. Communication domain 3. Type of service
Vanderbilt University
Do
CONNECTED DATAGRAM
DATA GRAM
LSOCK_Dgram LSOCK_CODgram
STREAM
The ACE C++ wrapper facades more explicitly model the key socket components using OO classes
Vanderbilt University
Do
ACE_SOCK_IO
ACE_SOCK
ACE_SOCK_Acceptor
ACE_INET_Addr
ACE_SOCK_Stream
ACE_SOCK_Connector
Participants Passive and active connection factories ACE_SOCK_Acceptor and ACE_SOCK_Connector Streaming classes ACE_SOCK_Stream and ACE_SOCK_IO Addressing classes ACE_Addr and ACE_INET_Addr
Vanderbilt University
Douglas C. Schmidt
ACE_SOCK_Acceptor (const ACE_INET_Addr &); int open (const ACE_INET_Addr &addr); int accept (ACE_SOCK_Stream &new_sap, ACE_INET_Addr *, ACE_Time_Value *); //... };
Vanderbilt University
53
Douglas C. Schmidt
Vanderbilt University
54
Douglas C. Schmidt
Do
Do
Douglas C. Schmidt
TLI SAP
TLI API
SPIPE SAP
STREAM PIPE API
SSL SAP
SSL API
FIFO SAP
NAMED PIPE API
MEM SAP
MMAP API
SysV IPC
SYSTEM V IPC API
C++NPv1 (www.cs.wustl.edu/schmidt/ACE/book1/)
Vanderbilt University
58
Do
Do
Vanderbilt University
Do
Vanderbilt University
Do
Vanderbilt University
Do
Vanderbilt University
Douglas C. Schmidt
Vanderbilt University
64
Douglas C. Schmidt
Douglas C. Schmidt
Vanderbilt University
66
Douglas C. Schmidt
Vanderbilt University
67
Douglas C. Schmidt
Vanderbilt University
68
Do
Note that SVR4 and BSD 4.4 APIs are different than BSD 4.3!
Vanderbilt University
Douglas C. Schmidt
Vanderbilt University
70
Douglas C. Schmidt
ACE SOCK
ACE LSOCK
CONNECTION ESTABLISHMENT
Vanderbilt University
71
Douglas C. Schmidt
(PARAMETERIZED TYPES)
COMMON INTERFACE
SOCK_SAP
SOCKET BSDSOCKET API API
TLI_SAP
BSDSOCKET SYSTEM V API TLI API
USER SPACE
// Conditionally select IPC mechanism. #if defined (USE_SOCKETS) typedef ACE_SOCK_Acceptor PEER_ACCEPTOR; #elif defined (USE_TLI) typedef ACE_TLI_Acceptor PEER_ACCEPTOR; #endif // USE_SOCKETS. int main (void) { // ... // Invoke with appropriate // network programming interface. echo_server<PEER_ACCEPTOR> (port); }
KERNEL SPACE
Switching wholesale between sockets and TLI simply requires instantiating a different ACE C++ wrapper facade
Vanderbilt University 72
Douglas C. Schmidt
Vanderbilt University
73
Douglas C. Schmidt
e.g., easy to neglect to zero-out a sockaddr_in or convert port numbers to network byte-order, etc.
ACE C++ Socket wrapper facades dene classes to handle details
class ACE_INET_Addr : public ACE_Addr { public: ACE_INET_Addr (u_short port, long ip_addr = 0) { memset (&this->inet_addr_, 0, sizeof this->inet_addr_); this->inet_addr_.sin_family = AF_INET; this->inet_addr_.sin_port = htons (port); memcpy (&this->inet_addr_.sin_addr, &ip_addr, sizeof ip_addr); } // ... private: sockaddr_in inet_addr_; };
Vanderbilt University 74
Douglas C. Schmidt
Solution Use the Reactor pattern to decouple event demuxing/dispatching from server-specic processing
Vanderbilt University 75
Douglas C. Schmidt
Intent
Handle
notifies
Demuxes & dispatches requests that are delievered concurrency to an application by one or more clients
Forces Resolved Serially demux events synchronously & efciently Extend applications without changing demuxing code
www.cs.wustl.edu/schmidt/ POSA/
Vanderbilt University
76
Douglas C. Schmidt
INITIALIZATION MODE
Note inversion of control Also note how long-running event handlers can degrade quality of service since callbacks steal Reactors thread of control...
INITIALIZE
DATA ARRIVES OK TO SEND SIGNAL ARRIVES TIMER EXPIRES REMOVE HANDLER CLEANUP
Vanderbilt University
77
Do
0..1
ACE_Reactor
ACE_Reactor_Impl
ACE_WFMO_Reactor
TOKEN
ACE_Select_Reactor_Impl
ACE_Select_Reactor_T
bind <ACE_Select_Reactor_Token>
ACE_TP_Reactor
ACE_Select_Reactor
Vanderbilt University
Do
FRAMEWORK LEVEL
APPLICATION LEVEL
:Timer Queue
: Handle Table
: Reactor
KERNEL LEVEL
Vanderbilt University
Douglas C. Schmidt
Do
peer_stream_ open()
APPLICATIONDEFINED
Acceptor
ACTIVATES
peer_acceptor_ accept()
APPLICATIONINDEPENDENT
Reactor
Decouple the passive connection and initialization of a peer service in a distributed system from the processing performed once the peer service is connected and initialized
Vanderbilt University
Reuse passive connection setup and service initialization code Ensure that acceptor-mode handles arent used to read/write data
Do
ACE_Task
ACE_Connector
PEER_STREAM, SYNCH_STRATEGY SVC_HANDLER, PEER_ACCEPTOR
ACE_Svc_Handler
bind
ACE_Acceptor
Application Service
Framework characteristics Uses C++ parameterized types to strategize IPC and service aspects Uses Template Method pattern to strategize creation, connection establishment, and concurrency policies
Vanderbilt University
Do
PASSIVE LISTENER
ACTIVE CONNECTIONS
: Reactor
The ACE_Acceptor is a factory i.e., it creates, connects, and activates an ACE_Svc_Handler Theres often one ACE_Acceptor per-service/per-port
Vanderbilt University
Do
Vanderbilt University
Do
Vanderbilt University
Douglas C. Schmidt
Intent
... primitive_operation1() ... primitive_operation2() ...
Concrete Class
primitive_operation1() primitive_operation2()
Vanderbilt University
86
Douglas C. Schmidt
Benets Straightforward to program via inheritance and dynamic binding Liabilities Design is brittle and can cause explosion of subclasses due to whitebox design
My Acceptor
make_svc_handler() activate_svc_handler()
Vanderbilt University
87
Douglas C. Schmidt
Strategy
algorithm_interface()
Dene a family of algorithms, encapsulate each one, and make them interchangeable
Gamma et al., Design Patterns: Elements of Reusable Object-Oriented Software AW, 94
Concrete Strategy A
algorithm_interface()
Concrete Strategy C
algorithm_interface()
Concrete Strategy B
algorithm_interface()
Vanderbilt University
88
Douglas C. Schmidt
Concurrency Strategy
activate_svc_handler()
Benets More extensible due to blackbox design Liabilities More complex and harder to develop initially
Reactive Strategy
Thread Strategy
Process Strategy
Vanderbilt University
89
Do
Vanderbilt University
Do
Vanderbilt University
Do
Vanderbilt University
Douglas C. Schmidt
ACE_Svc_Handler Implementation
#define PS PEER_STREAM #define SS SYNCH_STRAT template <class PS, class SS> ACE_Svc_Handler<PS, SS>::ACE_Svc_Handler (ACE_Reactor *r): ACE_Service_Object (r) {} template <class PS, class SS> int ACE_Svc_Handler<PS, SS>::open (void *) { // Enable non-blocking I/O. peer ().enable (ACE_NONBLOCK); // Register handler with the Reactor. reactor ()->register_handler (this, ACE_Event_Handler::READ_MASK); }
By default, a ACE_Svc_Handler object is registered with the singleton ACE_Reactor This makes the service reactive so that no other synchronization mechanisms are necessary
Vanderbilt University
93
Do
Reactor
LOGGING RECORDS
CONNECTION REQUEST
SERVER
Vanderbilt University
Do
Vanderbilt University
Douglas C. Schmidt
Vanderbilt University
96
Douglas C. Schmidt
int Logging_Handler::handle_input (ACE_HANDLE) { This is the main // Call existing function to recv supplied by a // logging record and print to stdout. developer! ssize_t n = handle_log_record (peer ().get_handle (), ACE_STDOUT); if (n > 0) // Count the # of logging records ++request_count; return n <= 0 ? -1 : 0; }
Vanderbilt University
97
Do
Douglas C. Schmidt
Douglas C. Schmidt
Concrete Component
Intent
CONFIGURATION LAYER
Component
suspend() resume() init() A fini() info()
Component Config n
1 1 1 1
Decouples the implementation of services from the time when they are congured
Forces Resolved Reduce resource utilization Support dynamic (re)conguration www.cs.wustl.edu/ schmidt/POSA/
100
Component Repository
REACTIVE LAYER
Event Handler n
Reactor
Vanderbilt University
Do
ACE_Service_Object
ACE_Service_Repository
Application Service
ACE_Service_Repository_Iterator
Framework characteristics ACE_Service_Config uses a variant of the Monostate pattern Can be accessed either via a script or programmatically
Vanderbilt University
Do
Using the ACE Service Congurator Framework for the Logging Server
SERVICE CONFIGURATOR RUNTIME
svc.conf
FILE
The existing Logging Server service is single-threaded Other versions could be multi-threaded Note how we can script this via the svc.conf le
Vanderbilt University
Douglas C. Schmidt
Application-specic factory function used to dynamically create a service The make_Logger() function provides a hook between an application-specic service and the application-independent ACE mechanisms ACE handles all memory allocation and deallocation
Vanderbilt University
103
Douglas C. Schmidt
Service Conguration
The logging service is congured Generic event-loop to dynamically congure service via scripting in a svc.conf le: daemons % cat ./svc.conf
# Dynamically configure int main (int argc, char *argv[]) # the logging service { dynamic Logger // Initialize the daemon and Service_Object * // configure services logger:_make_Logger() "-p 2001" ACE_Service_Config::open (argc, # Note, .dll or .so suffix argv); # added to the logger // Run forever, performing the # automatically // configured services ACE_Reactor::instance ()-> run_reactor_event_loop (); /* NOTREACHED */ }
Vanderbilt University
104
Douglas C. Schmidt
SHUTDOWN/ Service_Config::close()
RECONFIGURE/ Service_Config::process_directives()
Douglas C. Schmidt
We can use the techniques discussed thus far to extend applications without: Modifying, recompiling, and relinking existing code Terminating and restarting executing daemons The remainder of the Logging Server slides examine a set of techniques for decoupling functionality from concurrency mechanisms, as well
Vanderbilt University 106
Douglas C. Schmidt
Vanderbilt University
107
Do
7: recv() 7: recv() 8: write() 8: write() Logging Handler Logging Handler 6: send() CLIENT B
Vanderbilt University
Douglas C. Schmidt
Vanderbilt University
109
Douglas C. Schmidt
Concurrency Overview
SHARED ADDRESS SPACE
A thread is a sequence of instructions executed in one or more processes One process ! stand-alone systems More than one process ! distributed systems
THREADS
PROCESS
Traditional OS processes contain a single thread of control This simplies programming since a sequence of execution steps is protected from unwanted interference by other execution sequences...
Vanderbilt University 110
Douglas C. Schmidt
e.g., asynchronous I/O Note that concurrency encompasses more than multi-threading...
2. Many existing programs utilize OS processes to provide coarse-grained concurrency
e.g., Client/server database applications Standard network daemons like UNIX INETD Multiple OS processes may share memory via memory mapping or shared memory and use semaphores to coordinate execution The OS kernel scheduler dictates process behavior
Vanderbilt University 111
Douglas C. Schmidt
Inefcient
The OS kernel is involved in synchronization and process management Difcult to exert ne-grained control over scheduling and priorities
Vanderbilt University 112
Douglas C. Schmidt
Modern OS Concurrency
Modern OS platforms typically provide a standard set of APIs that handle Process/thread creation and destruction Various types of process/thread synchronization and mutual exclusion Asynchronous facilities for interrupting long-running processes/threads to report errors and control program behavior Once the underlying concepts are mastered, its relatively easy to learn different concurrency APIs e.g., traditional UNIX process operations, Solaris threads, POSIX pthreads, WIN32 threads, Java threads, etc.
Vanderbilt University
113
Douglas C. Schmidt
Lightweight Concurrency
Modern operating systems provide lightweight mechanisms that manage and synchronize multiple threads within a process Some systems also allow threads to synchronize across multiple processes Benets of threads 1. Relatively simple and efcient to create, control, synchronize, and collaborate Threads share many process resources by default 2. Improve performance by overlapping computation and communication Threads may also consume less resources than processes 3. Improve program structure e.g., compared with using asynchronous I/O
Vanderbilt University 114
Do
SERVER
USER KERNEL
REQUEST
USER KERNEL
THREAD BLOCKED
SINGLETHREADED RPC
USER KERNEL
SERVER
USER KERNEL
REQUEST
SERVER
USER KERNEL
SERVICE EXECUTES
CLIENT
MULTITHREADED RPC
Vanderbilt University
Douglas C. Schmidt
KERNEL-LEVEL
PE
PE
PE
PE
PE
PE
PE
PE
SHARED MEMORY
PE
THREAD PROCESSING ELEMENT
LWP
LIGHTWEIGHT PROCESS
UNIX PROCESS
Vanderbilt University
116
Douglas C. Schmidt
Application Threads
Most process resources are Each thread also contains unique equally accessible to all threads information, e.g., in a process, e.g., Identier Virtual memory Register set (e.g., PC and SP) User permissions and access Run-time stack control privileges Signal mask Open les Priority Signal handlers Thread-specic data (e.g., errno) Note, there is no MMU protection for threads in a single process
Vanderbilt University 117
Douglas C. Schmidt
Vanderbilt University
118
Douglas C. Schmidt
Vanderbilt University
119
Douglas C. Schmidt
Douglas C. Schmidt
Do
Task
Thread
LOCK TYPE
Atomic Op
TYPE
Condition
TSS GUARDS
SYNCH WRAPPERS Mutex Null Mutex Thread Mutex Process Mutex Events RW Mutex File Lock Semaphore Thread Semaphore Process Semaphore
All ACE Concurrency mechanisms are ported to all OS platforms www.cs.wustl.edu/schmidt/ACE/ book1/
Vanderbilt University
Douglas C. Schmidt
Vanderbilt University
123
Do
Scheduler
dispatch() enqueue()
3: dispatch()
Activation List
Servant
1
Method Request
M1 M2 M3
www.cs.wustl.edu/schmidt/POSA/ Intent Forces Resolved Allow blocking operations Permit exible concurrency strategies
Decouples method execution from method invocation to enhance concurrency and simplify synchronized access to an object that resides in its own thread of control
Vanderbilt University
Do
: TASK
STATE
2: enqueue (msg)
1: put (msg)
6: put (msg)
t1 : Task
: Message Queue
t3 : Task
: TASK
STATE
: TASK
STATE
: Message Queue
ACTIVE
ACTIVE
The ACE Task framework can be used to implement the complete Active Object pattern or lighterweight subsets
Vanderbilt University
Douglas C. Schmidt
Vanderbilt University
126
Do
0..1
SYNCH
ACE_Thread_Manager
ACE_Task
SYNCH
ACE_Message_Block
* 1
ACE_Message_Queue
Framework characteristics 1. ACE_Tasks can register with an ACE_Reactor 2. They can be dynamically linked 3. They can queue data 4. They can run as active objects in 1 or more threads
Vanderbilt University
Douglas C. Schmidt
Vanderbilt University
128
Douglas C. Schmidt
Douglas C. Schmidt
4. template <SYNCH_STRATEGY> void * 1. ACE_Task::activate () ACE_Task<SYNCH_STRATEGY>::svc_run 2. ACE_Thread_Manager::spawn (ACE_Task<SYNCH_STRATEGY> *t) { (svc_run, this); // ... 3. _beginthreadex void *status = t->svc (); (0, 0, // ... svc_run, this, R UN-T I ME return status; // Thread return. 0, &thread_id); T HR EA D ST A CK }
Vanderbilt University
130
Douglas C. Schmidt
Vanderbilt University
131
Douglas C. Schmidt
Vanderbilt University
132
Douglas C. Schmidt
Vanderbilt University
Do
<<activates>>
SOCK_Stream NULL_Synch
CONNECTIONORIENTED COMPONENTS
SVC_HANDLER PEER_ACCEPTOR
PEER_STREAM SYNCH
Acceptor
Svc Handler
PEER ACCEPTOR
PEER STREAM
Connection IPC_SAP
Stream
Service Configurator
global
Concurrency
Reactor
Vanderbilt University
Do
Vanderbilt University
Do
Thr_Logging_Handler Implementation
Override denition in the ACE_Svc_Handler class to spawn a new thread
int Thr_Logging_Handler::open (void *) { // Spawn a new thread to handle // logging records with the client. activate (THR_DETACHED); }
Vanderbilt University
Douglas C. Schmidt
extern "C" % cat ./svc.conf ACE_Service_Object *make_Logger (void); # Dynamically reconfigure # the logging service ACE_Service_Object * remove Logger make_Logger (void) dynamic Logger { Service_Object * return new Thr_Logging_Acceptor; thr_logger:_make_Logger() } "-p 2002" # .dll or .so suffix added to # "thr_logger" automatically
Logging service is recongured by changing the svc.conf le and sending SIGHUP signal to server
Vanderbilt University 137
Douglas C. Schmidt
Vanderbilt University
138
Douglas C. Schmidt
Douglas C. Schmidt
Error-prone
C++ exception handling and multiple method exit points Thread mutexes wont work for separate processes Global mutexes may not be initialized correctly
Non-portable ! Hard-coded to Solaris 2.x Inefcient ! e.g., expensive for certain platforms/designs
Vanderbilt University 140
Do
Note how we prevent improper copying and assignment by using C++ access control speciers
Vanderbilt University
Do
Vanderbilt University
Douglas C. Schmidt
However, this doesnt really solve the tedium or error-proneness problems www.cs.wustl.edu/schmidt/PDF/ObjMan.pdf
Vanderbilt University 143
Douglas C. Schmidt
ACE_Guard uses the Scoped Locking idiom whereby a constructor acquires a resource and the destructor releases the resource
Vanderbilt University 144
Douglas C. Schmidt
#define ACE_GUARD(MUTEX,OB,LOCK) \ ACE_Guard<MUTEX> OB (LOCK); if (OB.locked () == 0) return; #define ACE_GUARD_RETURN(MUTEX,OB,LOCK,RET) \ ACE_Guard<MUTEX> OB (LOCK); if (OB.locked () == 0) return RET; #define ACE_WRITE_GUARD(MUTEX,OB,LOCK) \ ACE_Write_Guard<MUTEX> OB (LOCK); if (OB.locked () == 0) return; #define ACE_WRITE_GUARD_RETURN(MUTEX,OB,LOCK,RET) \ ACE_Write_Guard<MUTEX> OB (LOCK); if (OB.locked () == 0) return RET; #define ACE_READ_GUARD(MUTEX,OB,LOCK) \ ACE_Read_Guard<MUTEX> OB (LOCK); if (OB.locked () == 0) return; #define ACE_READ_GUARD_RETURN(MUTEX,OB,LOCK,RET) \ ACE_Read_Guard<MUTEX> OB (LOCK); if (OB.locked () == 0) return RET;
Vanderbilt University 145
Do
Douglas C. Schmidt
Douglas C. Schmidt
Intent
Adapter
request() 2: specific_request()
Vanderbilt University
Douglas C. Schmidt
Remaining Caveats
int Logging_Handler::handle_input (void) { ssize_t n = handle_log_record (peer ().get_handle (), ACE_STDOUT); if (n > 0) // Count # of logging records. ++request_count; // Danger, race condition!!! return n <= 0 ? -1 : 0; }
There is a race condition when incrementing the request_count variable Solving this problem using the ACE_Thread_Mutex or ACE_Guard classes is still tedious, low-level, and error-prone
A more elegant solution incorporates parameterized types, overloading, and the Strategized Locking pattern, as discussed in C++NPv1
Vanderbilt University
149
Do
Vanderbilt University
Douglas C. Schmidt
Vanderbilt University
151
Douglas C. Schmidt
Vanderbilt University
152
Do
WWW
SERVER
HTML
PARSER
PROTOCOL HANDLERS
GUI
REQUESTER
DISPATCHER
GRAPHICS ADAPTER
OS KERNEL
OS I/O SUBSYSTEM NETWORK ADAPTERS
OS KERNEL
OS I/O SUBSYSTEM NETWORK ADAPTERS
NETWORK
www.cs.wustl.edu/jxh/research/
Vanderbilt University
Do
Vanderbilt University
Douglas C. Schmidt
Drawbacks
Using a message queue may lead to greater context switching and synchronization overhead... Single point for bottlenecks
Vanderbilt University 155
Do
Vanderbilt University
Do
Vanderbilt University
Do
Vanderbilt University
Douglas C. Schmidt
Vanderbilt University
159
Douglas C. Schmidt
Vanderbilt University
160
Douglas C. Schmidt
Douglas C. Schmidt
Monitor Object
Synchronizes method execution to ensure only one method runs within an object at a time. It also allows an objects methods to cooperatively schedule their execution sequences.
Forces Resolved Synchronization corresponds to methods
schmidt/POSA/
Objects, not clients, are responsible for synchronization Cooperative method scheduling
Vanderbilt University
162
Douglas C. Schmidt
Vanderbilt University
163
Douglas C. Schmidt
// synchronized void acquire_resources (void) { // synchronized // Automatically acquire lock. void release_resources (void) { ACE_GUARD (ACE_Thread_Mutex, g, lock); // Automatically acquire lock. ACE_GUARD (ACE_Thread_Mutex, g, lock); // Check condition in loop while (condition expression false) // Atomically modify shared // Sleep. // information... cond.wait (); cond.signal (); // Atomically modify shared // Could use cond.broadcast() here. // information. // guard automatically // Destructor releases lock. // releases lock. } }
Note how the use of the Scoped Locking idiom simplies the solution since we cant forget to release the lock!
Vanderbilt University
164
Douglas C. Schmidt
The ACE_Condition_ Thread_Mutex class is a wrapper for the native OS condition variable abstraction
e.g., cond_t on SunOS 5.x, pthread_cond_t for POSIX, and a custom implementation on Windows and VxWorks
Vanderbilt University
165
Douglas C. Schmidt
head_ tail_
Message Block
Data_Block
An ACE_Message_Queue is a list of ACE_Message_Blocks Efciently handles arbitrarily-large message payloads An ACE_Message_Block is a Composite Similar to BSD mbufs or SVR4 STREAMS m_blks Design parameterizes synchronization and allocation aspects
166
Message Block
Data_Block
Message Block
Data_Block
Message Block
Data_Block
Vanderbilt University
Do
ACE_Message _Block
cont() data_block() wr_ptr() rd_ptr()
ACE_Message _Block
cont() data_block() rd_ptr() wr_ptr()
ACE_Data _Block
PAYLOAD (1) SIMPLE MESSAGE STRUCTURE
reference_count() = 2
ACE_Data_Block
Vanderbilt University
Do
ACE_Message_Queue
# # # # head_ : ACE_Message_Block * tail_ : ACE_Message_Block * high_water_mark_ : size_t low_water_mark_ : size_t
+ ACE_Message_Queue (high_water_mark : size_t = DEFAULT_HWM, low_water_mark : size_t = DEFAULT_LWM, notify : ACE_Notification_Strategy * = 0) + open (high_water_mark : size_t = DEFAULT_HWM, low_water_mark : size_t = DEFAULT_LWM, notify : ACE_Notification_Strategy * = 0) : int + flush () : int + notification_strategy (s : ACE_Notification_Strategy *) : void + is_empty () : int + is_full () : int + enqueue_tail (item : ACE_Message_Block *, timeout : ACE_Time_Value * = 0) : int + enqueue_head (item : ACE_Message_Block *, timeout : ACE_Time_Value * = 0) : int + enqueue_prio (item : ACE_Message_Block *, timeout : ACE_Time_Value * = 0) : int + dequeue_head (item : ACE_Message_Block *&, timeout : ACE_Time_Value * = 0) : int + dequeue_tail (item : ACE_Message_Block *&, timeout : ACE_Time_Value * = 0) : int + high_water_mark (new_hwm : size_t) : void + high_water_mark (void) : size_t + low_water_mark (new_lwm : size_t) : void + low_water_mark (void) : size_t + close () : int + deactivate () : int + activate () : int + pulse () : int + state () : int
Do
Vanderbilt University
Douglas C. Schmidt
170
Do
Vanderbilt University
Douglas C. Schmidt
Do
Vanderbilt University
Douglas C. Schmidt
ACE_Message_Queue Operations
template <class SYNCH_STRAT> int template <class SYNCH_STRAT> int ACE_Message_Queue<SYNCH_STRAT>:: ACE_Message_Queue<SYNCH_STRAT>:: enqueue_tail (ACE_Message_Block *item, dequeue_head (ACE_Message_Block *&item, ACE_Time_Value *tv) { ACE_Time_Value *tv) { ACE_GUARD_RETURN (SYNCH_STRAT::MUTEX, ACE_GUARD_RETURN (SYNCH_STRAT::MUTEX, guard, lock_, -1); guard, lock_, -1); // Wait while the queue is empty. // Wait while the queue is full. while (is_empty_i ()) { while (is_full_i ()) { // Release lock_ and wait for timeout, // Release the <lock_> and wait // signal, or a new message being // for timeout, signal, or space // placed in the list. // to become available in the list. if (not_empty_cond_.wait (tv) == -1) if (not_full_cond_.wait (tv) == -1) return -1; return -1; } } // Actually dequeue the first message. // Actually enqueue the message at dequeue_head_i (item); // the end of the list. enqueue_tail_i (item); // Tell blocked threads that list // is no longer full. // Tell blocked threads that if (cur_bytes_ <= low_water_mark_) // list has a new item! not_full_cond_.signal (); not_empty_cond_.signal (); } }
Vanderbilt University
174
Douglas C. Schmidt
Douglas C. Schmidt
Vanderbilt University
176
Douglas C. Schmidt
Reactive Thread-per-request Thread-per-connection Synchronous Thread Pool Leader/Followers Thread Pool Half-Sync/Half-Async Thread Pool Asynchronous Thread Pool
Vanderbilt University
177
Do
HTTP Handler
HTTP Handler
Reactor
6: PROCESS
HTTP REQUEST
SERVER
1: CONNECT
CLIENT CLIENT CLIENT
Vanderbilt University
Do
HTTP Handler
Reactor
6: PROCESS
HTTP REQUEST
SERVER
1: CONNECT
CLIENT CLIENT CLIENT
Vanderbilt University
Do
2: CREATE, ACCEPT,
AND ACTIVATE HTTP_HANDLER
4: PROCESS
CLIENT
HTTP REQUEST
1: HTTP
REQUEST
SERVER
CLIENT
CLIENT
Vanderbilt University
Do
HTTP Acceptor
HTTP Acceptor
4: PROCESS
HTTP REQUEST
1: HTTP
CLIENT CLIENT CLIENT
REQUEST
SERVER
Vanderbilt University
Do
Active Object
Active Object
Active Object
Reactor
5: PROCESS
HTTP REQUEST
1: HTTP
REQUEST
Vanderbilt University
Do
HTTP Handler
6: DEQUEUE COMPLETION & PROCESS HTTP REQUEST Handler HTTP Handler HTTP Handler
Accept
Proactor
7: PROCESS
HTTP REQUEST
3: HTTP
REQUEST
Vanderbilt University
Do
HTTP Handler
Sock Stream
HTTP Acceptor
Sock Acceptor
Event Dispatcher
Event Dispatcher Encapsulates Web server concurrency and dispatching strategies HTTP Handlers Parses HTTP headers and processes requests HTTP Acceptor Accepts connections and creates HTTP Handlers
Vanderbilt University
Do
Thread-per Connection
Wrapper Facade
Singleton
Vanderbilt University
Douglas C. Schmidt
Do
svc_run
svc_run
svc_run
svc_run
QUEUEING LAYER
Options
HTTP Handler
I/O DEMUXING
LAYER
www.cs.wustl.edu/schmidt/PDF/HPL.pdf
Vanderbilt University
Do
HTTP Handler HTTP Handler HTTP Event Handler HTTP Handler Event Processor Handler Event Handler 2: recv_request(msg) 3: putq(msg)
1: handle_input()
APPLICATION
LEVEL
FRAMEWORK
LEVEL
: Handle Table
: Reactor
OS EVENT DEMULTIPLEXING INTERFACE
KERNEL
LEVEL
Douglas C. Schmidt
Douglas C. Schmidt
Douglas C. Schmidt
Integrating Multi-threading
Problem Multi-threaded Web servers are needed since Reactive Web servers are often inefcient and non-robust Forces Multi-threading can be very hard to program No single multi-threading model is always optimal Solution Use the Active Object pattern to allow multiple concurrent server operations in an OO-manner
Vanderbilt University
191
Do
Using the Active Object Pattern and ACE Task Framework in the Web Server
REGISTERED OBJECTS 4: getq(msg) 5:svc(msg) svc_run svc_run svc_run
HTTP Handler HTTP Handler HTTP Event Handler HTTP Handler Event Processor Handler Event Handler 2: recv_request(msg) 3: putq(msg)
1: handle_input()
APPLICATION
LEVEL
FRAMEWORK
LEVEL
: Handle Table
: Reactor
OS EVENT DEMULTIPLEXING INTERFACE
KERNEL
LEVEL
Douglas C. Schmidt
Processes HTTP requests using the Thread-Pool concurrency model This method implements the synchronous task portion of the HalfSync/Half-Async pattern
// Wait for messages to arrive. for (;;) { getq (mb); // Inherited from <ACE_Task> // Identify and perform HTTP // Server request processing...
Vanderbilt University
193
Do
Vanderbilt University
Douglas C. Schmidt
Vanderbilt University
195
Douglas C. Schmidt
Intent
Allows atomic initialization, regardless of initialization order, and eliminates subsequent locking overhead
Forces Resolved: Ensures atomic object initialization
HTTP Processor
static instance() static instance_
Mutex
Minimizes locking overhead Caveat! This pattern assumes atomic memory access
196
www.cs.wustl.edu/ schmidt/POSA/
Vanderbilt University
Douglas C. Schmidt
Douglas C. Schmidt
Vanderbilt University
198
Douglas C. Schmidt
Intent
QUEUEING
LAYER
1, 4: read(data)
MESSAGE QUEUES
Decouples synchronous I/O from asynchronous I/O in a system to simplify concurrent programming effort without degrading execution efciency
Forces Resolved: Simplify programming Ensure efcient I/O www.cs.wustl.edu/ schmidt/POSA/
199
ASYNCHRONOUS
TASK LAYER
3: enqueue(data)
ASYNC TASK
2: interrupt
EXTERNAL EVENT SOURCES
Vanderbilt University
Do
QUEUEING LEVEL
HTTP Processor
HTTP Handler HTTP Handler HTTP Event Handler Handler Event Handler Event Handler
ASYNC TASK LEVEL
1: handle_input() 2: recv_request(msg) 3: putq(msg) : Handle Table
: Reactor
Vanderbilt University
Do
Douglas C. Schmidt
Douglas C. Schmidt
Demultiplexes and dispatches service requests that are triggered by the completion of asynchronous operations
Resolves same forces as Reactor
HTTP Handler
Completion Handler
handle_accept() handle_read_file() handle_write_file() handle_timeout() get_handle() A
Async Op
open() cancel() 1
Async Accept
n Proactor
handle_events()
Handles
Timer_Queue
schedule_timer(h) cancel_timer(h)
www.cs.wustl.edu/schmidt/POSA/
Vanderbilt University
203
Do
ACE_Proactor
ACE_Asynch_Acceptor
ACE_Asynch_Connector
ACE_Handler
ACE_Asynch_Read_Stream
ACE_Asynch_Write_Stream
ACE_Asynch_Result
Framework characteristics Similar to the ACE Reactor framework, except behavior is inverse Portable to Windows and various UNIX platforms that support aio_*() family of methods
Vanderbilt University
Do
Web Server
7: create HTTP Handler 8: read (Handler, Dispatcher)
Operating System
6: write (File, Conn., 8: write Handler, Dispatcher) 5: read (File) 3: read complete complete 7: write complete Completion Operating File Dispatcher System System 2: read complete
Vanderbilt University
Douglas C. Schmidt
Do
PASSIVE LISTENER
ACTIVE CONNECTIONS
: Reactor
Vanderbilt University
Douglas C. Schmidt
Vanderbilt University
208
Do
Vanderbilt University
Douglas C. Schmidt
Reactive Web Server Service Object TPR Web Server Service Object
svc.conf
FILE
Vanderbilt University
210
Douglas C. Schmidt
Vanderbilt University
211
Douglas C. Schmidt
The main() function is totally generic! Dynamically congure & execute Web Server Make any application Web-enabled
Vanderbilt University
212
Douglas C. Schmidt
Tilde Expander
~
/home/...
Strategy
Event Dispatcher
www.cs.wustl.edu/jxh/research/
Vanderbilt University
Use lightweight concurrency Minimize locking Apply le caching and memory mapping Use gather-write mechanisms Minimize logging Pre-compute HTTP responses Avoid excessive time() calls Optimize the transport interface
Active Object
Strategy
Acceptor
213
Douglas C. Schmidt
STATUS INFO
This example explores the patterns and reusable framework components for an application-level Gateway The Gateway routes messages between Peers Gateway and Peers are connected via TCP/IP
GATEWAY
Vanderbilt University
214
Do
Supplier Handler
GATEWAY
CONNECTION REQUEST
OUTGOING MESSAGES
www.cs.wustl.edu/schmidt/PDF/ TAPOS-00.pdf All components in this architecture are based on patterns from ACE
Vanderbilt University
Douglas C. Schmidt
Gateway Behavior
Components in the Gateway behave as follows: 1. Gateway parses conguration les that specify which Peers to connect with and which routes to use 2. Proxy_Handler_Connector connects to Peers, then creates and activates Proxy_Handler subclasses (Supplier_Handler or Consumer_Handler) 3. Once connected, Peers send messages to the Gateway Messages are handled by an Supplier_Handler Supplier_Handlers work as follows: Receive and validate messages Consult a Routing_Table Forward messages to the appropriate Peer(s) via Consumer_Handlers
Vanderbilt University 216
Do
Reactor
TACTICAL Iterator Template Factory Proxy Wrapper PATTERNS Method Method Facade
Vanderbilt University
Do
SOCK_Stream Null_Synch
<<activates>>
Supplier/Consumer n Handler
CONNECTIONORIENTED COMPONENTS
SVC_HANDLER PEER_CONNECTOR
PEER_STREAM SYNCH
Connector
Svc Handler
PEER CONNECTOR
PEER STREAM
Connection IPC_SAP
Stream
Service Configurator
global
Concurrency
Reactor
Vanderbilt University
Douglas C. Schmidt
OO Gateway Architecture
Application-specic components
Proxy_Handlers route messages among Peers
Do
FRAMEWORK LEVEL
: Reactor
KERNEL LEVEL
Douglas C. Schmidt
Do
peer_stream_ open()
APPLICATIONDEFINED
Connector
ACTIVATES
Reactor
Decouple the active connection and initialization of a peer service in a distributed system from the processing performed once the peer service is connected and initialized
Vanderbilt University
Reuse connection code Efciently setup connections with many peers or over long delay paths
Douglas C. Schmidt
ACE_Task
Additional features of the ACE_Connector Uses C++ parameterized types to strategize IPC and service aspects Uses Template Method pattern to strategize creation, connection establishment, and concurrency policies
ACE_Connector
PEER_STREAM, SYNCH_STRATEGY SVC_HANDLER, PEER_ACCEPTOR
ACE_Svc_Handler
bind
ACE_Acceptor
Application Service
Vanderbilt University
223
Do
Svc Handler
Hash_Map
ACTIVE CONNECTIONS
Connector
PENDING CONNECTIONS
Svc Handler
Reactor
The ACE_Connector is a factory i.e., it connects and activates an ACE_Svc_Handler Theres typically 1 ACE_Connector per-service
Vanderbilt University
Do
Vanderbilt University
Do
Vanderbilt University
Do
, ,
Yes
time
Yes
NULL
No No
0,0 time
No
NULL
Vanderbilt University
Do
Vanderbilt University
Do
Vanderbilt University
Do
Vanderbilt University
Do
Svc Handler
Message Queue
Producing an application that meets Gateway requirements involves specializing ACE components ACE_Connector ! ACE_Proxy_Handler_Connector ACE_Svc_Handler ! ACE_Proxy_Handler ! ACE_Supplier_Handler and ACE_Consumer_Handler
Vanderbilt University
Do
Douglas C. Schmidt
Vanderbilt University
233
Douglas C. Schmidt
Do
Routing Table
Hash Map Manager
Supplier Handler
SOCK Stream
Connector
SOCK Connector Hash Map Manager
Acceptor
SOCK Acceptor
Consumer Handler
SOCK Stream Message Queue
GATEWAY
CONNECTION REQUEST
OUTGOING MESSAGES
Note the use of other ACE components, such as the socket wrapper facades and the ACE_Hash_Map_Manager
Vanderbilt University
Do
ACE_Supplier_Handler Interface
class Supplier_Handler : public Proxy_Handler { public: Supplier_Handler (void); protected: // Receive and process Peer messages. virtual int handle_input (ACE_HANDLE); // Receive a message from a Peer. virtual int recv_peer (ACE_Message_Block *&); // Action that routes a message from a Peer. int route_message (ACE_Message_Block *); // Keep track of message fragment. ACE_Message_Block *msg_frag_; };
Vanderbilt University
Do
ACE_Consumer_Handler Interface
class Consumer_Handler : public Proxy_Handler { public: Consumer_Handler (void); // Send a message to a Gateway // (may be queued). virtual int put (ACE_Message_Block *, ACE_Time_Value * = 0); protected: // Perform a non-blocking put(). int nonblk_put (ACE_Message_Block *mb); // Finish sending a message when // flow control abates. virtual int handle_output (ACE_HANDLE); // Send a message to a Peer. virtual int send_peer (ACE_Message_Block *); };
Vanderbilt University
Douglas C. Schmidt
ACE_Proxy_Handler_ Connector is a concrete factory class that: Establishes connections with Peers to produce ACE_Proxy_Handlers Activates ACE_Proxy_Handlers, which then route messages ACE_Proxy_Handler_ Connector also ensures reliability by restarting failed connections
238
Vanderbilt University
Do
ACE_Proxy_Handler_Connector Implementation
// (re)initiate a connection to a Proxy_Handler int Proxy_Handler_Connector::initiate_connection (Proxy_Handler *ph) { // Use asynchronous connections... if (connect (ph, ph->addr (), ACE_Synch_Options::asynch) == -1) { if (errno == EWOULDBLOCK) // No error, were connecting asynchronously. return -1; else // This is a real error, so reschedule // ourselves to reconnect. reactor ()->schedule_timer (ph, 0, ph->timeout ()); } else // Were connected synchronously! return 0; }
Vanderbilt University
Douglas C. Schmidt
Intent
Message Queue
ROUTING LAYER
Supplier Handler
handle_input()
n Consumer Handler
handle_output() put()
Decouple multiple input sources from multiple output sources to prevent blocking
Forces Resolved: Keep misbehaving connections from disrupting the QoS for well-behaved connections Different concurrency strategies for Supplier_Handlers and Consumer_Handlers
240
REACTIVE LAYER
Event Handler n
Reactor
www.cs.wustl.edu/schmidt/PDF/ TAPOS-00.pdf
Vanderbilt University
Do
ROUTE ID
3: find()
4: pu t( m sg )
6: put (msg)
Message Queue
Supplier Handler
1: handle_input() 2: recv_peer(msg)
Note the complex cooperative scheduling logic required to handle output ow control correctly
Vanderbilt University
Do
Vanderbilt University
Do
Vanderbilt University
Do
Peer_Message Schema
// Peer address is used to identify the // source/destination of a Peer message. class Peer_Addr { public: CONN_ID conn_id_; // Unique connection id. u_char logical_id_; // Logical ID. u_char payload_; // Payload type. }; // Fixed sized header. class Peer_Header { public: /* ... */ }; // Variable-sized message (sdu_ may be // between 0 and MAX_MSG_SIZE). class Peer_Message { public: // The maximum size of a message. enum { MAX_PAYLOAD_SIZE = 1024 }; Peer_Header header_; // Fixed-sized header. char sdu_[MAX_PAYLOAD_SIZE]; // Message payload. };
Vanderbilt University
Douglas C. Schmidt
Vanderbilt University
245
Do
Vanderbilt University
Douglas C. Schmidt
Douglas C. Schmidt
Do
Vanderbilt University
Do
Do
Config Table
SUPPLIER HANDLER CONSUMER HANDLER
Routing Table
Gateway
Vanderbilt University
Douglas C. Schmidt
template <class SUPPLIER_HANDLER, int main (int argc, char *argv[]) class CONSUMER_HANDLER> { class Gateway // Initialize the daemon and : public Service_Object // dynamically configure services. { ACE_Service_Config::open (argc, public: argv); // Perform initialization. // Run forever, performing the virtual int init // configured services. (int argc, char *argv[]); ACE_Reactor::instance ()-> run_reactor_event_loop (); // Perform termination. /* NOTREACHED */ virtual int fini (void); }
Vanderbilt University
252
Do
Thread-per Connection Gateway Service Object Thread Pool Gateway Service Object
svc.conf
FILE
Vanderbilt University
Douglas C. Schmidt
Vanderbilt University
254
Douglas C. Schmidt
Vanderbilt University
255
Do
FRAMEWORK LEVEL
APPLICATION LEVEL
Signal Handlers
Reactor
OS EVENT DEMULTIPLEXING INTERFACE
Vanderbilt University
KERNEL LEVEL
Do
ROUTE ID
3: find()
4: pu t( m sg )
Message Queue
Supplier Handler
5: send_peer(msg)
Note that this design is much simpler since the OS thread scheduler handles blocking
Vanderbilt University
Douglas C. Schmidt
ACE_Reactor plays the role of async layer ACE_Task active object plays the role of sync layer This particular conguration is a common variant of the Half-Sync/Half-Async pattern, as described in POSA2
1: dequeue(msg) 2: send(msg)
QUEUEING LAYER
MESSAGE QUEUES
Vanderbilt University
258
Do
<<activates>>
Supplier/Thr_Consumer Handler n
CONNECTIONORIENTED COMPONENTS
SVC_HANDLER PEER_CONNECTOR
PEER_STREAM SYNCH
Connector
Svc Handler
PEER CONNECTOR
PEER STREAM
Connection IPC_SAP
Stream
Service Configurator
global
Concurrency
Reactor
Vanderbilt University
Douglas C. Schmidt
New subclass of Proxy_Handler uses the Active Object pattern for the Consumer_Handler Uses multi-threading and synchronous I/O (rather than non-blocking I/O) to transmit message to Peers Transparently improve performance on a multi-processor platform and simplify design
260
Douglas C. Schmidt
The multi-threaded version of open() is slightly different since it spawns a new thread to become an active object! activate() is a pre-dened method on ACE_Task
Vanderbilt University
261
Do
Douglas C. Schmidt
Vanderbilt University
263
Do
CCM Stream
EVENT SERVER
Vanderbilt University
Do
The Event Server components are based upon a common pattern language www.cs.wustl.edu/schmidt/PDF/ DSEJ-94.pdf
Vanderbilt University
Douglas C. Schmidt
Do
ACE_Task
2
ACE_Module
2..*
ACE_Stream
Framework characteristics An ACE_Stream contains a stack of ACE_Modules Each ACE_Module contains two ACE_Tasks i.e., a read task and a write task Each ACE_Task contains an ACE_Message_Queue and a pointer to an ACE_Thread_Manager
Vanderbilt University
Do
Stream
APPLICATION
Stream
STREAM Head
DOWNSTREAM
UPSTREAM
MESSAGE
MODULE
WRITE TASK
READ TASK
Vanderbilt University
Do
Module A
ACTIVE
4: svc() 3: put()
Module A
2: put()
Module B
Module B
ACTIVE
2: svc() 1: put()
Module C
ACTIVE
Module C
1: put()
MESSAGE OBJECT
MODULE OBJECT
PROCESS OR THREAD
Task-based models are more intuitive but less efcient than Message-based models
Vanderbilt University
Do
Using the ACE Streams Framework for the CCM Event Server
Session Router Module Presentation Module Event Filter Module Event Analysis Module Presentation Module Switch Adapter Module
MD110 ERICSSON
Session IO
Reactor
Switch IO
MD110 ERICSSON
MD110
ERICSSON
TELECOM SWITCHES
www.cs.wustl.edu/schmidt/PDF/ DSEJ-94.pdf
Vanderbilt University
Douglas C. Schmidt
Features Allow clients to manage various aspects of telecom switches without modifying the switch software Support reuse of existing components based on a common architectural framework
SWITCHES
APPLICATION FRAMEWORK
SERVER
Vanderbilt University
271
Douglas C. Schmidt
CLIENT
NETWORK
DATABASE
SWITCHES
ACE
SERVER
Vanderbilt University
272
Douglas C. Schmidt
4: svc() 3: put()
Program copies stdin to stdout via the use of a multi-threaded ACE_Stream Stream implements a bounded buffer Since the data ow is uni-directional the read ACE_Task is always ignored
Producer Module
active
2: svc()
1: read()
Vanderbilt University 273
Do
Vanderbilt University
Do
Do
Vanderbilt University
Do
The Producer sends a 0-sized message to inform the Consumer to stop reading and exit
Vanderbilt University
Do
Vanderbilt University
Douglas C. Schmidt
Vanderbilt University
279
Douglas C. Schmidt
Concurrency Strategies
Developing correct, efcient, and robust concurrent applications is challenging Below, we examine a number of strategies that addresses challenges related to the following:
Concurrency control Library design Thread creation Deadlock and starvation avoidance
Vanderbilt University
280
Douglas C. Schmidt
Douglas C. Schmidt
Vanderbilt University
282
Douglas C. Schmidt
Vanderbilt University
283
Douglas C. Schmidt
Locking Alternatives
Code locking
Associate locks with body of functions Typically performed using bracketed mutex locks Often called a Monitor Object
Data locking
Associate locks with data structures and/or objects Permits a more ne-grained style of locking Data locking allows more concurrency than code locking, but may incur higher overhead
Vanderbilt University
284
Douglas C. Schmidt
Single-lock Strategy
One way to simplify locking is use a single, application-wide mutex lock Each thread must acquire the lock before running and release it upon completion The advantage is that most legacy code doesnt require changes The disadvantage is that parallelism is eliminated Moreover, interactive response time may degrade if the lock isnt released periodically
Vanderbilt University
285
Douglas C. Schmidt
Douglas C. Schmidt
Vanderbilt University
287
Douglas C. Schmidt
Invariants
In general, an invariant is a condition that is always true For concurrent programs, an invariant is a condition that is always true when an associated lock is not held However, when the lock is held the invariant may be false When the code releases the lock, the invariant must be re-established
Vanderbilt University
288
Douglas C. Schmidt
Vanderbilt University
289
Douglas C. Schmidt
Deadlock
Permanent blocking by a set of threads that are competing for a set of resources Caused by circular waiting, e.g., A thread trying to reacquire a lock it already holds Two threads trying to acquire resources held by the other e.g., T1 and T2 acquire locks L1 and L2 in opposite order One solution is to establish a global ordering of lock acquisition (i.e., a lock hierarchy) May be at odds with encapsulation...
Vanderbilt University
290
Douglas C. Schmidt
Vanderbilt University
291
Do
ACE_Recursive_Thread_Mutex Implementation
Here is portable implementation of recursive thread mutexes available in ACE:
class ACE_Recursive_Thread_Mutex { public: // Initialize a recursive mutex. ACE_Recursive_Thread_Mutex (void); // Implicitly release a recursive mutex. ACE_Recursive_Thread_Mutex (void); // Acquire a recursive mutex. int acquire (void); // Conditionally acquire a recursive mutex. int tryacquire (void); // Releases a recursive mutex. int release (void); private: ACE_Thread_Mutex nesting_mutex_; ACE_Condition_Thread_Mutex mutex_available_; ACE_thread_t owner_; int nesting_level_; };
Vanderbilt University
Do
Acquiring an ACE_Recursive_Thread_Mutex
int ACE_Recursive_Thread_Mutex::acquire (void) { ACE_thread_t t_id = ACE_Thread::self (); ACE_GUARD_RETURN (ACE_Thread_Mutex, guard, nesting_mutex_, -1); // If theres no contention, grab mutex. if (nesting_level_ == 0) { owner_ = t_id; nesting_level_ = 1; } else if (t_id == owner_) // If we already own the mutex, then // increment nesting level and proceed. nesting_level_++; else { // Wait until nesting level drops // to zero, then acquire the mutex. while (nesting_level_ > 0) mutex_available_.wait (); // Note that at this point // the nesting_mutex_ is held... owner_ = t_id; nesting_level_ = 1; } return 0;
Vanderbilt University
Do
Vanderbilt University
Douglas C. Schmidt
Avoiding Starvation
Starvation occurs when a thread never acquires a mutex even though another thread periodically releases it The order of scheduling is often undened This problem may be solved via: Use of voluntary pre-emption mechanisms e.g., thr_yield() or Sleep() Using an ACE Token that strictly orders acquisition and release
Vanderbilt University
295
Douglas C. Schmidt
Drawbacks to Multi-threading
Performance overhead
Some applications do not benet directly from threads Synchronization is not free Threads should be created for processing that lasts at least several 1,000 instructions
Correctness
Threads are not well protected against interference Concurrency control issues are often tricky Many legacy libraries are not thread-safe
Development effort
Developers often lack experience Debugging is complicated (lack of tools)
Vanderbilt University 296
Douglas C. Schmidt
Drawbacks of patterns
Do not lead to direct code reuse Can be deceptively simple Teams may suffer from pattern overload
Vanderbilt University
297
Douglas C. Schmidt
Drawbacks of frameworks
High initial learning curve Many classes, many levels of abstraction The ow of control for reactive dispatching is non-intuitive Verication and validation of generic components is hard
Vanderbilt University
298
Douglas C. Schmidt
Drawbacks of C++
Some language features are not implemented Some development environments are primitive Language has many dark corners and sharp edges Purify helps alleviate many problems...
Vanderbilt University
299
Douglas C. Schmidt
Douglas C. Schmidt
Douglas C. Schmidt
Vanderbilt University
302
Douglas C. Schmidt
Vanderbilt University
303
Do
Newsgroup comp.soft-sys.ace Commercial support from Riverace and OCI www.riverace.com www.theaceorb.com
Vanderbilt University
Douglas C. Schmidt
Concluding Remarks
Developers of networked application software confront recurring challenges that are largely application-independent e.g., service conguration and initialization, distribution, error handling, ow control, event demultiplexing, concurrency, synchronization, persistence, etc. Successful developers resolve these challenges by applying appropriate patterns to create communication frameworks containing components
Frameworks and components are an effective way to achieve systematic reuse of software
Vanderbilt University
305