C++ Network Programming with Patterns, Advanced ACE Tutorial Douglas C. Schmidt Frameworks, and ACE Roadmap to Levels of Middleware
APPLICATIONS Douglas C. Schmidt Observations
HUD AVIONICS – Historically, apps Professor Department of EECS DOMAIN-SPECIFIC MIDDLEWARE SERVICES WTS REPLICATION [email protected] Vanderbilt University Nav SERVICE built atop OS Cons EVENT Cons COMMON MIDDLEWARE SERVICES CHANNEL – Today, apps built www.cs.wustl.edu/ schmidt/ (615) 343-8197 Cons atop middleware DISTRIBUTION MIDDLEWARE – Middleware has multiple layers HOST INFRASTRUCTURE MIDDLEWARE
Just like network Sponsors protocol stacks OPERATING SYSTEMS & PROTOCOLS NSF, DARPA, ATD, BBN, Boeing, Cisco, Comverse, GDIS, Experian, Global MT, HARDWARE DEVICES Hughes, Kodak, Krones, Lockheed, Lucent, Microsoft, Mitre, Motorola, NASA, Nokia, Nortel, OCI, Oresis, OTI, QNX, Raytheon, SAIC, Siemens SCR, Siemens MED, www.cs.wustl.edu/˜schmidt/PDF/ Siemens ZT, Sprint, Telcordia, USENIX middleware-chapter.pdf
Vanderbilt University 1
Advanced ACE Tutorial Douglas C. Schmidt Advanced ACE Tutorial Douglas C. Schmidt Motivation for Concurrency Motivation for Distribution
PRINTER
SERVER Collaboration ! connectivity and
maxfdp1 Leverage hardware/software COMPUTER interworking read_fds CLIENT WORK FILE SYSTEM REQUEST – e.g., multi-processors and OS CD ROM Performance ! multi-processing thread support WORK WORK WORK and locality REQUEST REQUEST CLIENT REQUEST (1) STAND-ALONE APPLICATION ARCHITECTURE
CLIENT
CLIENT Increase performance Reliability and availability ! TIME NAME CYCLE (1) ITERATIVE SERVER SERVICE replication – e.g., overlap computation and SERVICE SERVICE DISPLAY
communication ! SERVER SERVICE Scalability and portability FI LE modularity
Improve response-time NETWORK SERVICE CLIENT
WORK configuration! and reconfiguration PRINT Extensibility dynamic REQUEST – e.g., GUIs and network servers SERVICE WORK WORK WORK CD ROM CLIENT REQUEST REQUEST REQUEST Simplify program structure systems CLIENT CLIENT PRINTER FILE SYSTEM Cost effectiveness ! open – e.g., sync vs. async (2) DISTRIBUTED APPLICATION ARCHITECTURE and resource sharing (2) CONCURRENT SERVER
Vanderbilt University 2 Vanderbilt University 3 Advanced ACE Tutorial Douglas C. Schmidt Advanced ACE Tutorial Douglas C. Schmidt Challenges and Solutions Caveats
Developing efficient, robust, and extensible concurrent networking OO is not a panacea applications is hard – Though when used properly it helps minimize “accidental” – e.g., must address complex topics that are less problematic or not complexity and improve software quality factors relevant for non-concurrent, stand-alone applications
It’s also essential to understand advanced OS features to enhance
OObinding techniques and OO language features help to enhance software functionality and performance, e.g., quality factors – Multi-threading – Key OO techniques include patterns and frameworks – Multi-processing – Key OO language features include classes, inheritance, dynamic – Synchronization , and parameterized types – Shared memory – Key software quality factors include modularity, extensibility, – Explicit dynamic linking portability, reusability, and correctness – Communication protocols and IPC mechanisms
Vanderbilt University 4 Vanderbilt University 5
Advanced ACE Tutorial Douglas C. Schmidt Advanced ACE Tutorial Douglas C. Schmidt Tutorial Outline Software Development Environment
Brief overview of key OO networking and concurrency concepts and The topics discussed here are largely independent of OS, network, OS platform mechanisms and programming language – Emphasis is on practical solutions – Currently used successfully on UNIX/POSIX, Windows, and RTOS platforms, running on TCP/IP networks using C++
Examine a range of examples in detail
Examples are illustrated using freely available ADAPTIVE – Networked Logging Service Communication Environment (ACE) OO framework components – Concurrent Web Server – Application-level Telecom Gateway – Although ACE is written in C++, the principles covered in this – Call Center Manager Event Server tutorial apply to other OO languages
Discuss general concurrent programming strategies – e.g., Java, Eiffel, Smalltalk, etc.
Provide URLs for further reading on the topic In addition, other networks and backplanes can be used, as well
Vanderbilt University 6 Vanderbilt University 7 Advanced ACE Tutorial Douglas C. Schmidt Advanced ACE Tutorial Douglas C. Schmidt Sources of Complexity Sources of Inherent Complexity
PRINTER
Inherent complexity Inherent complexity results from fundamental domain challenges, COMPUTER – Latency e.g.: FILE CD ROM SYSTEM – Reliability – Synchronization Concurrent programming Distributed programming (1) STAND-ALONE APPLICATION ARCHITECTURE – Deadlock Eliminating “race conditions” Addressing the impact of latency TIME NAME SERVICE CYCLE
SERVICE SERVICE Accidental Complexity Deadlock avoidance Fault tolerance and high availability DISPLAY SERVICE – Low-level APIs FI LE Fair scheduling Load balancing and service NETWORK SERVICE – Poor debugging tools partitioning
PRINT – Algorithmic Performance optimization SERVICE and tuning Consistent ordering of distributed CD ROM decomposition events PRINTER FILE SYSTEM – Continuous (2) DISTRIBUTED APPLICATION ARCHITECTURE re-invention
Vanderbilt University 8 Vanderbilt University 9
Advanced ACE Tutorial Douglas C. Schmidt Advanced ACE Tutorial Douglas C. Schmidt Sources of Accidental Complexity OO Contributions to Concurrent Accidental complexity results from limitations with tools and techniques and Distributed Applications used to develop concurrent applications, e.g., Concurrent network programming is and frameworks elevate traditionally performed using development level to focus on
Lack of portable, reentrant, type-safe and extensible system call low-level OS mechanisms, e.g.Patterns, application concerns, e.g., interfaces and component libraries
fork/exec Service functionality and
Inadequate debugging support and lack of concurrent and policies
distributed program analysis tools Shared memory and semaphores
Service configuration
Widespread use of algorithmic decomposition Memory-mapped files
– Fine for explaining concurrent programming concepts and Concurrent event Signals algorithms but inadequate for developing large-scale concurrent demultiplexing and event
network applications sockets/select handler dispatching
Continuous rediscovery and reinvention of core concepts and Low-level thread APIs Service concurrency and components synchronization
Vanderbilt University 10 Vanderbilt University 11 Do
Advanced ACE Tutorial Douglas C. Schmidt Overview of Patterns SERVER
Patterns represent solutions to problems that arise when developing software within a particular context FORWARD REQUEST FORWARD – i.e., “Patterns == problem/solution pairs within a context” 2:
Patterns capture the static and dynamic structure and collaboration QUOTER : PROXY
among key participants in software designs QUOTER : – They are particularly useful for articulating how and why to RESPONSE
resolve non-functional forces 3: METHOD CALL 1:
Patterns facilitate reuse of successful software architectures and
designs NETWORK METHOD RETURN Example: the Proxy Pattern BROKER : 4: : Provide a surrogate for another object that CLIENT Intent controls access to it Vanderbilt University Vanderbilt University 12 Advanced ACE Tutorial
Advanced ACE Tutorial Douglas C. Schmidt Advanced ACE Tutorial Douglas C. Schmidt Overview of Frameworks and Components Class Libraries versus Frameworks
APPLICATION- LOCAL MATH SPECIFIC INVOCATIONS CLASSES Key distinctions FUNCTIONALITY
A framework is: ADT
CLASSES DATABASE Class libraries – “An integrated collection of components that collaborate to CLASSES GUI GLUE NETWORK – Reusable building blocks produce a reusable architecture for a family of related applications” EVENT CLASSES LOOP CODE IPC CLASSES – Domain-independent
Frameworks differ from conventional class libraries: (A) CLASS LIBRARY ARCHITECTURE – Limited in scope – Passive 1. Frameworks are “semi-complete” applications NETWORKING EVENT LOOP
2. Frameworks address a particular application domain ADT Frameworks 3. Frameworks provide “inversion of control” CLASSES GUI APPLICATION- CALL – Reusable, “semi-complete” INVOKES SPECIFIC BACKS
Frameworks facilitate reuse of successful networked application FUNCTIONALITY EVENT applications MATH LOOP software designs and implementations CLASSES – Domain-specific
EVENT DATABASE – Broader in scope – Applications inherit from and instantiate framework components LOOP (B) FRAMEWORK ARCHITECTURE – Active
Vanderbilt University 14 Vanderbilt University 15 Advanced ACE Tutorial Douglas C. Schmidt Advanced ACE Tutorial Douglas C. Schmidt The ADAPTIVE Communication Environment (ACE) ACE Statistics JAWS ADAPTIVE NETWORKED STANDARDS-BASED MIDDLEWARE WEB SERVER SERVICE THE ACE ORB TOKEN GATEWAY (TAO) COMPONENTS SERVER SERVER LAYER
ACE library contains 250,000 Currently used by LOGGING NAME TIME SERVER SERVER SERVER lines of C++ dozens of companies
SERVICE CORBA FRAMEWORK ACCEPTOR CONNECTOR HANDLER HANDLER – Over 40 person-years of effort – Bellcore, BBN, LAYER Boeing, Ericsson,
/ C++ PROCESS STREAMS Ported to UNIX, Windows, MVS, and THREAD LOG SERVICE SHARED Hughes, Kodak, WRAPPER MANAGERS MSG CONFIG - MALLOC RT/embedded platforms FACADE REACTOR/ PROACTOR URATOR Lockheed, Lucent, LAYER SYNCH SPIPE SOCK SAP/ FIFO MEM FILE WRAPPERS SAP TLI SAP SAP MAP SAP – e.g., VxWorks, LynxOS, Chorus Motorola, Nokia, OS ADAPTATION LAYER Nortel, Raytheon, C PROCESSES/ WIN32 NAMED SOCKETS/ UNIX SELECT/ DYNAMIC SHARED FILE SYS PIPES & UNIX APIS THREADS TLI FIFOS IO COMP LINKING MEMORY APIS STREAM PIPES Large user and open-source SAIC, Siemens, etc. PROCESS/THREAD COMMUNICATION VIRTUAL MEMORY & FILE developer community SUBSYSTEM SUBSYSTEM SUBSYSTEM
Supported commercially GENERAL OPERATING SYSTEM SERVICES – ˜schmidt/ACE-users.html www.cs.wustl.edu/˜schmidt/ACE.html by Riverace – www.riverace.com
Vanderbilt University 16 Vanderbilt University 17
Advanced ACE Tutorial Douglas C. Schmidt Advanced ACE Tutorial Douglas C. Schmidt The Key Frameworks in ACE Patterns for Communication Middleware
Active Thread-per Acceptor Observation Request Object Acceptor-
Reactor Proactor Thread-per Failures rarely result from Connector Session Connector Half-Sync/ unknown scientific Thread Half-Async Component Pool Configurator principles, but from failing Service Streams Task to apply proven Configurator Thread Leader/ Object Specific Followers Lifetime engineering practices and Storage Manager patterns Asynchronous Reactor Completion Double Thread- ACE contains a number of frameworks that can be used separately Token Checked Safe Benefits of Patterns or together Proactor Locking Interface
Facilitate design reuse External Wrapper Scoped Strategized
This design permits fine-grained subsetting of ACE components Polymorphism Facade Locking Locking
Preserve crucial design – Subsetting helps minimize ACE’s memory footprint Concurrency Event Initialization Synchronization information – $ACE_ROOT/doc/ACE-subsets.html Patterns Patterns Patterns Patterns
Guide design choices
Vanderbilt University 18 Vanderbilt University 19 Advanced ACE Tutorial Douglas C. Schmidt Advanced ACE Tutorial Douglas C. Schmidt
The ACE ORB (TAO) TAO Statistics
in args
TAO Overview ! OBJ operation() OBJECT
CLIENT TAO order of magnitude 50 person-years of effort REF (SERVANT ) out args + return A real-time, value
high-performance – Core ORB > 300,000 LOC Currently used by many IDL
SKELETON REAL -TIME ORB – IDL compiler > 200,000 companies IDL ORB RUN -TIME OBJECT STUBS SCHEDULER Leverages ACE LOC ADAPTER – e.g., Boeing, BBN, Lockheed, REAL-TIME ORB CORE – Runs on POSIX, – CORBA Object Services > IOP IOP Lucent, Motorola, Raytheon, PLUGGABLE PLUGGABLE 250,000 LOC ORB & XPORT ORB & XPORT Windows, PROTOCOLS PROTOCOLS SAIC, Siemens, etc.
RTOSs – Leverages ACE heavily OS KERNEL OS KERNEL Supported commercially by OCI
REAL REAL -TIME I /O ACE -TIME I /O Related efforts ! Ported to UNIX, Windows, & SUBSYSTEM COMPONENTS SUBSYSTEM and PrismTech RT/embedded platforms HIGH -SPEED HIGH -SPEED QuO at BBN NETWORK INTERFACE NETWORK NETWORK INTERFACE – www.ociweb.com
MIC/GME at – e.g., VxWorks, LynxOS, – www.prismtechnologies.com www.cs.wustl.edu/˜schmidt/TAO. Vanderbilt Chorus, WinCE
html XOTS
Vanderbilt University 20 Vanderbilt University 21
Advanced ACE Tutorial Douglas C. Schmidt Advanced ACE Tutorial Douglas C. Schmidt JAWS Adaptive Web Server Java ACE 1: GET ~schmidt WWW HTTP/1.0 WWW JAWS Overview CLIENT SERVER 2: index.html DISTRIBUTED Java ACE – A high-performance SERVICES AND TOKEN LOGGING NAME TIME COMPONENTS SERVER SERVER SERVER SERVER Overview PROTOCOL Web server HTML HANDLERS
PARSER Flexible concurrency FRAMEWORKS A Java version AND CLASS SERVICE GUI ACCEPTOR CONNECTOR DISPATCHER and dispatching CATEGORIES HANDLER REQUESTER of ACE mechanisms ADAPTIVE SERVICE EXECUTIVE(ASX)
JAVA SYNCH THREAD LOG TIMER SERVICE – Used for – Leverages the ACE SOCK_SAP WRAPPERS WRAPPERS MANAGER MSG QUEUE CONFIGURATOR GRAPHICS COMMUNICATION PROTOCOL medical ADAPTER (E.G., HTTP ) framework JAVA VIRTUAL MACHINE ( JVM) imaging Ported to most OS OS KERNEL OS KERNEL platforms www.cs.wustl.edu/˜schmidt/JACE.html prototype OS I/O SUBSYSTEM OS I/O SUBSYSTEM – Used commercially by www.cs.wustl.edu/˜schmidt/C++2java. NETWORK ADAPTERS NETWORK ADAPTERS CacheFlow NETWORK html
www.cacheflow.com www.cs.wustl.edu/˜jxh/ www.cs.wustl.edu/˜schmidt/PDF/ research/ MedJava.pdf
Vanderbilt University 22 Vanderbilt University 23 adritUniversity Vanderbilt } { (void) logging_server void server: logging networked for pseudo-code algorithmic Typical dacdAETutorial ACE Advanced Advanced ACE Tutorial Do } { forever loop endpoint acceptor initialize
adecneto events connection events handle data events handle for wait Networked Logging Service
PRINTER P 1 CONSOLE
ovninlLgigSre Design Server Logging Conventional CLIENT LOCAL IPC P LOGGING 2 DAEMON REMOTE P 3 IPC SERVER LOGGING DAEMON
HAOST A HOSTB B HOST CLIENT SERVER A
IPC
NETWORK REMOTE STORAGE DEVICE
HOST CLIENT P1 h gadmistake:” “grand The B CLIENT
ogn server! logging the of implementation and design detailed the into directly pseudo-code decomposed algorithmically this refine” “step-wise to temptation the Avoid LOCAL IPC P LOGGING 2 DAEMON P3
oga .Schmidt C. Douglas Intent: Server logging daemon collects, formats, and outputs logging records forwarded from client logging daemons residing throughout a network or Internet 26 Vanderbilt University eeae nlgigsre host: server logging on generates ((LM_DEBUG, ACE_DEBUG and failed fork [email protected]@2766@LM_ERROR@client ::(4) 14:50:13 31 Oct host: server logging on failed")); Generates fork "(%t) ((LM_ERROR, ACE_ERROR to similar is API logging The Tutorial ACE Advanced adritUniversity Vanderbilt bastille server to sending [email protected]@18352@LM_DEBUG@drwho ::(6) 14:50:28 31 Oct Advanced ACE Tutorial Do The select()-based Logging Server ewre ogn evc rgamn API Programming Service Logging Networked Implementation
SERVER SERVER server_host)); %s", server to sending "(%t) LOGGING DAEMON
maxhandlep1 acceptor NETWORK read_handles printf() CLIENT CONNECTION REQUEST
LOGGING
RECORDS LOGGING LOGGING , RECORDS RECORDS e.g. : CLIENT CLIENT CLIENT oga .Schmidt C. Douglas Serializes server processing at select() demuxing level 25 Vanderbilt University Advanced ACE Tutorial Do Advanced ACE Tutorial Do Initialize Acceptor Socket Conventional Logging Server static void initialize_acceptor (u_short port) Implementation { struct sockaddr_in saddr; Note the excessive amount of detail required to // Create a local endpoint of communication. program at the socket level... acceptor = socket (PF_INET, SOCK_STREAM, 0); // Main program static const int PORT = 10000; // Set up the address info. to become server. memset ((void *) &saddr, 0, sizeof saddr); typedef u_long COUNTER; saddr.sin_family = AF_INET; typedef int HANDLE; saddr.sin_port = htons (port); saddr.sin_addr.s_addr = htonl (INADDR_ANY); // Counts the # of logging records processed static COUNTER request_count; // Associate address with endpoint bind (acceptor, // Acceptor-mode socket handle (struct sockaddr *) &saddr, static HANDLE acceptor; sizeof saddr); // Highest active handle number, plus 1 // Make endpoint listen for connection requests. static HANDLE maxhp1; listen (acceptor, 5); // Set of currently active handles // Initialize handle sets. static fd_set activity_handles; FD_ZERO (&ready_handles); FD_ZERO (&activity_handles); // Scratch copy of activity_handles FD_SET (acceptor, &activity_handles); static fd_set ready_handles; maxhp1 = acceptor + 1; }
Vanderbilt University Vanderbilt University
Advanced ACE Tutorial Do Advanced ACE Tutorial Do Handle Data Processing Main Event Loop of Logging Server static void handle_data (void) { int main (int argc, char *argv[]) // acceptor + 1 is the lowest client handle { initialize_acceptor for (HANDLE h = acceptor + 1; h < maxhp1; h++) (argc > 1 ? atoi (argv[1]) : PORT); if (FD_ISSET (h, &ready_handles)) { ssize_t n = handle_log_record (h, 1); // Loop forever performing logging // server processing. // Guaranteed not to block in this case! if (n > 0) for (;;) { ++request_count; // struct assignment. // Count the # of logging records ready_handles = activity_handles; else if (n == 0) { // Handle connection shutdown. // Wait for client I/O events. FD_CLR (h, &activity_handles); select (maxhp1, &ready_handles, 0, 0, 0); close (h); if(h+1==maxhp1) { // First receive pending logging records. // Skip past unused handles handle_data (); while (!FD_ISSET (--h, &activity_handles)) // Then accept pending connections. continue; handle_connections (); maxhp1 = h + 1; } } } } } }
Vanderbilt University Vanderbilt University Advanced ACE Tutorial Do Advanced ACE Tutorial Do Conventional Client Logging Receive and Process Logging Records Daemon Implementation static ssize_t handle_log_record (HANDLE in_h, The main() method receives logging records from HANDLE out_h) { client applications and forwards them on to the ssize_t n; logging server size_t len; Log_Record lr; int main (int argc, char *argv[]) { // The first recv reads the length (stored as a HANDLE stream = initialize_stream_endpoint // fixed-size integer) of adjacent logging record. (argc > 1 ? atoi (argv[1]) n = recv (in_h, (char *) &len, sizeof len, 0); : PORT); if (n <= 0) return n; Log_Record lr; len = ntohl (len); // Convert byte-ordering
// Loop forever performing client // The second recv then reads
Vanderbilt University Vanderbilt University
Advanced ACE Tutorial Do Advanced ACE Tutorial Do Client Connection Establishment Handle Connection Acceptance static HANDLE initialize_stream_endpoint static void handle_connections (void) (const char *host, u_short port) { { if (FD_ISSET (acceptor, &ready_handles)) { struct sockaddr_in saddr; static struct timeval poll_tv = {0, 0}; HANDLE h; // Create a local endpoint of communication. HANDLE stream = socket (PF_INET, SOCK_STREAM, 0); // Handle all pending connection requests // (note use of select’s polling feature) // Set up the address info. to become client. memset ((void *) &saddr, 0, sizeof saddr); do { saddr.sin_family = AF_INET; // Beware of subtle bug(s) here... saddr.sin_port = htons (port); h = accept (acceptor, 0, 0); hostent *hp = gethostbyname (host); FD_SET (h, &activity_handles); memcpy ((void *) &saddr, htonl (hp->h_addr), // Grow max. socket handle if necessary. hp->h_length); if (h >= maxhp1) maxhp1=h+1; // Associate address with endpoint } while (select (acceptor + 1, &ready_handles, connect (stream, 0, 0, &poll_tv) == 1); (struct sockaddr *) &saddr, } sizeof saddr); return stream; }
Vanderbilt University Vanderbilt University Advanced ACE Tutorial Douglas C. Schmidt Advanced ACE Tutorial Douglas C. Schmidt Limitations with Algorithmic Decomposition Overcoming Limitations via OO Algorithmic decomposition tightly couples application-specific
functionality and the following configuration-related characteristics: The algorithmic decomposition illustrated above specifies many low-level details
Application Structure – Moreover, the excessive coupling impedes reusability, – The number of services per process extensibility, and portability... – Time when services are configured into a process
In contrast, OO focuses on application-specific behavior, e.g.,
Communication and Demultiplexing Mechanisms int Logging_Handler::handle_input (void) – The underlying IPC mechanisms that communicate with other { participating clients and servers ssize_t n = handle_log_record (peer ().get_handle (), – Event demultiplexing and event handler dispatching mechanisms ACE_STDOUT); if (n > 0) ++request_count; // Count the # of logging records Concurrency and Synchronization Model – The process and/or thread architecture that executes service(s) at return n <= 0 ? -1 : 0; run-time }
Vanderbilt University 36 Vanderbilt University 37
Advanced ACE Tutorial Douglas C. Schmidt Advanced ACE Tutorial Douglas C. Schmidt OO Contributions to Software Patterns in the Networked Logging Server Active Object
Patterns facilitate the large-scale reuse of software architecture Component – Even when reuse of algorithms, detailed designs, and Acceptor implementations is not feasible Configurator
Frameworks achieve large-scale design and code reuse STRATEGIC Reactor – In contrast, traditional techniques focus on the functions and PATTERNS algorithms that solve particular requirements TACTICAL PATTERNS
Note that patterns and frameworks are not unique to OO! Factory Adapter Iterator Template Wrapper – However, objects and classes are useful abstraction mechanisms Method Method Facade
Strategic and tactical are relative to the context and abstraction level
Vanderbilt University 38 Vanderbilt University 39 Advanced ACE Tutorial Douglas C. Schmidt Advanced ACE Tutorial Douglas C. Schmidt Summary of Pattern Intents Components in the OO Logging Server
Wrapper Facade ! “Encapsulates the functions and data provided
Application-specific components by existing non-OO APIs within more concise, robust, portable, maintainable, and cohesive OO class interfaces” – Process logging records received from clients
Reactor ! “Demultiplexes and dispatches requests that are Connection-oriented application components delivered concurrently to an application by one or more clients” – ACE_Svc_Handler (service handler)
Acceptor ! “Decouple the passive connection and initialization of a Performs I/O-related tasks with clients peer service in a distributed system from the processing performed – ACE_Acceptor factory
once the peer service is connected and initialized” Passively accepts connection requests
Dynamically creates a service handler for each client and
Component Configurator ! “Decouples the implementation of “activates” it services from the time when they are configured”
Application-independent ACE framework components
Active Object ! “Decouples method execution from method invocation to enhance concurrency and simplify synchronized – Perform IPC, explicit dynamic linking, event demultiplexing, event access to an object that resides in its own thread of control” handler dispatching, multi-threading, etc.
Vanderbilt University 40 Vanderbilt University 41 Do
Advanced ACE Tutorial Douglas C. Schmidt Addressing Robustness, Portability, Stream Service SOCK_Stream Null_Synch
Configurator and Maintainability Challenges PEER_STREAM SYNCH_STRAT Handler Logging Svc n
Handler Problem
Reactor – Building distributed applications using low-level APIs is hard Connection
Forces
<
STREAM – Low-level APIs are non-portable and non-maintainable IPC_SAP Concurrency
SVC_HANDLER PEER_ACCEPTOR Solution Logging_Handler SOCK_Acceptor – Apply the Wrapper Facade pattern to encapsulate low-level PEER Logging Acceptor Acceptor ACCEPTOR
1 functions and data structures
COMPONENTS COMPONENTS COMPONENTS
SPECIFIC ORIENTED FRAMEWORK
- APPLICATION - CONNECTION Class Diagram for OO Logging Server ACE
Advanced ACE Tutorial Vanderbilt University Vanderbilt University 43 Do
Advanced ACE Tutorial Douglas C. Schmidt The Wrapper Facade Pattern Intent
client ROLE PASSIVE SERVER close() socket() bind() listen() accept()
1: Encapsulates the functions send()/recv() and data provided by 1: method_k() existing lower-level, Wrapper 2: function_k() non-OO APIs within more Facade Functions concise, robust, portable, method_1() function_1() maintainable, and cohesive ...... SERVICE method_m() function_n() NETWORK 3:
higher-level OO class PROCESSING interfaces POSA2 (www.cs.wustl.edu/ ˜schmidt/POSA/) the Socket API Forces Resolved
Avoid tedious, error-prone, and non-portable system APIs CLIENT ACTIVE ROLE 2: close() socket() bind() (optional) connect() Create cohesive abstractions send()/recv() Motivating the Wrapper Facade Pattern: Sockets are the most commonprogramming network API and are availableplatforms on most OS Vanderbilt University Vanderbilt University 44 Advanced ACE Tutorial
Advanced ACE Tutorial Douglas C. Schmidt Advanced ACE Tutorial Douglas C. Schmidt Problem with Sockets: Lack of Type-safety Problem with Sockets: Steep Learning Curve
int buggy_echo_server (u_short port_num) I/O handles are { // Error checking omitted. not amenable to Many socket/TLI API functions have complex semantics, e.g.: sockaddr_in s_addr; strong type int acceptor = checking at socket (PF_UNIX, SOCK_DGRAM, 0); Multiple protocol families and address families s_addr.sin_family = AF_INET; compile-time s_addr.sin_port = port_num; – e.g., TCP, UNIX domain, OSI, XNS, etc.
s_addr.sin_addr.s_addr = INADDR_ANY; The adjacent bind (acceptor, (sockaddr *) &s_addr, code contains Infrequently used features, e.g.: sizeof s_addr); many subtle, int handle = accept (acceptor, 0, 0); – Broadcasting/multicasting for (;;) { common bugs char buf[BUFSIZ]; – Passing open file handles ssize_t n = read (acceptor, buf, sizeof buf); – Urgent data delivery and reception if (n <= 0) break; – Asynch I/O, non-blocking I/O, I/O-based and timer-based event write (handle, buf, n); multiplexing } }
Vanderbilt University 46 Vanderbilt University 47 Advanced ACE Tutorial Douglas C. Schmidt Advanced ACE Tutorial Douglas C. Schmidt Problem with Sockets: Portability Problem with Sockets: Poorly Structured
Having multiple “standards,” i.e., sockets and TLI, makes portability difficult, e.g., – May require conditional compilation – In addition, related functions are not included in POSIX standards
e.g., select(), WaitForMultipleObjects(), and poll() socket() bind() connect() listen() accept() read() write() readv() writev() recv() send() recvfrom() sendto() recvmsg() sendmsg() setsockopt() getsockopt() getpeername() getsockname() gethostbyname() getservbyname()
Portability between UNIX and Windows Sockets is problematic, e.g.: Limitations – Header files
Socket API is linear rather than hierarchical – Error numbers
– Handle vs. descriptor types There is no consistency among names... – Shutdown semantics
– I/O controls and socket options Non-portable
Vanderbilt University 48 Vanderbilt University 49 Do Do REMOTE / REMOTE / LOCAL SOCK_Acceptor LOCAL bind()/connect() socket(PF_INET) socket(PF_INET) SOCK_Dgram bind()/listen()/accept() socket(PF_INET)/bind()
SOCK_Stream SOCK_Dgram sendto()/recvfrom() send()/recv() send()/recv() SOCK_CODgram bind()/connect() socket(PF_INET) SOCK_Connector bind()/connect() socket(PF_INET) SOCK_Dgram_Bcast COMMUNICATION DOMAIN socket(PF_INET)/bind() COMMUNICATION DOMAIN SOCK_Dgram_Mcast LOCAL LOCAL bind()/connect() socket(PF_UNIX) socket(PF_UNIX) LSOCK_Acceptor bind()/listen()/accept() socket(PF_UNIX)/bind() LSOCK_Dgram
LSOCK_Stream sendto()/recvfrom()
send()/recv() send()/recv()
Socket Taxonomy LSOCK_Dgram PASSIVE PASSIVE bind()/connect() socket(PF_UNIX)
bind()/connect()
socket(PF_UNIX) /
/ LSOCK_CODgram
XFER
XFER LSOCK_Connector socket(PF_UNIX)/bind()
ROLE ROLE
DATAGRAM GRAM
ACTIVE GRAM STREAM DATAGRAM
ACTIVE
CONNECTED DATA STREAM
DATA CONNECTION CONNECTED COMMUNICATION
COMMUNICATION CONNECTION
TYPE OF COMMUNICATION SERVICE COMMUNICATION OF TYPE TYPE OF COMMUNICATION SERVICE COMMUNICATION OF TYPE Advanced ACE Tutorial The Socket API can bedimensions classified along three Vanderbilt University Advanced ACE Tutorial Solution: ACE Socket Wrapper Facades The ACE C++ wrapper facadesmodel more the explicitly key socket componentsclasses using OO Vanderbilt University 1. Connection role 2. Communication domain 3. Type of service adritUniversity Vanderbilt }; public: ACE_SOCK_Stream class dacdAETutorial ACE Advanced
sz_ evn(od*u,itn); ... (void); int // *buf, close (void int recv_n *iov, ssize_t iovec (const sendv_n *buf, ssize_t void (const send_n ssize_t *buf, (void recv *buf, ssize_t void (const send PEER_ADDR; ssize_t ACE_INET_Addr typedef Trait. // { ACE_SOCK public : Advanced ACE Tutorial Do C oncinOine oktWaprFacade Wrapper Socket Connection-Oriented ACE The ACE Connection-Oriented Socket Wrapper Facades
ACE_IPC_SAP ACE_Addr temn n drsigClasses Addressing and Streaming n n); int n); int n n); int
n n); int ACE_SOCK_IO ACE_SOCK
ACE_SOCK_Acceptor ACE_INET_Addr
ACE_SOCK_Stream ACE_SOCK_Connector
Participants }; public: { ACE_INET_Addr class /... (void); // get_ip_addr ACE_UINT_32 (void); get_port_number u_short port, (u_short ACE_INET_Addr ACE_Addr public :
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 os hrhost[]); char const oga .Schmidt C. Douglas 54 Vanderbilt University }; public: { ACE_SOCK_Connector class Tutorial ACE Advanced adritUniversity Vanderbilt University Vanderbilt dacdAETutorial ACE Advanced
/... // connect int PEER_STREAM; ACE_SOCK_Stream PEER_ADDR; typedef ACE_INET_Addr typedef Traits // :Frtesm esn that ACE_Connector reasons same the For A: ACE_SOCK_Connector Q: – – AESC_tem&new_sap, (ACE_SOCK_Stream os C_NTAd &laddr); ACE_INET_Addr const *timeout, ACE_Time_Value &raddr, ACE_INET_Addr const
incorrectly... the that ensures This An
h eopethe decouple Why e.g. passively established actively is or connection the whether of Regardless ACE_SOCK_Connectors ACE_SOCK_Stream o a’ accidentally can’t you , h C oncinOine Socket Connection-Oriented ACE The oktWaprFcd Structure Facade Wrapper Socket einItrue oiaigthe Motivating Interlude: Design rpe aaeFactories Facade Wrapper
r eope from decoupled are ACE_SOCK_Acceptor
ACE_SOCK* from sol epnil o aatransfer data for responsible only is
ACE_Acceptor ACE_SOCK_Stream or read() ACE_SOCK_Acceptors }; public: { ACE_SOCK_Acceptor class //... &addr); ACE_INET_Addr accept (const int open &); int ACE_INET_Addr (const ACE_SOCK_Acceptor PEER_STREAM; ACE_SOCK_Stream typedef PEER_ADDR; ACE_INET_Addr typedef Traits // ACE_SOCK public : opnnsae’ used aren’t components ACE_Svc_Handler AESC_tem&new_sap, (ACE_SOCK_Stream C_ieVle*); ACE_Time_Value *, ACE_INET_Addr or
write() n the and
and ? on oga .Schmidt C. Douglas oga .Schmidt C. Douglas etc. ,
, e.g. , 53 55 adritUniversity Vanderbilt Tutorial ACE Advanced Advanced ACE Tutorial Do SOCKET S S O API +Nv ( C++NPv1 A An Echo Server Written using C P K ACE C++ Socket Wrapper Facades cp fteAEICWaprFacades Wrapper IPC ACE the of Scope S T API TLI int echo_server (u_short port_num) A L www.cs.wustl.edu/˜schmidt/ACE/book1/ P I { // Local server address. S STREAM PIPE API PIPE ACE_INET_Addr my_addr (port_num); S P A I
P P // Initialize the acceptor mode server. E
S I A ACE_SOCK_Acceptor acceptor (my_addr); A P C P C E S S A
SSL // Data transfer object. API A S P L ACE_SOCK_Stream new_stream;
// Accept a new connection. PIPE API PIPE NAMED F
S acceptor.accept (new_stream); I A F P O for (;;) { char buf[BUFSIZ];
MMAP // Error caught at compile time! M S API E A ssize_t n = M P oga .Schmidt C. Douglas acceptor.recv (buf, sizeof buf); new_stream.send_n (buf, n); SYSTEM V S IPC API IPC
I } y P s ) } C V 58 Vanderbilt University
Advanced ACE Tutorial Do Advanced ACE Tutorial Do Using the Wrapper Facade Pattern A Generic Version of the Echo Server for the Logging Server Note we haven’t improved the overall design (yet) template
Vanderbilt University Vanderbilt University Advanced ACE Tutorial Do Advanced ACE Tutorial Do Receive and Process Logging Records Main Event Loop of Logging Server static ssize_t handle_log_record (ACE_SOCK_Stream s, int main (int argc, char *argv[]) ACE_HANDLE out_h) { ACE_UINT_32 len; initialize_acceptor ACE_Log_Record lr; (argc > 1 ? atoi (argv[1]) : PORT);
// The first recv reads the length (stored as a // Loop forever performing logging // fixed-size integer) of adjacent logging record. // server processing.
ssize_t n = s.recv_n ((char *) &len, sizeof len); for (;;) { if (n <= 0) return n; // object assignment. ready_handles = activity_handles; len = ntohl (len); // Convert byte-ordering // Perform sanity check! // Wait for client I/O events. if (len > sizeof (lr)) return -1; ACE::select (int (maxhp1), // calls operator fd_set *(). // The second recv then reads
Vanderbilt University Vanderbilt University
Advanced ACE Tutorial Do Advanced ACE Tutorial Do OO Client Logging Handling Connections and Daemon Implementation Data Processing int main (int argc, char *argv[]) static void handle_connections (void) { { if (ready_handles.is_set (acceptor.get_handle ())) ACE_SOCK_Stream stream; ACE_SOCK_Stream str; ACE_SOCK_Connector con; // Establish connection. con.connect (stream, ACE_INET_Addr (argc > 1 // Handle all pending connection requests. ? atoi (argv[1]) : PORT)); while (acceptor.accept (str) != -1) ACE_Log_Record lr; activity_handles.set_bit (str.get_handle ()); } // Loop forever performing client } // logging daemon processing. for (;;) { static void handle_data (void) { // ... get logging records from client ACE_HANDLE h; // application processes ... ACE_Handle_Set_Iterator iter (ready_handles); ACE_UINT_32 size = lr.size; lr.size = htonl (lr.size); while ((h = iter ()) != ACE_INVALID_HANDLE) { encode_log_record (&lr); ACE_SOCK_Stream str (h); iovec iov[2]; ssize_t n = handle_log_record (str, ACE_STDOUT); iov[0].iov_len = sizeof (ACE_UINT_32); if (n > 0) // Count # of logging records. iov[0].iov_base = &lr.size; ++request_count; iov[1].iov_len = size; else if (n == 0) { iov[1].iov_base = &lr; // Handle connection shutdown. // Uses writev(2); activity_handles.clr_bit (h); stream.sendv_n (iov, 2); s.close (); } } } }
Vanderbilt University Vanderbilt University Advanced ACE Tutorial Douglas C. Schmidt Advanced ACE Tutorial Douglas C. Schmidt Evaluating the Wrapper Facade Solution ACE C++ Wrapper Facade Benefits Liabilities Design Refactoring Principles
More concise Potentially more indirection
Enforce typesafety at compile-time
More robust Additional learning curve
Allow controlled violations of typesafety
More portable Still haven’t solved the overall
design problem Simplify for the common case
More maintainable
– i.e., the overall design is Replace one-dimensional interfaces with hierarchical class
More efficient still based on step-wise categories refinement of functions
Enhance portability with parameterized types
Inline performance critical methods
Define auxiliary classes to hide error-prone details
Vanderbilt University 64 Vanderbilt University 65
Advanced ACE Tutorial Douglas C. Schmidt Advanced ACE Tutorial Douglas C. Schmidt Enforce Typesafety at Compile-Time Allow Controlled Violations of Typesafety
Sockets cannot detect certain errors at compile-time, e.g., Make it easy to use the C++ Socket wrapper facades correctly, hard to use it incorrectly, but not impossible to use it in ways the class int acceptor = socket (PF_INET, SOCK_STREAM, 0); designers did not anticipate // ... bind (acceptor, ...); // Bind address. listen (acceptor); // Make a acceptor-mode socket. e.g., it may be necessary to retrieve the underlying socket handle: HANDLE n_sd = accept (acceptor, 0, 0); // Error not detected until run-time. ACE_SOCK_Acceptor acceptor; read (acceptor, buf, sizeof buf); // ... ACE enforces type-safety at compile-time via factories, e.g.: ACE_Handle_Set ready_handles; ACE_SOCK_Acceptor acceptor (port); // ... // Error: recv() not a method of
Vanderbilt University 66 Vanderbilt University 67 Do
Advanced ACE Tutorial Douglas C. Schmidt Supply Default Parameters
ACE_SOCK_Connector (ACE_SOCK_Stream &new_stream, const ACE_Addr &remote_sap, ACE_Time_Value *timeout = 0, const ACE_Addr &local_sap = ACE_Addr::sap_any, int protocol_family = PF_INET, int protocol = 0);
The result is extremely concise for the common case:
ACE_SOCK_Stream stream; &send_msg, 0);
// Compiler supplies default values. to pass socket handles: ACE_SOCK_Connector con (stream, ACE_INET_Addr (port, host)); LSOCK Define Parsimonious Interfaces (const ACE_HANDLE sd) const { ,use u_char a[2]; iovec iov;a[0] msghdr = send_msg; iov.iov_base 0xab, = a[1]iov.iov_len (char = = *) 0xcd; send_msg.msg_iov sizeof a; = a; send_msg.msg_iovlen &iov; =send_msg.msg_name 1; =send_msg.msg_namelen (char = *)send_msg.msg_accrights 0; 0; =send_msg.msg_accrightslen (char = *)return sizeof &sd; sendmsg sd; (this->get_handle (), e.g. ACE_LSOCK_Stream stream; ACE_LSOCK_Acceptor acceptor ("/tmp/foo"); acceptor.accept (stream); stream.send_handle (stream.get_handle ()); versus the less parsimonious BSD 4.3 socketACE_LSOCK::send_handle code Note that SVR4 and BSDthan 4.4 BSD APIs 4.3! are different Vanderbilt University Vanderbilt University 68 Advanced ACE Tutorial
Advanced ACE Tutorial Douglas C. Schmidt ACEAdvanced ACE Tutorial Douglas C. Schmidt IPC Combine Multiple Operations into One Operation SAP Create Hierarchical Class Categories
Creating a conventional acceptor-mode socket requires multiple calls: ACE SOCK int acceptor = socket (PF_INET, SOCK_STREAM, 0); sockaddr_in addr; ACE ACE ACE ACE ACE ACE memset (&addr, 0, sizeof addr); SOCK SOCK SOCK SOCK SOCK SOCK addr.sin_family = AF_INET; Dgram Dgram CODgram Stream Connector Acceptor addr.sin_port = htons (port); Bcast addr.sin_addr.s_addr = INADDR_ANY; ACE SOCK ACE ACE ACE ACE ACE bind (acceptor, &addr, addr_len); Dgram LSOCK LSOCK LSOCK LSOCK LSOCK listen (acceptor); Mcast Dgram CODgram Stream Connector Acceptor // ... GROUP DATAGRAM ACE STREAM CONNECTION L ACE_SOCK_Acceptor combines this into a single operation: COMM COMM SOCK COMM ESTABLISHMENT
ACE_SOCK_Acceptor acceptor ((ACE_INET_Addr) port);
Vanderbilt University 70 Vanderbilt University 71 Advanced ACE Tutorial Douglas C. Schmidt Advanced ACE Tutorial Douglas C. Schmidt Enhance Portability with Parameterized Types Inline Performance Critical Methods
// Conditionally select IPC mechanism. DISTRIBUTEDAPPLICATION1 DISTRIBUTEDAPPLICATION2 DISTRIBUTEDAPPLICATION3 #if defined (USE_SOCKETS) Inlining is time and space efficient since key methods are very short: APPLICATION 1 APPLICATION 2 APPLICATION 3 typedef ACE_SOCK_Acceptor PEER_ACCEPTOR; class ACE_SOCK_Stream : public ACE_SOCK COMMON INTERFACE #elif defined (USE_TLI) (PARAMETERIZED TYPES) typedef ACE_TLI_Acceptor PEER_ACCEPTOR; { SOCK_SAP TLI_SAP #endif // USE_SOCKETS. public: ssize_t send (const void *buf, size_t n) BSDSOCKET SOCKET BSDSYSTEM SOCKET V USER SPACE int main (void) { APIAPI TLIAPI API { return ACE_OS::send (this->get_handle (), buf, n); // ... OS KERNEL } KERNEL PROTOCOL MECHANISMS // Invoke with appropriate SPACE (TCP/IP, OSI, ETC.) // network programming interface. echo_server
Vanderbilt University 72 Vanderbilt University 73
Advanced ACE Tutorial Douglas C. Schmidt Advanced ACE Tutorial Douglas C. Schmidt Define Auxiliary Classes to Hide Error-Prone Details Demultiplexing and Dispatching Events
Standard C socket addressing is awkward and error-prone Problem – The logging server must process several different types of events
e.g., easy to neglect to zero-out a sockaddr_in or convert port simultaneously from different sources of events numbers to network byte-order, etc.
Forces ACE C++ Socket wrapper facades define classes to handle details – Multi-threading is not always available class ACE_INET_Addr : public ACE_Addr { public: – Multi-threading is not always efficient ACE_INET_Addr (u_short port, long ip_addr = 0) { – Multi-threading can be error-prone memset (&this->inet_addr_, 0, sizeof this->inet_addr_); this->inet_addr_.sin_family = AF_INET; – Tightly coupling event demuxing with server-specific logic is this->inet_addr_.sin_port = htons (port); inflexible memcpy (&this->inet_addr_.sin_addr, &ip_addr, sizeof ip_addr); } // ... Solution private: sockaddr_in inet_addr_; – Use the Reactor pattern to decouple event demuxing/dispatching }; from server-specific processing
Vanderbilt University 74 Vanderbilt University 75 Advanced ACE Tutorial Douglas C. Schmidt Advanced ACE Tutorial Douglas C. Schmidt The Reactor Pattern Collaboration in the Reactor Pattern Reactor select (handles); Intent handle_events() foreach h in handles loop callback : table[h].handle_event(type) main Reactor register_handler(h) Concrete Note inversion of end loop Demuxes & dispatches program Event_Handler control remove_handler(h) handlers Reactor() 1 N Event Handler requests that are INITIALIZE uses owns register_handler(callback) Handle handle_event(type) delievered concurrency REGISTER HANDLER Also note how get_handle() to an application by one get_handle() long-running notifies EXTRACT HANDLE or more clients MODE handle_events() event handlers Synchronous Event START EVENT LOOP Concrete INITIALIZATION select() can degrade Demultiplexer Event Forces Resolved FOREACH EVENT DO select() Handler handle_input() quality of service DATA ARRIVES Serially demux events since callbacks handle_output() www.cs.wustl.edu/˜schmidt/ synchronously & OK TO SEND “steal” Reactor’s handle_signal() POSA/ efficiently SIGNAL ARRIVES thread of
MODE handle_timeout() TIMER EXPIRES control...
Extend applications remove_handler(callback) without changing REMOVE HANDLER EVENT HANDLING handle_close() demuxing code CLEANUP
Vanderbilt University 76 Vanderbilt University 77 Do Do TOKEN : Event Handler Handler Acceptor : Logging ACE_WFMO_Reactor «bind» Application Event ACE_Event_Handler ACE_Select_Reactor 0..1 : Reactor ACE_Select_Reactor_T 1: handle_input() 2: sh = new Logging_Handler (sh->peer()) 3: accept 4: sh->open() Callbacks are “brittle” Can’t leverage multi-processors
of the ACE Reactor Framework Structure and Implementations LEVEL LEVEL LEVEL
APPLICATION FRAMEWORK ACE_Select_Reactor_Impl KERNEL Using the ACE Reactor Framework ACE_Time_Value Straightforward to program Concurrency control is easy ACE_Timer_Queue ACE_Reactor Advanced ACE Tutorial Reactor framework participants Common Reactor implementations in ACE Vanderbilt University Advanced ACE Tutorial Benefits Vanderbilt University Do
Advanced ACE Tutorial Douglas C. Schmidt Addressing Acceptor Endpoint Connection and Initialization Challenges initialization Problem
– The communication protocol used between applications is often Handler Svc
orthogonal to its connection establishment and service handler Acceptor peer_acceptor_ accept() Reactor protocols Reuse passive connection setup and service initialization code Ensure that acceptor-mode handles aren’t used to read/write data Forces resolved
Forces -
– Low-level connection APIs are error-prone and non-portable ACTIVATES – Separating initialization from processing increases software reuse INDEPENDENT APPLICATION
Solution (Acceptor Role)
– Use the Acceptor pattern to decouple passive connection - establishment and connection handler initialization from the Svc Handler initialized peer_stream_ open() connected and once the peer service is subsequent logging protocol DEFINED processing performed system from the The Acceptor-Connector Pattern www.cs.wustl.edu/˜schmidt/POSA/ service in a distributed APPLICATION initialization of a peer connection and Decouple the passive Intent of Acceptor Role Vanderbilt University Vanderbilt University 80 Advanced ACE Tutorial Do Do IPC an : Svc Handler Handler : Logging PEER_STREAM, SYNCH_STRATEGY : Svc SYNCH_STRATEGY Handler Handler ACE_Task : Logging strategize Service «bind» Application activates ACE_Svc_Handler : Svc , and Handler Handler factory ACTIVE : Logging CONNECTIONS SVC_HANDLER, PEER_CONNECTOR : Reactor : is a ACE_Acceptor ACE_Acceptor connects ACE_Connector , : Svc Handler Handler : Logging aspects Structure of the ACE in the Logging Server PASSIVE LISTENER creates SVC_HANDLER, PEER_ACCEPTOR Using the ,it ACE_Acceptor service ACE_Svc_Handler i.e. Acceptor-Connector Framework ACE_Acceptor – Uses C++ parameterized types to Uses Template Method pattern tocreation, strategize connection establishment, and concurrency policies The There’s often one per-service/per-port and Acceptor : Logging : Acceptor ACE_Event_Handler 1: handle_input() make_svc_handler() 2: sh = 3: accept_svc_handler(sh) 4: activate_svc_handler(sh) Advanced ACE Tutorial Framework characteristics Vanderbilt University Advanced ACE Tutorial Vanderbilt University adritUniversity Vanderbilt Tutorial ACE Advanced primitive_operation2() primitive_operation1() template_method() Advanced ACE Tutorial Do primitive_operation2() primitive_operation1() Abstract ACE_Acceptor Class Public Interface Class Concrete Class template
protected:
// Factory method creates a service handler.
atrs lmnsof Elements Patterns: Software esbeObject-Oriented Reusable al., et Gamma Intent virtual SVC_HANDLER *make_svc_handler (void);
// Accept a new connection.
nagrtmi an in algorithm an oesesto steps some en h kltnof skeleton the Define prto,deferring operation, subclasses virtual int accept_svc_handler (SVC_HANDLER *); // Activate a service handler. virtual int activate_svc_handler (SVC_HANDLER *); W ’94 AW, private: // Acceptor IPC connection strategy. Design PEER_ACCEPTOR peer_acceptor_; oga .Schmidt C. Douglas }; 86 Vanderbilt University adritUniversity Vanderbilt dacdAETutorial ACE Advanced activate_svc_handler() accept_svc_handler() make_svc_handler() handle_input() activate_svc_handler() make_svc_handler() Advanced ACE Tutorial Do Acceptor Acceptor ACE_Acceptor Class Implementation My
sn h epaeMto atr in Pattern Method Template the Using // Shorthand names. #define SH SVC_HANDLER h C cetrImplementation Acceptor ACE the #define PA PEER_ACCEPTOR
// Template Method that creates, connects,
activate_svc_handler() ... accept_svc_handler() ... make_svc_handler() ... // and activates service handlers.
template
SH *svc_handler = make_svc_handler (); Liabilities Benefits // Accept the connection. n yai binding dynamic and inheritance via program to Straightforward wieo”design “whitebox” to due subclasses of “explosion” cause can and “brittle” is Design accept_svc_handler (svc_handler);
// Delegate control to the service handler.
activate_svc_handler (svc_handler);
oga .Schmidt C. Douglas } 87 Vanderbilt University Advanced ACE Tutorial Douglas C. Schmidt Advanced ACE Tutorial Douglas C. Schmidt The Strategy Pattern Using the Strategy Pattern in Intent the ACE Acceptor Implementation
STRATEGY Benefits Context Strategy Define a family of Acceptor Concurrency <
Vanderbilt University 88 Vanderbilt University 89 Do Do method open() ’s Initialization Template Method Implementation PEER_ACCEPTOR (this, ACE_Event_Handler::ACCEPT_MASK); Hook Implementations ACE_Acceptor sh->close (); ACE_Acceptor ACE_Reactor *reactor) return new SH; // Default behavior. peer_acceptor_.accept (sh->peer ()); if (sh->open () == -1) (typename const PA::PEER_ADDR &addr, // Forward// initialization peer topeer_acceptor_.open acceptor. the (addr); concrete // Registerreactor->register_handler with Reactor. hides all the detailsinitializing associated communication with endpoints passively Advanced ACE Tutorial Template method hooks can be overridden // Factorytemplate method
SERVER LOGGING Service Note how IPC and synchronization aspects are DAEMON Config strategized
Logging Service template
// Return underlying IPC mechanism. CLIENT PEER_STREAM &peer (void); CLIENT CLIENT CLIENT // ... private: PEER_STREAM peer_; // IPC mechanism. virtual ˜ACE_Svc_Handler (void); };
Vanderbilt University Vanderbilt University } epae
The Logging_Handler and ACE_Event_Handler::READ_MASK); (this, Logging_Acceptor Classes ACE_Svc_Handler // Performs I/O with client logging daemons. class Logging_Handler : public ACE_Svc_Handler
Q: How can you switch between different IPC mechanisms?
Callback routine that receives logging records Implementation of A: By parameterizing IPC Mechanisms with C++ Templates, e.g.: application-specific #if defined (ACE_USE_SOCKETS) int logging method typedef ACE_SOCK_Acceptor PEER_ACCEPTOR; Logging_Handler::handle_input (ACE_HANDLE)
#elif defined (ACE_USE_TLI) { This is the main code typedef ACE_TLI_Acceptor PEER_ACCEPTOR; // Call existing function to recv supplied by a #endif /* ACE_USE_SOCKETS */ // logging record and print to stdout. ssize_t n = developer! class Logging_Handler : public handle_log_record (peer ().get_handle (), ACE_Svc_Handler
Vanderbilt University 96 Vanderbilt University 97 Do
Advanced ACE Tutorial Douglas C. Schmidt Putting the Pieces Together at Run-time
Problem – Prematurely committing ourselves to a particular logging server configuration is inflexible and inefficient Initialization
Forces – It is useful to build systems by “scripting” components – Certain design decisions can’t be made efficiently until run-time – It is a bad idea to force users to “pay” for components they do not use and Termination
Solution
addr.set (atoibreak; (getopt.optarg)); break; – Use the Component Configurator pattern to assemble the desired
case ’p’: default: logging server components dynamically switch (c) { } Logging_Acceptor ACE_Get_Opt get_optACE_INET_Addr (argc, addr argv, (DEFAULT_PORT); "p:", 0); for (int c; (c = get_opt ()) != -1; ) // Initialize// endpoint with andopen the register (addr,
Advanced ACE Tutorial Douglas C. Schmidt The Component Configurator Pattern Intent Concrete Component
LAYER Decouples the
APPLICATION implementation of services from the time when they are Component Component Config configured ACE_Service_Config uses a variant of the ACE_Service_Repository suspend() 1 1 resume() n Forces Resolved
init() A ACE_Service_Repository_Iterator fini() 1 1 LAYER info() Reduce resource utilization Component
CONFIGURATION Repository
Support dynamic (re)configuration
Event www.cs.wustl.edu/ Configurator Framework Handler n Reactor
LAYER 1 Structure of the ACE Service REACTIVE ˜schmidt/POSA/ Monostate pattern ACE_Service_Config Can be accessed either viaprogrammatically a script or ACE_Event_Handler ACE_Service_Object Application Service Framework characteristics Vanderbilt University Vanderbilt University 100 Advanced ACE Tutorial Do
Advanced ACE Tutorial Douglas C. Schmidt Dynamically Linking a Service Pool Object Logger Object Service Thread Logger Service Thread
Dynamically linked factory function Application-specific factory S svc.conf that allocates a new function used to dynamically DLL Logging_Acceptor create a service extern "C"
ACE_Service_Object * The make_Logger() function make_Logger (void); provides a hook between an application-specific service ACE_Service_Object * and the Object
Logger make_Logger (void) Service Reactive Reactor { application-independent ACE dynamic Logger Service_Object * Service_Object Logger dynamic "-p 2001" logger:make_Logger() return new Logging_Acceptor; mechanisms // Framework automatically // deletes memory. – ACE handles all memory } allocation and deallocation FILE svc.conf Service Config Repository Service Framework for the Logging Server SERVICE RUNTIME The existing Logging Server servicesingle-threaded is Other versions could be multi-threaded Note how we can scriptfile this via the Using the ACE Service Configurator CONFIGURATOR
Advanced ACE Tutorial Vanderbilt University Vanderbilt University 103 Advanced ACE Tutorial Douglas C. Schmidt Advanced ACE Tutorial Douglas C. Schmidt Service Configuration State Chart for the Service Configurator Framework CONFIGURE/ The logging service is configured Generic event-loop to Service_Config::process_directives() via scripting in a svc.conf file: dynamically configure service % cat ./svc.conf daemons INITIALIZED # Dynamically configure int main (int argc, char *argv[]) IDLE START # the logging service { EVENT LOOP/ dynamic Logger // Initialize the daemon and Reactor::run_event_loop() Service_Object * // configure services SHUTDOWN/ logger:_make_Logger() "-p 2001" ACE_Service_Config::open (argc, NETWORK EVENT/ Service_Config::close() AWAITING # Note, .dll or .so suffix argv); EVENTS Reactor::dispatch() # added to the logger // Run forever, performing the # automatically // configured services ACE_Reactor::instance ()-> PERFORM run_reactor_event_loop (); RECONFIGURE/ CALLBACK /* NOTREACHED */ Service_Config::process_directives() } CALL HANDLER/ Event_Handler::handle_input()
Vanderbilt University 104 Vanderbilt University 105
Advanced ACE Tutorial Douglas C. Schmidt Advanced ACE Tutorial Douglas C. Schmidt Advantages of OO Logging Server Concurrent OO Logging Server
The OO architecture illustrated thus far decouples application-specific service functionality from:
The structure of the Logging Server can benefit from concurrent – Time when a service is configured into a process execution on a multi-processor platform – The number of services per-process
– The type of IPC mechanism used This section examines ACE C++ classes and patterns that extend – The type of event demultiplexing mechanism used the logging server to incorporate concurrency
We can use the techniques discussed thus far to extend applications – Note how most extensions require minimal changes to the without: existing OO architecture... – Modifying, recompiling, and relinking existing code
This example also illustrates additional ACE components involving – Terminating and restarting executing daemons synchronization and multi-threading
The remainder of the Logging Server slides examine a set of techniques for decoupling functionality from concurrency mechanisms, as well
Vanderbilt University 106 Vanderbilt University 107 rdtoa Spoesscnanasnl hedo control of thread single a contain processes OS Traditional adritUniversity Vanderbilt dacdAETutorial ACE Advanced Advanced ACE Tutorial Do rtce rmuwne nefrneb te execution other is sequences... by steps interference execution unwanted of from sequence protected a since programming simplifies This Concurrent OO Logging SHARED ADDRESS SPACE Server Architecture PROCESS THREADS SERVER LOGGING SERVER 1: SOCK Acceptor ocrec Overview Concurrency 2: accept() 4: handle_input() 5: spawn() 7: recv() 7: recv() 8: write() 8: write() Logging Acceptor Logging Logging Reactor Handler Handler 3: connect() rmr processes more or one in executed of instructions sequence a is thread A –
– 6: send()
oeta n process one than More itiue systems distributed systems stand-alone process One 6: send() CLIENT CLIENT A NETWORK B !
Runs each client connection in a separate thread oga .Schmidt C. Douglas ! 110 Vanderbilt University .Dvc rvr n rgaswt inlhnlr tlz limited a utilize handlers signal with programs and drivers Device 1. .Mn xsigporm tlz Spoesst provide to processes OS utilize programs existing Many 2. dacdAETutorial ACE Advanced adritUniversity Vanderbilt University Vanderbilt dacdAETutorial ACE Advanced omof form cas-rie”concurrency “coarse-grained” ogn Server Logging } { (void) logging_handler void for Pseudo-code } { (void) handler_factory void multi-threaded for Pseudo-code
– –
oec icmn ogn eod rmclient) thread from exit records logging (incoming foreach } { event) connection (pending endpoint foreach acceptor initialize e.g. h Skre ceue ittspoesbehavior process dictates execution scheduler coordinate kernel to OS semaphores The use mapping and memory memory via shared memory or share may processes OS Multiple that Note e.g. tnadntokdeoslk UNIX like daemons network Standard applications database Client/server rdtoa prahst SConcurrency OS to Approaches Traditional
, I/O asynchronous , concurrency suocd o ocretServer Concurrent for Pseudo-code
alhandle_log_record() call concurrency pw hedt adecneto and connection point handle entry to logging_handler() thread run a spawn connection accept logging_handler() nopse oethan more encompasses Logging_Handler function
INETD multi-threading factory oga .Schmidt C. Douglas oga .Schmidt C. Douglas ... 109 111 Advanced ACE Tutorial Douglas C. Schmidt Advanced ACE Tutorial Douglas C. Schmidt Evaluating Traditional OS Process-based Concurrency Modern OS Concurrency
Advantages
Modern OS platforms typically provide a standard set of APIs that – Easy to keep processes from interfering handle
A process combines security, protection, and robustness – Process/thread creation and destruction
Disadvantages – Various types of process/thread synchronization and mutual – Complicated to program , e.g., exclusion – Asynchronous facilities for interrupting long-running – Signal handling may be tricky processes/threads to report errors and control program behavior – Shared memory may be inconvenient
Once the underlying concepts are mastered, it’s relatively easy to Inefficient learn different concurrency APIs – The OS kernel is involved in synchronization and process – e.g., traditional UNIX process operations, Solaris threads, POSIX management pthreads, WIN32 threads, Java threads, etc. – Difficult to exert fine-grained control over scheduling and priorities
Vanderbilt University 112 Vanderbilt University 113 Do
Advanced ACE Tutorial Douglas C. Schmidt Lightweight Concurrency SERVICE SERVICE SERVER SERVICE SERVER
EXECUTES SERVER EXECUTES Modern operating systems provide lightweight mechanisms that EXECUTES manage and synchronize multiple threads within a process USER USER USER – Some systems also allow threads to synchronize across multiple KERNEL KERNEL KERNEL processes - RPC RPC - Benefits of threads
1. Relatively simple and efficient to create, control, synchronize, and REQUEST MULTI RESPONSE SINGLE RESPONSE REQUEST collaborate REQUEST RESPONSE THREADED THREADED – Threads share many process resources by default THREADED 2. Improve performance by overlapping computation and
communication
KERNEL
– Threads may also consume less resources than processes KERNEL USER
3. Improve program structure USER Multi-threaded Applications
– e.g., compared with using asynchronous I/O Example: Single-threaded vs. THREAD BLOCKED CLIENT CLIENT CLIENT
Vanderbilt University 114 Advanced ACE Tutorial Vanderbilt University Advanced ACE Tutorial Douglas C. Schmidt Advanced ACE Tutorial Douglas C. Schmidt Hardware and OS Concurrency Support Application Threads Four typical Most process resources are Each thread also contains unique abstractions LEVEL
- equally accessible to all threads information, e.g.,
LWP LWP LWP LWP LWP LWP LWP 1. Application in a process, e.g., USER Identifier threads Virtual memory
Register set (e.g., PC and SP) 2. Lightweight
User permissions and access
LEVEL processes Run-time stack - PE PE PE PE PE PE PE PE control privileges
3. Kernel threads Signal mask
Open files KERNEL
SHARED MEMORY 4. Processing Priority
Signal handlers elements
Thread-specific data (e.g., PE LWP UNIX errno) PROCESSING LIGHTWEIGHT PROCESS THREAD ELEMENT PROCESS Note, there is no MMU protection for threads in a single process
Vanderbilt University 116 Vanderbilt University 117
Advanced ACE Tutorial Douglas C. Schmidt Advanced ACE Tutorial Douglas C. Schmidt Kernel-level vs. User-level Threads Overview of OS Synchronization Mechanisms
Application and system characteristics influence the choice of user-level vs. kernel-level threading Threads share resources in a process address space
Therefore, they must use synchronization mechanisms to coordinate
A high degree of “virtual” application concurrency implies user-level threads (i.e., unbound threads) their access to shared data
– e.g., desktop windowing system on a uni-processor Traditional OS synchronization mechanisms are very low-level, tedious to program, error-prone, and non-portable
A high degree of “real” application parallelism implies lightweight processes (LWPs) (i.e., bound threads) ACE encapsulates these mechanisms with wrapper facades and higher-level patterns/components – e.g., video-on-demand server or matrix multiplication on a multi-processor
Vanderbilt University 118 Vanderbilt University 119 Advanced ACE Tutorial Douglas C. Schmidt Advanced ACE Tutorial Douglas C. Schmidt Common OS Synchronization Mechanisms Additional ACE Synchronization Mechanism
Mutual exclusion (mutex) locks Events – Serialize thread access to a shared resource – Gates and latches
Counting semaphores Barriers – Synchronize thread execution – Allows threads to synchronize their completion
Readers/writer (R/W) locks Token – Serialize resources that are searched more than changed – Provides FIFO scheduling order
Condition variables Task – Used to block threads until shared data changes state – Provides higher-level “active object” for concurrent applications
File locks Thread-specific storage – System-wide R/W locks accessed by processes – Low-overhead, contention-free storage
Vanderbilt University 120 Vanderbilt University 121 Do
Advanced ACE Tutorial Douglas C. Schmidt MUTEX
Read Addressing Logger Server Concurrency Challenges Guard Null Write Condition Guard Guard Condition GUARDS CONDITIONS
Problem TYPE SYNCH
TSS – Multi-threaded logging servers may be necessary when Thread Task Semaphore single-threaded reactive servers inefficient, non-scalable, or Thread Process non-robust Semaphore Semaphore
Forces ACTIVE TYPE LOCK OBJECTS File Op Lock Atomic
RW – Multi-threading can be very hard to program Mutex – No single multi-threading model is always optimal Events
Solution Process Barrier Manager Null Mutex – Use the Active Object pattern to allow multiple concurrent logging Mutex Thread server operations using an OO programming style MANAGERS Concurrency Mechanisms in ACE ADVANCED SYNCH Thread Token Manager All ACE Concurrency mechanisms areall ported OS to platforms www.cs.wustl.edu/˜schmidt/ACE/ book1/ Mutex Mutex Process SYNCH WRAPPERS
Advanced ACE Tutorial Vanderbilt University Vanderbilt University 123 adritUniversity Vanderbilt Tutorial ACE Advanced Advanced ACE Tutorial Do ACE_Task other ACE_Task An betsdt n methods and data object’s – –
rcse in processes Each separate processes in heavyweight parallel or in lightweight execute may objects active Multiple The Active Object Pattern ACE_Task
ACE_Task loop {
ACE_Task m = act_list.dequeue() Proxy if (m.guard()) m.call() else act_list.enqueue (m); salwlvlmcaimt upr cieobjects active support to mechanism low-level a is to messages typed passing by communicate objects Future m1() 1: enqueue(new M1) } Future m2()
id eaaetra fcnrltgte ihan with together control of thread separate a binds roiyorder priority Activation h C akFramework Task ACE The Future m3() 3: dispatch() objects Scheduler List
anan uu fpnigmsae htit that messages pending of queue a maintains dispatch() enqueue() VISIBLE enqueue() 2: enqueue(M1) dequeue() TO 1 CLIENTS n Servant Method M1 m1() 11Request M2 HIDDEN m2() FROM guard() CLIENTS m3() 4: m1() call() M3 www.cs.wustl.edu/˜schmidt/POSA/
Intent Forces Resolved Decouples method Allow blocking execution from method operations invocation to enhance
Permit flexible concurrency and simplify oga .Schmidt C. Douglas concurrency synchronized access to strategies an object that resides in its own thread of control 126 Vanderbilt University
Advanced ACE Tutorial Do Advanced ACE Tutorial Do Structure of the ACE Task Framework ACE Support for Active Objects
t2 : ACE_Event_Handler ACE_Service_Object Task : TASK 2: enqueue (msg) STATE 3: svc () : Message 4: dequeue (msg) SYNCH Queue 0..1 * 5: do_work(msg) ACE_Thread_Manager ACE_Task ACTIVE
1: put (msg) 6: put (msg) SYNCH ACE_Message_Block ACE_Message_Queue t3 : * 1 t : Task : TASK 1 STATE Task : TASK STATE : Message Queue : Message Queue ACTIVE
Framework characteristics ACTIVE
1. ACE_Tasks can register with an ACE_Reactor The ACE Task framework can be used to 2. They can be dynamically linked implement the complete Active Object pattern or 3. They can queue data lighterweight subsets 4. They can run as active objects in 1 or more threads
Vanderbilt University Vanderbilt University Advanced ACE Tutorial Douglas C. Schmidt Advanced ACE Tutorial Douglas C. Schmidt The ACE_Task Class Public Interface ACE_Task Class Protected Interface template
Vanderbilt University 128 Vanderbilt University 129
Advanced ACE Tutorial Douglas C. Schmidt Advanced ACE Tutorial Douglas C. Schmidt Design Interlude: Combining Threads & C++ Objects The svc_run() Adapter Function ACE_Task::svc_run() is static method used as the entry point to Q: What is the svc_run() execute an instance of a service concurrently in its own thread
A: OS thread APIs require C-style functions as entry point function and why is it a static method? template
The ACE Task framework encapsulates the svc_run() function ACE_Task
Vanderbilt University 130 Vanderbilt University 131 Advanced ACE Tutorial Douglas C. Schmidt Advanced ACE Tutorial Douglas C. Schmidt Design Interlude: Motivation Using ACE Task Framework for Logging Server for the ACE_Thread_Manager
Process remote logging records The OO implementation localizes by looping until the client the application-specific part of
Q: How can groups of collaborating threads be managed atomically? terminates connection the logging service in a single int point, while leveraging off
A: Develop the ACE_Thread_Manager class that: Thr_Logging_Handler::svc (void) reusable ACE components – Supports the notion of thread groups { while (handle_input () != -1) Compare with original, which
i.e., operations on all threads in a group // Call existing function borrow’s the Reactor thread – Implements barrier synchronization on thread exits // to recv logging record int – Shields applications from incompatibilities between different OS // and print to stdout. Logging_Handler::handle_input (void) thread libraries continue; { handle_log_record
e.g., detached threads and thread joins return 0; (peer ().get_handle (), } ACE_STDOUT); // ... }
Vanderbilt University 132 Vanderbilt University 133 Do Do Stream Service SOCK_Stream NULL_Synch Configurator PEER_STREAM SYNCH and Thr Svc Handler Logging n Handler Interfaces Reactor Connection PEER STREAM <
Thr_Logging_Acceptor
Class Diagram for Concurrent
COMPONENTS COMPONENTS COMPONENTS
// Override// definition class in// to
SPECIFIC ORIENTED FRAMEWORK Thr_Logging_Handler
virtual int open (void *); virtual int svc (void); ACE_Acceptor
aet o h ocretLgigServer Logging Concurrent the for Caveats Implementation
Override definition in the ACE_Svc_Handler class to spawn a new thread handle_log_record() int Thr_Logging_Handler::open (void *) { // Spawn a new thread to handle // logging records with the client. activate (THR_DETACHED); } Process remote logging records by looping until client terminates connection
request_count int ucini o serialized not is function Thr_Logging_Handler::svc (void) { while (handle_input () != -1) // Call existing function to recv // logging record and print to stdout.
oga .Schmidt C. Douglas continue; } salso is 138 Vanderbilt University dlo s ufxaddto added suffix automatically .so "thr_logger" or # .dll # thr_logger:_make_Logger() * Service_Object Logger dynamic service Logger logging remove the reconfigure # Dynamically ./svc.conf # cat % a svc.conf in scripting via configured is service logging The Tutorial ACE Advanced adritUniversity Vanderbilt University Vanderbilt server to signal the SIGHUP changing sending by reconfigured is service Logging dacdAETutorial ACE Advanced oee,adn these adding However, } out_h) ACE_HANDLE in_h, { (ACE_HANDLE mechanism handle_log_record synchronization ... 5.x // SunOS // scope lock; file mutex_t at // exclusion mutual OS explicitly, uses mechanisms serialization for approach One /... -1) // == (&lock); lr.size) mutex_unlock lr.buf, (out_h, (ACE_OS::write ... if scope (&lock); method mutex_lock in // yaial eofiuigteLgigServer Logging the Reconfiguring Dynamically eun-1; return xlctSnhoiainMechanisms Synchronization Explicit file:
- 2002" "-p e.g. mutex , } { (void) make_Logger * ACE_Service_Object (void); *make_Logger ACE_Service_Object "C" extern new threaded a allocates that function factory linked Dynamically al xlctycue problems... causes explicitly calls eunnwThr_Logging_Acceptor; new return Logging_Acceptor svc.conf oga .Schmidt C. Douglas oga .Schmidt C. Douglas l and file 137 139 Do
Advanced ACE Tutorial Douglas C. Schmidt Problem: Explicit mutex_* Calls
Inelegant ! “Impedance mismatch” with C/C++
Obtrusive – Must find and lock all uses of write() – Can yield inheritance anomaly
Error-prone – C++ exception handling and multiple method exit points – Thread mutexes won’t work for separate processes – Global mutexes may not be initialized correctly Wrapper Facades
Non-portable ! Hard-coded to Solaris 2.x Solution: Synchronization
Inefficient ! e.g., expensive for certain platforms/designs { return mutex_trylock (&lock_); } mutex_init (&lock_, USYNCH_THREAD, 0); ACE_Thread_Mutex (void) { } ˜ACE_Thread_Mutex (void)int { acquire mutex_destroyint (void) (&lock_); tryacquire { (void) return mutex_lockint (&lock_); release } (void) { return mutex_unlock// (&lock_); SunOSmutex_t 5.x lock_; serializationvoid mechanism. operator=ACE_Thread_Mutex (const (const ACE_Thread_Mutex ACE_Thread_Mutex &); &); class ACE_Thread_Mutex { public: private: }; Note how we prevent improperassignment copying by and using C++ access control specifiers Vanderbilt University Vanderbilt University 140 Advanced ACE Tutorial Do
Advanced ACE Tutorial Douglas C. Schmidt Using the C++ Mutex Wrapper Facade
Using C++ wrapper facades improves portability and elegance to // at file scope. ACE_Thread_Mutex lock; // Implicitly unlocked.
// ... handle_log_record (ACE_HANDLE in_h, ACE_HANDLE out_h) { // in method scope ...
lock.acquire (); if (ACE_OS::write (out_h, lr.buf, lr.size) == -1) return -1; lock.release (); Windows NT // ... ACE_Thread_Mutex
However, this doesn’t really solve the tedium or error-proneness problems www.cs.wustl.edu/˜schmidt/PDF/ObjMan.pdf
Porting – lock_ = CreateMutex (0, FALSE, 0); CloseHandle (lock_); return WaitForSingleObject (lock_, INFINITE); return WaitForSingleObject (lock_, 0); return ReleaseMutex (lock_); ACE_Thread_Mutex (void) { } ˜ACE_Thread_Mutex (void) { } int acquire (void) { } int tryacquire (void) { } int release (void) { } ACE_HANDLE lock_;// // ... Windows locking mechanism.
Advanced ACE Tutorial class ACE_Thread_Mutex { public: private: Vanderbilt University Vanderbilt University 143 Advanced ACE Tutorial Douglas C. Schmidt Advanced ACE Tutorial Douglas C. Schmidt Automated Mutex Acquisition and Release The ACE_GUARD Macros
To ensure mutexes are locked and unlocked, we’ll define a template ACE defines a set of macros that simplify the use of the class that acquires and releases a mutex automatically ACE_Guard, ACE_Write_Guard, and ACE_Read_Guard classes template
ACE_Guard uses the Scoped Locking idiom whereby a constructor ACE_Read_Guard
Vanderbilt University 144 Vanderbilt University 145 Do
Advanced ACE Tutorial Douglas C. Schmidt Design Interlude: Motivating the ACE_Guard Design
Q: Why is ? ACE_Guard
A: since many differentparameterized flavors of locking by the can type benefit of LOCK from the Scoped Locking protocol – e.g., non-recursive vs. recursive mutexes, intra-process vs. inter-process mutexes, readers/writer mutexes, POSIX and System V semaphores, file locks, and the null mutex
Function Q: Why are templates used, as opposed to
handle_log_record() inheritance/polymorphism?
A: since they are more efficient and can reside in shared memory
All ACE synchronization wrapper facades use the Adapter pattern to provide identical interfaces to facilitate parameterization return -1; // Automatically release mutex lock. // bewarestatic static LOCK initialization... ACE_UINT_32 lock; len; ACE_Log_Record lr; // The// first fixed-size recvssize_t integer) reads n of theif = adjacent length (n s.recv_n logging (stored <= ((char record. as 0) *)len a return &len, = n; sizeof// ntohl len); Perform (len);if sanity // (len check! Convert > byte-ordering sizeof// (lr)) The return// second -1; obtain recvs.recv_n the then ((char actual reads *) record.
Advanced ACE Tutorial template
Force resolved: // Danger, race condition!!! Solving this problem specific_request()Adaptee2 using the
Provide an interface specific_request()Adaptee3 return n <=0?-1:0; ACE_Thread_Mutex that captures } specific_request() or ACE_Guard classes similarities between A more elegant solution incorporates is still tedious, different OS parameterized types, overloading, and the low-level, and mechanisms, e.g., Strategized Locking pattern, as discussed in error-prone locking or IPC C++NPv1
Vanderbilt University 148 Vanderbilt University 149 Do
Advanced ACE Tutorial Douglas C. Schmidt Final Version of Concurrent Logging Server
Using the Atomic_Op class, only one change is made // At file scope. typedef ACE_Atomic_Op<> COUNTER; // Note default parameters... COUNTER request_count;
request_count is now serialized automatically pattern, C++ for (; ; ++request_count) // ACE_Atomic_Op::operator++ handle_log_record (get_handle (), ACE_STDOUT);
The original non-threaded version may be supported efficiently as follows: typedef ACE_Atomic_Op
class TYPE = u_long> for (; ; ++request_count)
Strategized Locking handle_log_record
Transparently Parameterizing (get_handle (), ACE_STDOUT); ACE_GUARD (LOCK, guard, lock_); return ++count_; ACE_GUARD (LOCK, guard, lock_); return count_; ACE_Atomic_Op (TYPETYPE c operator++ = (void) 0) { {} count_ =operator c; TYPE } () { } // Other arithmetic operationsLOCK omitted... lock_; TYPE count_; Advanced ACE Tutorial Use the template Advanced ACE Tutorial Douglas C. Schmidt Concurrent Web Client/Server Example ) HANDLERS ) SERVER SERVER PROTOCOL WWW WWW O SUBSYSTEM DISPATCHER / OS KERNEL The following example illustrates a concurrent OO architecture for a HTTP HTTP OS I NETWORK ADAPTERS ., ., G G . high-performance Web client/server . E E ( ( Key functional and non-functional system requirements are: COMMUNICATION PROTOCOL – Robust implementation of HTTP 1.0 protocol COMMUNICATION PROTOCOL i.e., resilient to incorrect or malicious Web clients/servers NETWORK HTTP/1.0 – Extensible for use with other protocols HTTP/1.0 2: index.html 2: index.html 1: GET ~schmidt e.g., DICOM, HTTP 1.1, CORBA Simple Flow Protocol (SFP) 1: GET ~schmidt – Leverage multi-processor hardware and OS software e.g., Support various concurrency patterns HTML PARSER HTML PARSER REQUESTER REQUESTER O SUBSYSTEM / CLIENT CLIENT WWW www.cs.wustl.edu/˜jxh/research/ OS KERNEL OS I ADAPTER ADAPTER NETWORK ADAPTERS GRAPHICS GRAPHICS GUI GUI General Web Client/Server Interactions Vanderbilt University Vanderbilt University 152 Advanced ACE Tutorial Do Advanced ACE Tutorial Douglas C. Schmidt Design Interlude: Motivating a Request Queue Q: Why use a request queue to store messages, rather than directly reading from I/O handles? A: – Promotes more efficient use of multiple CPUs via load balancing – Enables transparent interpositioning and prioritization – Makes it easier to shut down the server correctly and portably – Improves robustness to “denial of service” attacks Server – Moves queueing into the application process rather than OS Drawbacks receive and queue request on queue – Using a message queue may lead to greater context switching and synchronization overhead... dequeue and process request – Single point for bottlenecks initialize queuespawn and pool acceptorforeach of at (pending worker port work threads 80 request} from clients)exit { process foreach (work request onexit queue) thread Pseudo-code for Concurrent Web Pseudo-code for master server void master_server{ (void) } Pseudo-code for thread pool workers void worker{ (void) } As usual, make sure to avoid the “grand mistake” Advanced ACE Tutorial Vanderbilt University Vanderbilt University 155 Advanced ACE Tutorial Do Advanced ACE Tutorial Do Pseudo-code for recv_requests() Thread Entry Point void recv_requests (MESSAGE_QUEUE *msg_queue) typedef ACE_Unbounded_Queue Vanderbilt University Vanderbilt University adritUniversity Vanderbilt Tutorial ACE Advanced Advanced ACE Tutorial Do hr are There hard-codes it since portable not is solution The application-specific functionality couples tightly decomposition algorithmic The – – – – – okt and sockets threading 5.x SunOS h iewe evcsaecngrdit process a into configured are services when time process The per services of number The protocol 1.0 HTTP The Master Server Driver Function // Thread function prototype. aeconditions race typedef void *(*THR_FUNC)(void *); iiain ihteWbServer Web the with Limitations ihvroscngrto-eae characteristics, configuration-related various with select() int main (int argc, char *argv[]) { parse_args (argc, argv); // Queue client requests. MESSAGE_QUEUE msg_queue; // Spawn off NUM_THREADS to run in parallel. ntecode the in for (int i = 0; i < NUM_THREADS; i++) thr_create (0, 0, THR_FUNC (&worker), (void *) &msg_queue, THR_BOUND, 0); // Initialize network device and // recv HTTP work requests. thr_create (0, 0, THR_FUNC (&recv_requests), (void *) &msg_queue, THR_BOUND, 0); oga .Schmidt C. Douglas // Wait for all threads to exit (BEWARE)! while (thr_join (0, &t_id, (void **) 0) == 0) continue; // ... } e.g. 159 , Vanderbilt University Advanced ACE Tutorial Douglas C. Schmidt Advanced ACE Tutorial Douglas C. Schmidt Overcoming Limitations via OO Eliminating Race Conditions The algorithmic decomposition illustrated above specifies too many Problem low-level details – A naive implementation of MESSAGE_QUEUE will lead to race – Moreover, the excessive coupling complicates reusability, conditions extensibility, and portability... e.g., when messages in different threads are enqueued and dequeued concurrently In contrast, OO focuses on decoupling application-specific behavior from reusable application-independent mechanisms Forces – Producer/consumer concurrency is common, but requires careful The OO approach described below uses reusable framework components and commonly recurring patterns attention to avoid overhead, deadlock, and proper control Solution – Utilize the Monitor Object pattern and condition variables Vanderbilt University 160 Vanderbilt University 161 Advanced ACE Tutorial Douglas C. Schmidt Advanced ACE Tutorial Douglas C. Schmidt The Monitor Object Pattern Overview of Condition Variables Intent Monitor Object + synchronized_method_1() Condition variables (CVs) are used to “sleep/wait” until a particular ... Synchronizes method execution to ensure + synchronized_method_m() condition involving shared data is signaled only one method runs within an object at a # monitor_lock_ # monotor_condition_1_ – CVs can wait on arbitrarily complex C++ expressions time. It also allows an object’s methods to ... – Sleeping is often more efficient than busy waiting... cooperatively schedule their execution # monitor_condition_n_ sequences. ˜schmidt/POSA/ This allows more complex scheduling decisions, compared with a Forces Resolved mutex – i.e.,amutexmakesother threads wait, whereas a condition Synchronization corresponds to methods variable allows a thread to make itself wait for a particular condition involving shared data Objects, not clients, are responsible for synchronization Cooperative method scheduling Vanderbilt University 162 Vanderbilt University 163 Advanced ACE Tutorial Douglas C. Schmidt Advanced ACE Tutorial Douglas C. Schmidt Condition Variable Usage Patterns ACE Condition Variable Interface class ACE_Condition_Thread_Mutex ACE_Condition_ // Initially unlocked. Note how the use of the Scoped The static ACE_Thread_Mutex lock; public: Thread_Mutex class is static ACE_Condition_Thread_Mutex Locking idiom simplifies the // Initialize the CV. cond (lock); solution since we can’t forget to ACE_Condition_Thread_Mutex a wrapper for the native (const ACE_Thread_Mutex &); OS condition variable // synchronized release the lock! // Implicitly destroy the CV. void acquire_resources (void) { // synchronized abstraction // Automatically acquire lock. void release_resources (void) { ˜ACE_Condition_Thread_Mutex (void); ACE_GUARD (ACE_Thread_Mutex, g, lock); // Automatically acquire lock. // Block on condition, or until ACE_GUARD (ACE_Thread_Mutex, g, lock); // time passes. If time == 0 block. e.g., cond_t on // Check condition in loop int wait (ACE_Time_Value *time = 0); SunOS 5.x, while (condition expression false) // Atomically modify shared // Sleep. // information... // Signal one waiting thread. pthread_cond_t cond.wait (); int signal (void); cond.signal (); // Signal *all* waiting threads. for POSIX, and a // Atomically modify shared // Could use cond.broadcast() here. int broadcast (void) const; custom // information. private: implementation on // guard automatically cond_t cond_; // Solaris CV. // Destructor releases lock. // releases lock. Windows and } } const ACE_Thread_Mutex &mutex_; }; VxWorks Vanderbilt University 164 Vanderbilt University 165 Do Advanced ACE Tutorial Douglas C. Schmidt Overview of ACE_Message_Queue and EE RR ACE_Message_Block UU TT CC _Block UU SYNCH RR TT Class cont() data_block() rd_ptr() wr_ptr() ACE_Message SS STRATEGY ACE_Data_Block An ACE_Message_Queue is a list of # base_ : char * # refcnt_ : int Message Message EE GG Block AA Queue ACE_Message_Blocks SS SS next() EE head_ prev() MM tail_ cont() EE TT – Efficiently handles arbitrarily-large II * 1 Data_Block SS OO ACE_Data_Block PP reference_count() = 2 MM message payloads OO CC Message )) cont() Block 22 wr_ptr() rd_ptr() (( next() An ACE_Message_Block is a _Block prev() data_block() Message cont() Composite ACE_Message Block Data_Block EE RR UU next() TT prev() CC – Similar to BSD mbufs or SVR4 UU cont() RR Message TT SS Block PAYLOAD Data_Block STREAMS m_blks EE GG next() AA SS prev() SS cont() EE MM ACE_Message_Block Design parameterizes ACE_Message_Block EE cont() Data_Block LL PP wr_ptr() rd_ptr() MM synchronization and allocation II _Block SS _Block data_block() )) ACE_Data 11 ACE_Message The aspects (( + init (size : size_t) : int + msg_type (type : ACE_Message_Type) + msg_type () : ACE_Message_Type + msg_priority (prio : u_long) + msg_priority () : u_long + clone () : ACE_Message_Block * + duplicate () : ACE_Message_Block * + release () : ACE_Message_Block * + set_flags (flags : u_long) : u_long + clr_flags (flags : u_long) : u_long + copy (buf : const char *,n : size_t) : int + rd_ptr (n : size_t) + rd_ptr () : char * + wr_ptr (n : size_t) + wr_ptr () : char * + length () : size_t + total_length () : size_t + size () : size_t # rd_ptr_ : size_t # wr_ptr_ : size_t # cont_ : ACE_Message_Block * # next_ : ACE_Message_Block * # prev_ : ACE_Message_Block * # data_block_ : ACE_Data_Block * Hide messaging implementations from clients Vanderbilt University 166 Advanced ACE Tutorial Class characteristics Vanderbilt University adritUniversity Vanderbilt Tutorial ACE Advanced Advanced ACE Tutorial Do o a for strategy synchronization thread-safe A: work? it does how Q: – – ACE_MT_SYNCH the use can state shared Any thread-safe ACE_Message_Queue ACE_Svc_Handler e.g. ACE_MT_SYNCH ACE_Message_Queue htis What The Class ACE_Svc_Handler SYNCH_STRATEGY tesrsta an that ensures it , ACE_Message_Queue ACE_Task # head_ : ACE_Message_Block * # tail_ : ACE_Message_Block * ACE_MT_SYNCH # high_water_mark_ : size_t einItrue Parameterizing Interlude: Design # low_water_mark_ : size_t + ACE_Message_Queue (high_water_mark : size_t = DEFAULT_HWM, ycrnzto Strategies Synchronization low_water_mark : size_t = DEFAULT_LWM, notify : ACE_Notification_Strategy * = 0) + open (high_water_mark : size_t = DEFAULT_HWM, htaccesses that traits low_water_mark : size_t = DEFAULT_LWM, rvdsa provides notify : ACE_Notification_Strategy * = 0) : int + flush () : int ’s + notification_strategy (s : ACE_Notification_Strategy *) : void + is_empty () : int + is_full () : int is + enqueue_tail (item : ACE_Message_Block *, timeout : ACE_Time_Value * = 0) : int and + 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 *&, }; tutAENL_YC { ACE_NULL_SYNCH struct }; tutAEM_YC { ACE_MT_SYNCH struct of use the Note timeout : ACE_Time_Value * = 0) : int + high_water_mark (new_hwm : size_t) : void typedef ACE_Null_Mutex typedef typedef ACE_Thread_Mutex typedef + high_water_mark (void) : size_t + low_water_mark (new_lwm : size_t) : void C_ulCniinCOND; ACE_Null_Condition MUTEX; COND; ACE_Condition_Thread_Mutex MUTEX; + low_water_mark (void) : size_t + close () : int + deactivate () : int + activate () : int + pulse () : int + state () : int traits Class characteristics oga .Schmidt C. Douglas : Note how the synchronization aspect can be strategized! 170 Vanderbilt University Advanced ACE Tutorial Do Advanced ACE Tutorial Do ACE_Message_Queue Class Private The ACE_Message_Queue Public Interface Interface private: template Vanderbilt University Vanderbilt University Do Advanced ACE Tutorial Douglas C. Schmidt Design Interlude: Tips for Intra-class Locking Q: How should locking be performed in an OO class? A: Apply the Thread-Safe Interface pattern: Class – “Interface functions should lock and do no work – implementation functions should do the work and not lock ” This pattern helps to avoid intra-class method deadlock – This is actually a variant on a common OO pattern that “public functions should check, private functions should trust” Naturally, there are exceptions to this rule... – This pattern avoids the following surprises Implementation Unnecessary overhead from recursive mutexes Deadlock if recursive mutexes aren’t used ACE_Message_Queue www.cs.wustl.edu/˜schmidt/POSA/ ... {} (size_t hwm,: size_t not_empty_cond_ lwm) (lock_), not_full_cond_ (lock_), ACE_GUARD_RETURN (SYNCH_STRAT::MUTEX,return g, is_empty_i lock_, (); -1); ACE_GUARD_RETURN (SYNCH_STRAT::MUTEX,return g, is_full_i lock_, (); -1); template Advanced ACE Tutorial Douglas C. Schmidt Advanced ACE Tutorial Douglas C. Schmidt ACE_Message_Queue Operations Overcoming Algorithmic Decomposition Limitations template // Actually enqueue the message at // Actually dequeue the first message. Next, we describe strategic patterns, frameworks, and components // the end of the list. dequeue_head_i (item); enqueue_tail_i (item); to: // Tell blocked threads that list // Tell blocked threads that // is no longer full. – Increase reuse and extensibility e.g. , // list has a new item! if (cur_bytes_ <= low_water_mark_) Decoupling service, IPC, and demultiplexing not_empty_cond_.signal (); not_full_cond_.signal (); } } – Improve the flexibility of concurrency control Vanderbilt University 174 Vanderbilt University 175 Advanced ACE Tutorial Douglas C. Schmidt Advanced ACE Tutorial Douglas C. Schmidt Selecting the Server’s Concurrency Architecture componentsConcurrency Patterns in the Web Server Problem The following example illustrates the patterns and framework in an OO implementation of a concurrent Web Server – A very strategic design decision for high-performance Web servers is selecting an efficient concurrency architecture There are various architectural patterns for structuring concurrency in a Web Server Forces – Reactive – No single concurrency architecture is optimal – Thread-per-request – Key factors include OS/hardware platform and workload – Thread-per-connection Solution – Synchronous Thread Pool Leader/Followers Thread Pool – Understand key alternative concurrency patterns Half-Sync/Half-Async Thread Pool – Asynchronous Thread Pool Vanderbilt University 176 Vanderbilt University 177 Do Do SERVER SERVER HTTP HTTP Acceptor Acceptor CLIENT CLIENT CONNECT CONNECT 1: Reactor 1: Reactor HANDLE INPUT HANDLE HANDLER CREATE CONNECTION ACCEPT THREAD SPAWN HANDLE INPUT HANDLE HANDLER CREATE CONNECTION ACCEPT HANDLER ACTIVATE 2: 3: 4: 5: 2: 3: 4: 5: HTTP CLIENT Handler CLIENT Reactive Web Server HTTP Handler HTTP Handler HTTP Thread-per-Request Web Server Handler HTTP Handler PROCESS HTTP REQUEST CLIENT PROCESS HTTP REQUEST CLIENT 6: 6: Advanced ACE Tutorial Vanderbilt University Advanced ACE Tutorial Vanderbilt University Advanced ACE Tutorial Do Advanced ACE Tutorial Do Half-Sync/Half-Async Synchronous Thread-per-Connection Web Server Thread Pool Web Server 3: SPAWN THREAD 2: CREATE, ACCEPT, 2: HANDLE INPUT PER CONNECTION AND ACTIVATE Message 3: ENQUEUE REQUEST HTTP_HANDLER Queue Active HTTP HTTP HTTP Handler HTTP Object Handler HTTP Handler Handler HTTP Acceptor 4: DEQUEUE & HTTP Handler Active PROCESS Reactor REQUEST Handler Object HTTP Acceptor Active Active Object 4: PROCESS HTTP REQUEST Object Reactor 1: HTTP REQUEST SERVER CLIENT 5: PROCESS HTTP REQUEST 1: HTTP REQUEST CLIENT CLIENT SERVER CLIENT CLIENT CLIENT Vanderbilt University Vanderbilt University Advanced ACE Tutorial Do Advanced ACE Tutorial Do Asynchronous Thread Pool Web Server Leader/Followers Synchronous Thread Pool Web Server 1: INITIATE ASYNC ACCEPT I/O 2: RUN EVENT LOOP HTTP Completion 4: ACCEPT COMPLETES Port 5: QUEUE COMPLETION Handler HTTP Event Dispatcher Handler 6: DEQUEUE COMPLETION Async Async HTTP & PROCESS Read REQUEST Async Accept Handler Read 2: ACCEPT CONNECTION Async HTTP 3: MORPH INTO HANDLER Accept Handler HTTP HTTP HTTP Handler Handler Acceptor Proactor HTTP HTTP Handler Acceptor 7: PROCESS HTTP REQUEST 3: HTTP 4: PROCESS HTTP REQUEST REQUEST SERVER 1: HTTP REQUEST SERVER CLIENT CLIENT CLIENT CLIENT CLIENT CLIENT Vanderbilt University Vanderbilt University adritUniversity Vanderbilt Tutorial ACE Advanced Advanced ACE Tutorial Do tas otispten ihtefloigintents: following the with patterns contains also It logger distributed as patterns same uses Client/Server Web The – – – – Half-Sync/Half-Async Optimization Locking Double-Checked Connector fotwtotdgaigeeuinefficiency” programming execution concurrent degrading simplify without to effort system a in I/O asynchronous i.e. efre netepe evc scnetdadinitialized” and connected is processing service the peer from the system once distributed performed a in service peer a Acceptor usqetlcigoverhead” eliminates locking and subsequent order, initialization of regardless initialization, Web Server Software Architecture eco,CmoetCngrtr cieOjc,and Object, Active Configurator, Component Reactor, , atrsi h e letSre (cont’d) Client/Server Web the in Patterns HTTP HTTP Handler Handler ! Sock Sock Stream Dcul h ciecneto n ntaiainof initialization and connection active the “Decouple HTTP Stream Handler HTTP Acceptor Sock Stream Event Sock ! Dispatcher Acceptor DculssnhoosIOfrom I/O synchronous “Decouples Event Dispatcher – Encapsulates Web server concurrency and ! dispatching strategies Alw atomic “Allows HTTP Handlers – Parses HTTP headers and processes requests oga .Schmidt C. Douglas HTTP Acceptor – Accepts connections and creates HTTP Handlers 186 Vanderbilt University Advanced ACE Tutorial Do Advanced ACE Tutorial Do Architecture of Our Web Server Patterns in the Web Server Implementation REQUEST PROCESSING LAYER Thread-per Thread Pool Acceptor svc_run Request svc_run svc_run svc_run Active Connector Thread-per Object Connection Component QUEUEING Msg Configurator HTTP Queue Options Half-Sync/ LAYER Processor s Half-Async s Asynchronous Completion Double HTTP HTTP HTTP Reactor/ Handler Handler Handler Token Proactor Checked Locking STRATEGIC PATTERNS HTTP TACTICAL PATTERNS I/O DEMUXING Reactor Acceptor LAYER Wrapper Strategy Abstract Adapter Singleton Facade Factory www.cs.wustl.edu/˜schmidt/PDF/HPL.pdf Vanderbilt University Vanderbilt University }; adritUniversity Vanderbilt protected: dacdAETutorial ACE Advanced Advanced ACE Tutorial Do n evrqet(C_esg_lc *&); (ACE_Message_Block recv_request int (ACE_HANDLE); handle_input int virtual } { timeout. handle_timeout clients int when virtual this method dispatches // Reactor // /rqet eg,GET). (e.g., HTTP requests client // Receive/frame arrive. // requests method HTTP this when dispatches // Reactor // /Rmv rmteReactor. the ()->remove_handler from reactor *) Remove void // const &, ACE_Time_Value (const An Integrated Reactive/Active (this, ACE_Event_Handler::READ_MASK); Web Server svc_run REGISTERED svc_run HTTP_Handler svc_run OBJECTS 4: getq(msg) 5:svc(msg) HTTP Handler HTTP Handler HTTP Event Handler HTTP LEVEL Handler Event Processor HTTP Handler Event APPLICATION Acceptor Handler 2: recv_request(msg) rtce Interface Protected 3: putq(msg) Event Handler 1: handle_input() : Handle LEVEL Table FRAMEWORK from callbacks by invoked are methods These Handler Handler : Reactor HTTP Event OS EVENT DEMULTIPLEXING INTERFACE ACE_Reactor : Timer Queue 2: remove_handler(this) 1: handle_timeout() 1: oga .Schmidt C. Douglas LEVEL KERNEL REGISTERED Reactor OBJECTS :Reactor We’re focusing on the Reactive layer here 190 Vanderbilt University public: ls TPHnlr:public : HTTP_Handler ACCEPTOR> class ti,0 C_ieVle(CLIENT_TIMEOUT)); ACE_Time_Value 0, (this, ACE_Event_Handler::READ_MASK); (this, cieObject Active HTTP_Handler nertn Multi-threading Integrating C_ULSNH { ACE_NULL_SYNCH> atr oalwmlil ocretserver concurrent multiple allow to pattern ulcInterface Public or Netscape like browsers Web (e.g., clients with communicating for Proxy the The pattern Sync/Half-Async Half- of portion asynchronous the implements It i.e. HTTP_Handler ,) oga .Schmidt C. Douglas oga .Schmidt C. Douglas 189 191 is Advanced ACE Tutorial Do Advanced ACE Tutorial Do Using the Singleton Pattern Using the Active Object Pattern and ACE Task Framework in the Web Server // Singleton access point. svc_run REGISTERED svc_run OBJECTS svc_run HTTP_Processor * 4: getq(msg) HTTP_Processor::instance (void) 5:svc(msg) { HTTP // Beware of race conditions! Handler HTTP if (instance_ == 0) Handler HTTP // Create the Singleton "on-demand." Event Handler HTTP LEVEL Handler instance_ = new HTTP_Processor; Event Processor HTTP Handler Event APPLICATION Acceptor Handler 2: recv_request(msg) return instance_; 3: putq(msg) Event } Handler 1: handle_input() // Constructor creates the thread pool. HTTP_Processor::HTTP_Processor (void) : Handle LEVEL Table { // Inherited from class Task. FRAMEWORK : Reactor activate (THR_BOUND, Options::instance ()->threads ()); OS EVENT DEMULTIPLEXING INTERFACE } LEVEL KERNEL We’re focusing on the Active Object layer here Vanderbilt University Vanderbilt University rvt:HT_rcso (void); public: HTTP_Processor private: HTTP_Processor class Tutorial ACE Advanced adritUniversity Vanderbilt Tutorial ACE Advanced University Vanderbilt uteCnurnyWe ihteSnltnPattern Singleton the with Woes Concurrency Subtle ulcAETs and obeCekdLocking Double-Checked The nueaoi initialization atomic ensure C_ieVle*); ACE_Time_Value HTTP_Processor piiainptent minimize to pattern optimization Class pattern Sync/Half-Async Half- the of portion task synchronous the implements method This model concurrency “Thread-Pool” the using requests HTTP Processes oga .Schmidt C. Douglas oga .Schmidt C. Douglas 193 195 Advanced ACE Tutorial Douglas C. Schmidt Advanced ACE Tutorial Douglas C. Schmidt The Double-Checked Locking Optimization Pattern The ACE Singleton Template if (instance_ == NULL) { Intent template Ensures atomic object // Memory barrier could go here. Ensures automatic static instance() initialization ACE_Object_Manager::at_exit (s_); static instance_ } cleanup when Mutex return s_->instance_; process exits Minimizes locking overhead } virtual void cleanup (void *param = 0); www.cs.wustl.edu/ www.cs.wustl.edu/ Caveat! protected: ACE_Singleton (void); ˜schmidt/PDF/ ˜schmidt/POSA/ TYPE instance_; This pattern assumes atomic static ACE_Singleton Vanderbilt University 196 Vanderbilt University 197 Advanced ACE Tutorial Douglas C. Schmidt Advanced ACE Tutorial Douglas C. Schmidt Integrating Reactive and Multi-threaded Layers The Half-Sync/Half-Async Pattern SYNC SYNC Intent TASK Problem 1 TASK 3 Decouples synchronous I/O – Justifying the hybrid design of our Web server can be tricky SYNC TASK 2 from asynchronous I/O in a TASK LAYER SYNCHRONOUS Forces system to simplify concurrent programming effort without – Engineers are never satisfied with the status quo ;-) 1, 4: read(data) degrading execution efficiency – Substantial amount of time is spent re-discovering the intent of LAYER MESSAGE QUEUES complex concurrent software design QUEUEING Forces Resolved: 3: enqueue(data) Simplify programming Solution ASYNC TASK 2: interrupt – Use the Half-Sync/Half-Async pattern to explain and justify our Ensure efficient I/O Web server concurrency architecture EXTERNAL EVENT SOURCES www.cs.wustl.edu/ TASK LAYER ASYNCHRONOUS ˜schmidt/POSA/ Vanderbilt University 198 Vanderbilt University 199 adritUniversity Vanderbilt Tutorial ACE Advanced Advanced ACE Tutorial Do Solution Forces Problem – – – – snhoosO platforms OS Asynchronous oddsgssol eaatbet e contexts new to adaptable be should designs Good s the Use platforms OS some on powerful quite is I/O asynchronous Purely most the always efficient not are solutions multi-threaded Synchronous Using the Half-Sync/Half-Async e.g. Pattern in the Web Server idw T4xo NXwith UNIX or 4.x NT Windows , snhoosOeaigSystems Operating Asynchronous Proactor svc_run piiigOrWbSre for Server Web Our Optimizing svc_run svc_run 4: getq(msg) LEVEL 5:svc(msg) atr omxmz efrac on performance maximize to pattern SYNC TASK SYNC HTTP LEVEL Processor QUEUEING HTTP Handler HTTP aio_()* HTTP Handler HTTP Acceptor Event Handler Handler Event Event Handler Event Handler calls Handler 1: handle_input() oga .Schmidt C. Douglas 2: recv_request(msg) : Handle 3: putq(msg) Table LEVEL : Reactor ASYNC TASK 202 Vanderbilt University adritUniversity Vanderbilt Reactor as forces same Resolves Intent dacdAETutorial ACE Advanced Advanced ACE Tutorial Do ipthsservice dispatches rgee ythe by triggered asynchronous eutpee and Demultiplexes eussta are that requests opeinof completion operations Joining Async and Sync Tasks in the Web Server // The following methods form the boundary // between the Async and Sync layers. template h ratrPattern Proactor The HTTP_Handler 1 { www.cs.wustl.edu/˜schmidt/POSA/ ACE_Message_Block *mb = 0; overlapped_result->complete() GetQueuedCompleteStatus(); overlapped_result = handle_events() Proactor // Try to receive and frame message. if (recv_request (mb) == HTTP_REQUEST_COMPLETE) { APPLICATION INDEPENDENT reactor ()->remove_handler get_handle() handle_timeout() handle_write_file() handle_read_file() handle_accept() Completion (this, ACE_Event_Handler::READ_MASK); Handler - reactor ()->cancel_timer (this); // Insert message into the Queue. Handles APPLICATION A HTTP_Processor - } Async cancel() open() 1 Op Handler Timer_Queue cancel_timer(h) schedule_timer(h) HTTP int HTTP_Processor::put (ACE_Message_Block *msg, ACE_Time_Value *timeout) oga .Schmidt C. Douglas { // Insert the message on the Message_Queue Async Write Acceptor Accept // (inherited from class Task). Async HTTP putq (msg, timeout); } 203 Vanderbilt University adritUniversity Vanderbilt Tutorial ACE Advanced Advanced ACE Tutorial Do Solution Forces Problem – – – – substantially s the Use Separating error-prone, non-portable tedious, and are APIs establishment connection Low-level The evc ntaiainfo u-ieprotocol run-time from initialization service evri fe rhgnlt the to orthogonal often is server Structure of the ACE Proactor Framework omncto protocol communication ACE_Timer_Queue ACE_Service_Handler Acceptor tutrn evc Initialization Service Structuring initialization ACE_Proactor ACE_Asynch_Acceptor ACE_Asynch_Connector and ACE_Handler Connector from ACE_Asynch_Read_Stream ACE_Asynch_Write_Stream use Web the and clients between used ntaiainprotocol initialization a nraesfwr reuse software increase can atrst eopepassive decouple to patterns ACE_Asynch_Result Framework characteristics Similar to the ACE Reactor framework, except oga .Schmidt C. Douglas behavior is “inverse” Portable to Windows and various UNIX platforms that support aio_*() family of methods 206 Vanderbilt University Advanced ACE Tutorial Do Advanced ACE Tutorial Do Using the ACE_Acceptor Using the ACE Proactor Framework for in the Web Server the Web Server Connection Setup Phase : HTTP : HTTP 1: accept Web Server Handler Handler : HTTP : HTTP connections Handler 7: create HTTP Acceptor Acceptor : Svc : Svc Handler Handler Handler : Svc 4: connect : Acceptor Handler 6: 2: accept 8: read (Handler, Web accept (Acceptor, Dispatcher) : HTTP Browser complete Dispatcher) PASSIVE ACTIVE Handler Completion Operating LISTENER CONNECTIONS Dispatcher System 1: handle_input() : Svc 3: handle 5: accept 2: sh = make_svc_handler() Handler events complete 3: accept_svc_handler(sh) : Reactor 4: activate_svc_handler(sh) Data Transfer Phase 1: GET /etc/passwd Web Server Web HTTP 4: parse request The HTTP_Acceptor is a factory that creates, Browser Handler connects, and activates an HTTP_Handler 6: write (File, Conn., 8: write Handler, Dispatcher) 5: read (File) 3: read complete complete 7: write complete File Completion Operating System Dispatcher System 2: read complete Vanderbilt University Vanderbilt University Do Advanced ACE Tutorial Douglas C. Schmidt HTTP_Acceptor Class Interface template i.e.,itaccepts ACCEPTOR> { connections/initializes public: HTTP_Handlers // Called when Advanced ACE Tutorial Douglas C. Schmidt Advanced ACE Tutorial Douglas C. Schmidt Using the ACE Service Configurator Component Configurator Implementation in C++ Framework in the Web Server Reactive The concurrent Web Server is Factory function that dynamically SERVICE Web configured and initialized via a allocates a Half-Sync/Half-Async CONFIGURATOR Server TP Web configuration script Web Server object RUNTIME Server Service Object % cat ./svc.conf extern "C" ACE_Service_Object * dynamic Web_Server make_Web_Server (void); Service Service DLLS Repository Object Service_Object * TPR web_server:_make_Web_Server() Web ACE_Service_Object * Server "-p 80 -t $THREADS" make_Web_Server (void) Service # .dll or .so suffix added to Service { Config Reactor # "web_server" automatically return new Object HTTP_Acceptor Vanderbilt University 210 Vanderbilt University 211 Advanced ACE Tutorial Douglas C. Schmidt Advanced ACE Tutorial Douglas C. Schmidt Main Program for the Web Server Optimizing the JAWS Framework Reactor/ProactorState Singleton Use lightweight Strategy int main (int argc, char *argv[]) The main() I/O Strategy Cached Virtual concurrency { function is totally Framework Filesystem Minimize locking // Initialize the daemon and generic! Apply file caching // dynamically configure services. Asynchronous Completion Token Tilde ~ and memory ACE_Service_Config::open (argc, Dynamically Expander /home/... mapping argv); Protocol Acceptor configure & execute Handler Event Dispatcher // Loop forever, running services Use “gather-write” Web Server Protocol mechanisms // and handling reconfigurations. Filter Strategy Minimize logging ACE_Reactor::instance ()-> Make any run_reactor_event_loop (); application Adapter Pre-compute HTTP responses /* NOTREACHED */ “Web-enabled” } Concurrency Avoid excessive Protocol Pipeline Strategy Framework Framework Active Object time() calls Streams Service Configurator Optimize the www.cs.wustl.edu/˜jxh/research/ transport interface Vanderbilt University 212 Vanderbilt University 213 Do Advanced ACE Tutorial Douglas C. Schmidt Application-level Telecom Gateway Example OUTGOING TRACKING MESSAGES SATELLITES This example explores the Handler STATION Consumer PEERS patternsframeworkand reusable components Handler for an application-level Supplier Gateway STATUS INFO REQUEST Acceptor CONNECTION WIDE AREA NETWORK The Gateway routes COMMANDS BULK DATA messages between Peers TRANSFER Table Reactor Routing Gateway and Peers are GATEWAY GATEWAY connected via TCP/IP TAPOS-00.pdf of the Gateway LOCAL AREA NETWORK Connector GROUND REQUEST CONNECTION STATION OO Software Architecture PEERS www.cs.wustl.edu/˜schmidt/PDF/ Handler Consumer Handler Supplier INCOMING MESSAGES Advanced ACE Tutorial Vanderbilt University Vanderbilt University 214 All components in this architecturepatterns are from based ACE on Do Advanced ACE Tutorial Douglas C. Schmidt Gateway Behavior Facade Wrapper Components in the Gateway behave as follows: Component Gateway Configurator 1. parses configuration files that specify which Peers to Proxy connect with and which routes to use Buffered I/O Buffered 2. Proxy_Handler_Connector connects to Peers, then creates Non-blocking and activates Proxy_Handler subclasses Method Factory (Supplier_Handler or Consumer_Handler) Reactor 3. Once connected, Peers send messages to the Gateway – Messages are handled by an Supplier_Handler Method Te m p l a te – Supplier_Handlers work as follows: Acceptor- Connector Receive and validate messages Consult a Routing_Table Iterator Patterns in the Gateway Forward messages to the appropriate Peer(s) via pattern language Consumer_Handlers Active Object Active Half-Sync/ Half-Async TACTICAL PATTERNS PATTERNS STRATEGIC The Gateway components are basedcommon upon a Vanderbilt University Vanderbilt University 216 Advanced ACE Tutorial Do Advanced ACE Tutorial Douglas C. Schmidt OO Gateway Architecture Stream Service Configurator Application-specific components SOCK_Stream Null_Synch PEER_STREAM SYNCH Proxy_Handler Handler – s route messages among Peers Svc Handler n Connection-oriented application components Supplier/Consumer Reactor Connection – ACE_Svc_Handler Performs I/O-related tasks with connected clients – ACE_Connector factory Establishes new connections with clients PEER STREAM Gateway < Application-independent ACE framework components PEER Connector Proxy Handler CONNECTOR Connector 1 – Perform IPC, explicit dynamic linking, event demultiplexing, event handler dispatching, multi-threading, etc. COMPONENTS COMPONENTS COMPONENTS SPECIFIC FRAMEWORK ORIENTED Class Diagram for Single-Threaded - APPLICATION ACE - CONNECTION Advanced ACE Tutorial Vanderbilt University Vanderbilt University 219 Advanced ACE Tutorial Do Advanced ACE Tutorial Do The Acceptor-Connector Pattern Using the ACE Reactor (Connector Role) Framework for the Gateway CONCRETE EVENT Svc Svc Handler Consumer HANDLERS Handler Connector Consumer Handler Handler 4: send(msg) Supplier LEVEL Handler peer_stream_ ACTIVATES connect(sh, addr) Event 2: recv(msg) open() Event complete() APPLICATION Handler 3: route(msg) Handler Event Handler APPLICATION- HANDLE ASYNC DEFINED CONNECTION COMPLETION 1: handle_input() APPLICATION- Reactor Timer Handle INDEPENDENT Table LEVEL Queue : Reactor www.cs.wustl.edu/˜schmidt/POSA/ FRAMEWORK Intent of Connector Role Forces Resolved: OS EVENT DEMULTIPLEXING INTERFACE Decouple the active Reuse connection LEVEL connection and code KERNEL initialization of a peer Efficiently setup service in a distributed Benefits Liabilities connections with system from the many peers or over Straightforward to Design is “brittle” processing performed long delay paths program once the peer service is Can’t leverage connected and initialized Concurrency control multi-processors is trivial Vanderbilt University Vanderbilt University dacdAETutorial ACE Advanced adritUniversity Vanderbilt Tutorial ACE Advanced University Vanderbilt ACE_Event_Handler tutr fteAcpo-onco atr nACE in Pattern Acceptor-Connector the of Structure Solution Forces Problem – – – – – ACE_Acceptor ntaiainpooosfo h aea otn protocol routing Gateway the from protocols initialization establishment connection s the Use non-portable and Separating error-prone are APIs connection Low-level Application snhooscnetosaeipratoe ogdlypaths long-delay over important are connections Asynchronous PEER_ACCEPTOR SVC_HANDLER, drsigAtv npitConnection Endpoint Active Addressing Acceptor-Connector ACE_Connector initialization communication n ntaiainChallenges Initialization and PEER_CONNECTOR SVC_HANDLER, ACE_Svc_Handler Application «bind» Service ACE_Task from SYNCH_STRATEGY SYNCH_STRATEGY PEER_STREAM, and rtcl r fe rhgnlt their to orthogonal often are protocols processing atr odcul oncinand connection decouple to pattern evc initialization service ACE_Connector the of features Additional service ye to types parameterized C++ Uses ocrec policies concurrency and establishment, connection creation, strategize to pattern Method Template Uses nrae otaereuse software increases aspects strategize protocols oga .Schmidt C. Douglas oga .Schmidt C. Douglas IPC and 221 223 Advanced ACE Tutorial Do Advanced ACE Tutorial Do Design Interlude: Motivation for the Using the ACE_Connector ACE_Synch_Options Class in the Gateway Svc Svc Svc Q: What is the ACE_Synch_Options class? Svc HandlerHandler Handler Handler Svc A: This allows callers to define the synchrony/asynchrony policies, e.g., Handler class ACE_Synch_Options { ACTIVE // Options flags for controlling Hash_Map CONNECTIONS // synchronization. Svc enum { USE_REACTOR = 1, USE_TIMEOUT = 2 }; Connector Handler PENDING ACE_Synch_Options Reactor (u_long options = 0, CONNECTIONS const ACE_Time_Value &timeout = ACE_Time_Value::zero, const void *act = 0); The ACE_Connector is a factory // This is the default synchronous setting. static ACE_Synch_Options synch; – i.e.,itconnects and activates an // This is the default asynchronous setting. ACE_Svc_Handler static ACE_Synch_Options asynch; }; There’s typically 1 ACE_Connector per-service Vanderbilt University Vanderbilt University Advanced ACE Tutorial Do Advanced ACE Tutorial Do ACE_Synch_Options and ACE_Connector Class Public Interface ACE_Connector Semantics A reusable template factory class that establishes connections with clients Reactor Timeout Behavior template Ye s 0,0 Return 1 with errno class PEER_CONNECTOR> EWOULDBLOCK; service handler // Connection factory is closed via reactor event loop. class ACE_Connector : public ACE_Service_Object Ye s time Return 1 with errno { EWOULDBLOCK; wait up to specified public: amount of time for completion using // Initiate connection to Peer. the reactor. virtual int connect Ye s NULL Return 1 with errno (SVC_HANDLER *&svc_handler, EWOULDBLOCK; wait for completion typename const PEER_CONNECTOR::PEER_ADDR &ra, indefinitely using the reactor. ACE_Synch_Options &synch_options); No 0,0 Close service handler directly; return