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 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  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 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 “” 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 ( ) 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 bytes to // logging daemon processing. // obtain the actual record. for (size_t nread = 0; nread < len; nread += n for (;;) { n = recv (in_h, ((char *) &lr) + nread, // ... get logging records from client len - nread, 0); // application processes ... // Decode and print record. decode_log_record (&lr); size_t size = htonl (lr.size); if (write (out_h, lr.buf, lr.size) == -1) send (stream, &size, sizeof size); return -1; encode_log_record (&lr); else return 0; send (stream, ((char *) &lr), sizeof lr); } } }

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

 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

<> – Low-level APIs are verbose, tedious, and error-prone to program PEER

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 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 // . 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 int echo_server (u_short port) // ... Same as before ... { // Local server address (note traits). // Acceptor-mode socket handle. typename static ACE_SOCK_Acceptor acceptor; ACCEPTOR::PEER_ADDR my_addr (port); // Set of currently active handles static ACE_Handle_Set activity_handles; // Initialize the acceptor mode server. ACCEPTOR acceptor (my_addr); // Scratch copy of activity_handles static ACE_Handle_Set ready_handles; // Data transfer object (note traits). typename ACCEPTOR::PEER_STREAM stream; static void initialize_acceptor (u_short port) { // Accept a new connection. // Set up address info. to become server. acceptor.accept (stream); ACE_INET_Addr saddr (port); for (;;) { // Create a local endpoint of communication. acceptor.open (saddr); char buf[BUFSIZ]; ssize_t n = // Set the into non-blocking mode. stream.recv (buf, sizeof buf); acceptor.enable (ACE_NONBLOCK); stream.send_n (buf, n); } activity_handles.set_bit (acceptor.get_handle ()); } }

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 bytes to ready_handles); // obtain the actual record. s.recv_n ((char *) &lr, sizeof lr); // First receive pending logging records. handle_data (); // Decode and print record. decode_log_record (&lr); // Then accept pending connections. if (ACE_OS::write (out_h, lr.buf, lr.size) == -1) handle_connections (); return -1; } else return 0; } }

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 . acceptor.recv (buf, sizeof buf); if (ready_handles.is_set (acceptor.get_handle ()) ACE::select (acceptor.get_handle () + 1, ready_handles);

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 (port); ssize_t recv (void *buf, size_t n) NETWORK } { INTERFACE return ACE_OS::recv (this->get_handle (), buf, n); } Switching wholesale between sockets and TLI simply requires }; instantiating a different ACE C++ wrapper facade

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   Liabilities Table : Handle 5: handle_input() 6: recv(msg) 7:process(msg) OBJECTS ACE_Reactor REGISTERED ACE_Reactor_Impl OS EVENT DEMULTIPLEXING INTERFACEOS EVENT DEMULTIPLEXING 1 : Event Handler Handler : Logging :Timer Queue in the Logging Server : Event Handler Handler : Logging ACE_TP_Reactor

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 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 // IPC aspect class ACE_Acceptor : public ACE_Service_Object { h epaeMto Pattern Method Template The // Inherits indirectly from public: // Initialization. ... primitive_operation2() ... primitive_operation1() ... virtual int open (typename const PEER_ACCEPTOR::PEER_ADDR &, ACE_Reactor * = ACE_Reactor::instance ()); // Template Method. virtual int handle_input (ACE_HANDLE);

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 int ACE_Acceptor::handle_input (ACE_HANDLE) { // Factory method that makes a service handler.

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 Using the Strategy Pattern in Intent the ACE Acceptor Implementation

STRATEGY Benefits Context Strategy  Define a family of Acceptor Concurrency <> context_interface() algorithm_interface() algorithms, encapsulate handle_input() Strategy  More 2: activate_svc_handler(sh) activate_svc_handler() each one, and make extensible due them interchangeable to “blackbox” sh = create_svc_handler () Patterns: Elements of ... design Gamma et al., Design accept_svc_handler (sh) Concrete Concrete ... Reusable Object-Oriented Reactive Thread Process Strategy A Strategy C 1: activate_svc_handler(sh) Liabilities Software ... Strategy Strategy Strategy algorithm_interface() algorithm_interface() AW, ’94  More complex Concrete and harder to Strategy B develop initially algorithm_interface()

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 ::make_svc_handler class a (ACE_HANDLE) PA> service SH handler. } * // Accepttemplate connections ::accept_svc_handler class{ (SH PA> *sh) int } // Activatetemplate the ::activate_svc_handler class{ (SH PA> *sh) int Vanderbilt University Advanced ACE Tutorial Note how the // Initialization. template ::open class PA> int Vanderbilt University } { } Advanced ACE Tutorial Do Advanced ACE Tutorial Do Object Diagram for OO Logging Server ACE_Svc_Handler Class Public Interface

SERVER LOGGING Service Note how IPC and synchronization aspects are DAEMON Config strategized

Logging Service template // Synch aspect Logging class ACE_Svc_Handler Service Handler Manager : public ACE_Task Logging // Task is-a Service_Object, Handler Reactor // which is-an Event_Handler { public: // Constructor. ACE_Svc_Handler (Reactor * = LOGGING ACE_Reactor::instance ()); SERVER REMOTE RECORDS CONNECTION // Activate the handler (called by the REQUEST CONTROL OPERATIONS . // or ). virtual int open (void *);

// 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 SS>::open class ACE_Svc_Handler class SS>::ACE_Svc_Handler PS, ACE_Svc_Handlerregister_handler handler reactor Register // (ACE_NONBLOCK); I/O. ().enable non-blocking peer Enable { // *) (void (r) ACE_Service_Object {} *r): (ACE_Reactor

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 { public: // Recv and process remote logging records. virtual int handle_input (ACE_HANDLE); }; Implementation // Logging_Handler factory. class Logging_Acceptor : public ACE_Acceptor  { ACE_Reactor singleton the with registered is object ACE_Svc_Handler a default, By – public: necessary are mechanisms synchronization other no that so “reactive” service the makes This // Dynamic linking hooks. virtual int init (int argc, char *argv[]); virtual int fini (void); Schmidt C. Douglas }; 93 Vanderbilt University Advanced ACE Tutorial Douglas C. Schmidt Advanced ACE Tutorial Douglas C. Schmidt Design Interlude: Parameterizing IPC Mechanisms Logging_Handler Input Method

 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 if (n > 0) { /* ... /* }; // Count the # of logging records ++request_count; class Logging_Acceptor : public return n <=0?-1:0; ACE_Acceptor } { /* ... */ };

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, . ACE_Reactor::instance ()); Advanced ACE Tutorial // Automatically// called object when is a linked Logging_Acceptor Logging_Acceptor::init dynamically. (int{ argc, char *argv[]) Vanderbilt University } // Automatically called whenLogging_Acceptor::fini object (void) is { unlinked. handle_close (); } Vanderbilt University 99 Do

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 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 Many of the following methods are used by put() and svc() // Synchronization aspect class ACE_Task : public ACE_Service_Object { // Accessors to internal queue. public: ACE_Message_Queue *msg_queue (void); // Initialization/termination hooks. void msg_queue (ACE_Message_Queue *); virtual int open (void *args = 0) = 0; virtual int close (u_long = 0) = 0; // Accessors to thread manager. ACE_Thread_Manager *thr_mgr (void); // Transfer msg to queue for immediate processing. void thr_mgr (ACE_Thread_Manager *); virtual int put (ACE_Message_Block *, ACE_Time_Value * = 0) = 0; // Insert message into the message list. // Run by a daemon thread for deferred processing. int putq (ACE_Message_Block *, ACE_Time_Value *tv = 0); virtual int svc (void) = 0; // Extract the first message from the list (blocking). // Turn task into active object. int getq (ACE_Message_Block *&mb, ACE_Time_Value *tv = 0); int activate (long flags, int threads = 1); // Hook into the underlying thread library. static void *svc_run (ACE_Task *);

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 void *

 The ACE Task framework encapsulates the svc_run() function ACE_Task::svc_run (ACE_Task *t) within the ACE_Task::activate() method: { // Thread added to thr_mgr() automatically on entry. template int ACE_Task::activate (long flags, int n_threads) { if (thr_mgr () == NULL) thr_mgr (ACE_Thread_Manager::instance ()); // Run service handler and record return value. thr_mgr ()->spawn_n (n_threads, &ACE_Task::svc_run, void *status = (void *) t->svc (); (void *) this, flags); } t->close (u_long (status)); 1. ACE_Task::activate () 4. template void * 2. ACE_Thread_Manager::spawn ACE_Task::svc_run (svc_run, this); (ACE_Task *t) { // Status becomes "return" value of thread... 3. _beginthreadex // ... (0, 0, void *status = t->svc (); return status; svc_run, this, // ... 0, &thread_id); RUN-TIME return status; // Thread return. THREAD STAC K } // Thread removed from thr_mgr() automatically on return. }

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 <> IPC_SAP Concurrency global SVC_HANDLER PEER_ACCEPTOR ACE_SOCK_Acceptor> Thr_Logging_Handler SOCK_Acceptor OO Logging Server Thr Acceptor PEER Logging Acceptor ACCEPTOR 1

Thr_Logging_Acceptor

Class Diagram for Concurrent

COMPONENTS COMPONENTS COMPONENTS

// Override// definition class in// to is spawn called a by new the thread! . // This Process method remote logging records.

SPECIFIC ORIENTED FRAMEWORK Thr_Logging_Handler

virtual int open (void *); virtual int svc (void); ACE_Acceptor... : public// Logging_Handler Inherits - APPLICATION - CONNECTION ACE }; class Thr_Logging_Acceptor : public { }; Advanced ACE Tutorial Vanderbilt University Advanced ACE Tutorial Template classes that create, connect,a and new activate thread to handle each client class Thr_Logging_Handler { public: Vanderbilt University adritUniversity Vanderbilt dacdAETutorial ACE Advanced    Advanced ACE Tutorial Do h olwn ldscmaeadcnrs eiso techniques of problem series this a address contrast that and compare slides following The memory shared many on platforms... errors multi-processor to leads serialization of Lack problems several has Server Logging concurrent The – – – o serialized not oeta hspolmi niaieo ag ls ferr in errors of class large a of programs... indicative concurrent is problem this that Note variable global of auto-increment The the in Output Thr_Logging_Handler

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 class ACE_Guard – These macros test for deadlock and detect when operations on { the underlying locks fail public: ACE_Guard (LOCK &m): lock_ (m) { lock_.acquire (); } #define ACE_GUARD(MUTEX,OB,LOCK) \ ACE_Guard OB (LOCK); if (OB.locked () == 0) return; ˜ACE_Guard (void) { lock_.release (); } #define ACE_GUARD_RETURN(MUTEX,OB,LOCK,RET) \ // ... other methods omitted ... ACE_Guard OB (LOCK); if (OB.locked () == 0) return RET; acquires a resource #define ACE_WRITE_GUARD(MUTEX,OB,LOCK) \ private: ACE_Write_Guard OB (LOCK); if (OB.locked () == 0) return; LOCK &lock_; #define ACE_WRITE_GUARD_RETURN(MUTEX,OB,LOCK,RET) \ } ACE_Write_Guard OB (LOCK); if (OB.locked () == 0) return RET; #define ACE_READ_GUARD(MUTEX,OB,LOCK) \

 ACE_Guard uses the Scoped Locking idiom whereby a constructor ACE_Read_Guard OB (LOCK); if (OB.locked () == 0) return; and the destructor releases the resource #define ACE_READ_GUARD_RETURN(MUTEX,OB,LOCK,RET) \ ACE_Read_Guard OB (LOCK); if (OB.locked () == 0) return RET;

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 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. &lr, bytes// sizeof to Decode lr); decode_log_record and (&lr); print// record. AutomaticallyACE_GUARD_RETURN acquire (LOCK, mutexif guard, lock. (ACE_OS::write lock, (out, -1); lr.buf,return lr.size) 0; == -1) Thread-safe

Advanced ACE Tutorial template ACE_HANDLE ssize_t out) { } Vanderbilt University Vanderbilt University 147 Advanced ACE Tutorial Douglas C. Schmidt Advanced ACE Tutorial Douglas C. Schmidt The Adapter Pattern Remaining Caveats Intent 1: request () int Logging_Handler::handle_input (void) There is a race { Adapter  Convert the interface condition when client of a class into another ssize_t n = handle_log_record incrementing the request() (peer ().get_handle (), ACE_STDOUT); interface client if (n > 0) request_count 2: specific_request() expects // Count # of logging records. variable Adaptee1 ++request_count;

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 COUNTER; //...

class TYPE = u_long> for (; ; ++request_count)

Strategized Locking handle_log_record Synchronization Using C++

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 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 MESSAGE_QUEUE; { typedef u_long COUNTER; initialize socket acceptor at port 80 // Track the number of requests COUNTER request_count; // At file scope. foreach (incoming request}) { // Entry point into the Web HTTP 1.0 protocol, use select to wait for new // which runs in each thread in the thread pool. connections or data void *worker (MESSAGE_QUEUE *msg_queue) if (connection) { establish connections using accept() Message mb; // Message containing HTTP request. else if (data) { use sockets calls to while (msg_queue->dequeue_head (mb)) > 0) { read() HTTP requests into msg // Keep track of number of requests. msg_queue.enqueue_tail (msg); ++request_count; } } // Print diagnostic } cout << "got new request" << ACE_OS::thr_self () This is the “supplier” thread << endl; // Identify and perform Web Server // request processing here... } return 0; }

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 // Check boundary conditions & don’t hold locks. // Synchronization aspect int is_empty_i (void) const; class ACE_Message_Queue { int is_full_i (void) const; public: // Default high and low water marks. // Routines that actually do the enqueueing enum { // and dequeueing and don’t hold locks. DEFAULT_LWM = 0, int enqueue_prio_i (ACE_Message_Block *); DEFAULT_HWM = 4096 int enqueue_tail_i (ACE_Message_Block *); }; int dequeue_head_i (ACE_Message_Block *&); // Initialize a Message_Queue. int dequeue_tail_i (ACE_Message_Block *&); Message_Queue (size_t hwm = DEFAULT_HWM, // ... size_t lwm = DEFAULT_LWM); // Parameterized types for synchronization // Check if full or empty (hold locks) // primitives that control concurrent access. int is_empty (void) const; // Note use of C++ traits int is_full (void) const; typename SYNCH_STRAT::MUTEX lock_; typename SYNCH_STRAT::COND not_empty_cond_; // Enqueue and dequeue Message_Block *’s. int enqueue_prio (ACE_Message_Block *, ACE_Time_Value *); typename SYNCH_STRAT::COND not_full_cond_; int enqueue_tail (ACE_Message_Block *, ACE_Time_Value *); int dequeue_head (ACE_Message_Block *&, ACE_Time_Value *); size_t high_water_mark_; int dequeue_tail (ACE_Message_Block *&, ACE_Time_Value *); size_t low_water_mark_; size_t cur_bytes_; size_t cur_count_; };

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 ::ACE_Message_Queue SYNCH_STRAT> template ::is_empty_i SYNCH_STRAT> (void) int const { return cur_bytes_ ==template 0 ::is_full_i SYNCH_STRAT> cur_count_ (void) int == const { 0; return } cur_bytes_ >template high_water_mark_; ::is_empty SYNCH_STRAT> (void) int const { } template ::is_full SYNCH_STRAT> (void) int const { } Vanderbilt University Vanderbilt University 172 Advanced ACE Tutorial

Advanced ACE Tutorial Douglas C. Schmidt Advanced ACE Tutorial Douglas C. Schmidt ACE_Message_Queue Operations Overcoming Algorithmic Decomposition Limitations template int template int  Previous slides illustrate tactical techniques and patterns that: ACE_Message_Queue:: ACE_Message_Queue:: enqueue_tail (ACE_Message_Block *item, dequeue_head (ACE_Message_Block *&item, – Reduce accidental complexity e.g. , ACE_Time_Value *tv) { ACE_Time_Value *tv) {  Automate synchronization acquisition and release (Scoped ACE_GUARD_RETURN (SYNCH_STRAT::MUTEX, ACE_GUARD_RETURN (SYNCH_STRAT::MUTEX, guard, lock_, -1); guard, lock_, -1); Locking idiom) // Wait while the queue is full. // Wait while the queue is empty. while (is_full_i ()) { while (is_empty_i ()) {  Improve synchronization mechanisms (Adapter, Wrapper // Release the and wait // Release lock_ and wait for timeout, Facade, Monitor Object, Thread-Safe Interface, Strategized // for timeout, signal, or space // signal, or a new message being // to become available in the list. // placed in the list. Locking patterns) if (not_full_cond_.wait (tv) == -1) if (not_empty_cond_.wait (tv) == -1) return -1; return -1; – Eliminate race conditions } }

// 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 schedule_timer case send reactor in doesn’t timeout // Register // input. ()->register_handler handle reactor to with // Register // . , by into called point // Entry // prtosi nOO-manner an in operations s the Use optimal always is model multi-threading program single to No hard very be can Multi-threading non-robust and inefficient Web often Reactive are since servers needed are servers Web Multi-threaded

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 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 public : ita n u AEMsaeBok*, (ACE_Message_Block put int virtual (void); *instance HTTP_Processor static ita n v (void) svc { int virtual Solution Forces Problem – – – – /Ps eus otetra pool. thread the to request a Pass // point. access Singleton // /Wi o esgst arrive. to { messages (;;) for for Wait // 0; = thread. *mb pool ACE_Message_Block a into point Entry // s the Use unsafe... Singleton makes locking slow... little Too too Singleton makes locking much Too in “bugs” applications subtle multi-threaded has implementation Singleton canonical The locking /Sre eus processing... HTTP request perform Server from and // Inherited Identify // // (mb); getq

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 Features mutex_.acquire (); class ACE_Singleton : public ACE_Cleanup { if (instance_ == NULL)  Allows atomic initialization, public:  Turns any class into instance_ = new HTTP_Processor; static TYPE *instance (void) { mutex_.release (); regardless of initialization order, // Memory barrier could go here... a singleton } and eliminates subsequent if (s_ == 0) { return instance_; ACE_GUARD_RETURN (LOCK, g,  Automates locking overhead ACE_Object_Manager ::get_singleton_lock (), -1); Double-Checked HTTP Forces Resolved: if (s_ == 0) Locking Optimization Processor s_ = new ACE_Singleton;

 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 *s_; ObjMan.pdf memory access };

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 int

h ratrPattern Proactor The HTTP_Handler::handle_input (ACE_HANDLE h)

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::instance ()->put (mb); DEPENDENT n }

- } 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 The HTTP_Acceptor class HTTP_Acceptor : class implements the public ACE_Acceptor, // Note use of a "trait".

 i.e.,itaccepts ACCEPTOR> { connections/initializes public: HTTP_Handlers

// Called when is Class Implementation // dynamically linked. virtual int init (int argc, char *argv[]); // Called when is // dynamically unlinked. virtual int fini (void); // ... }; Reactor::instance ()); PA::PEER_ADDR (Options::instance ()->port ()), msg_queue ()->deactivate (); thr_mgr ()->wait (); Options::instance ()->parse_args (argc, argv); // Initialize// the register communicationpeer_acceptor to endpoint ().open accept and (typename connections. // ShutdownHTTP_Processor::instance threads ()-> in the pool. // WaitHTTP_Processor::instance for ()-> all threads to exit. HTTP_Acceptor // Initialize service whentemplate dynamically ::init PA> (int int { argc, char *argv[]) Vanderbilt University Advanced ACE Tutorial } // Terminate service whentemplate dynamically ::fini PA> (void) int { Vanderbilt University 208 }

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; // ACE dynamically unlinks and svc.conf dynamic Web_Server Service_Object * // deallocates this object. FILE web_server:make_Web_Server() "-port 80" }

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 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 <>  Dynamically creates an ACE_Svc_Handler object for each IPC_SAP Concurrency global client and “activates” it Proxy_Handler SOCK_Connector SVC_HANDLER PEER_CONNECTOR

 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

1 with errno EWOULDBLOCK. // Cancel a that was No time Block in connect_svc_handler() // started asynchronously. up to specified amount of time for virtual int cancel (SVC_HANDLER *svc_handler); completion; if still not completed,

return 1 with errno ETIME. No NULL Block in connect_svc_handler() indefinitely for completion.

Vanderbilt University Vanderbilt University Advanced ACE Tutorial Do Advanced ACE Tutorial Do ACE_Connector Hook Method ACE_Connector Class Protected Implementations Interface

protected: template SH * // Make a new connection. ACE_Connector::make_svc_handler (void) { virtual SVC_HANDLER *make_svc_handler (void); return new SH; // Accept a new connection. } virtual int connect_svc_handler template int (SVC_HANDLER *&sh, ACE_Connector::connect_svc_handler (SH &*sh, typename const PEER_CONNECTOR::PEER_ADDR &addr, typename const PEER_CONNECTOR::PEER_ADDR &addr, ACE_Time_Value *timeout); ACE_Time_Value *timeout) { // Activate a service handler. // Peer_Connector factory initiates connection. virtual int activate_svc_handler (SVC_HANDLER *); if (connector_.connect (sh, addr, timeout) == -1) // If the connection hasn’t completed, then // Demultiplexing hooks. // register with the Reactor to call us back. virtual int handle_output (ACE_HANDLE);// Success. if (use_reactor && errno == EWOULDBLOCK) virtual int handle_input (ACE_HANDLE); // Failure. // Create for & return -1 virtual int handle_timeout (ACE_Time_Value &, } else const void *); // Activate immediately if we’re connected. // Table maps I/O handle to an ACE_Svc_Tuple *. activate_svc_handler (sh); Hash_Map_Manager handler_map_; template int // Factory that establishes connections actively. ACE_Connector::activate_svc_handler (SH *sh) PEER_CONNECTOR connector_; { if (sh->open ((void *)this) == -1) sh->close (); } };

Vanderbilt University Vanderbilt University

Advanced ACE Tutorial Do Advanced ACE Tutorial Do Specializing ACE_Connector and ACE_Connector Class Implementation ACE_Svc_Handler // Initiate connection using specified APPLICATION- // blocking semantics. INDEPENDENT Svc template int Handler APPLICATION- ACE_Connector::connect SPECIFIC (SH *&sh, const PC::PEER_ADDR &r_addr, Proxy ACE_Synch_Options &options) Handler { ACE_Time_Value *timeout = 0; int use_reactor = Supplier options[ACE_Synch_Options::USE_REACTOR]; Consumer Message Handler if (use_reactor) Handler Queue timeout = &ACE_Time_Value::zero; else timeout =

 Producing an application that meets Gateway options[ACE_Synch_Options::USE_TIMEOUT] requirements involves specializing ACE ? (Time_Value *) &options.timeout () : 0; components // Hook methods. if (sh == 0) sh = make_svc_handler (); – ACE_Connector ! if (connect_svc_handler (sh, raddr, ACE_Proxy_Handler_Connector timeout) != -1)

– ACE_Svc_Handler ! activate_svc_handler (sh);

ACE_Proxy_Handler ! } ACE_Supplier_Handler and ACE_Consumer_Handler

Vanderbilt University Vanderbilt University }; private: adritUniversity Vanderbilt public: { ACE_Hash_Map_Manager INT_ID, class class EXT_ID,

} Advanced ACE Tutorial Do olfn_ ETI,ITI &); INT_ID ... (EXT_ID, // find_i bool lock_; LOCK olfn ETI x N_D&in) code... INT_ID Exception-safe ex, // (EXT_ID { find *); (EXT_ID); bool INT_ID unbind (EXT_ID, bool bind bool

/lc_rlae(); true; lock_.release return false; // in)) return (ex, else (find_i (); if lock_.read_acquire // g, (LOCK, ACE_READ_GUARD ACE_Proxy_Handler Class Public

pligteSrtgzdLcigpattern Locking Strategized the Applying Interface othe to ls LOCK> class // Determine the type of threading mechanism. #if defined (ACE_USE_MT) typedef ACE_MT_SYNCH SYNCH;

ACE_Hash_Map_Manager #else typedef ACE_NULL_SYNCH SYNCH; ok,false); lock_, #endif /* ACE_USE_MT */

// Unique connection id that denotes Proxy_Handler. typedef short CONN_ID;

// This is the type of the Routing_Table. typedef ACE_Hash_Map_Manager to pattern Locking Strategized template-based the uses ACE_Hash_Map_Manager   ROUTING_TABLE; strategies, synchronization different Parameterize reuse Enhance –

ACE_RW_Mutex ACE_Thread_Mutex ACE_Null_Mutex class Proxy_Handler : public ACE_Svc_Handler {

Class public:

// Initialize the handler (called by the e.g.

oga .Schmidt C. Douglas // or ). virtual int open (void * = 0); :

etc. , // Bind addressing info to Router. virtual int bind (const ACE_INET_Addr &, CONN_ID); , 234 , Vanderbilt University dacdAETutorial ACE Advanced adritUniversity Vanderbilt    Advanced ACE Tutorial Do ahn provides Hashing a Use A: Q: – einItrue aaeeiigSynchronization Parameterizing Interlude: Design

 

associates a provides ACE Detailed OO Architecture Table? Routing a implement to technique good a What’s of the Gateway (values) ids Internal (keys) ids External ACE_Hash_Map_Manager

Consumer Routing the into Table Supplier

Handler Handler ids external Hash Map Manager SOCK Message SOCK Stream Queue Stream O ACE_Hash_Map_Manager

Reactor 1

Supplier ACE_Hash_Map_Manager efrac nteaverage-case the in performance Handler Consumer ! Handler !

Connector with SOCK Acceptor URI Stream SOCK Message file memory-mapped to pointer SOCK Hash Map SOCK Stream Queue

Connector Manager Acceptor nenlids internal

INCOMING OUTGOING MESSAGES GATEWAY

MESSAGES container CONNECTION CONNECTION REQUEST REQUEST

, e.g. otie that container ,

Note the use of other ACE components, such as the socket wrapper facades and the Schmidt C. Douglas ACE_Hash_Map_Manager 233 Vanderbilt University } public: { adritUniversity Vanderbilt : Proxy_Handler_Connector class Tutorial ACE Advanced Advanced ACE Tutorial Do n initiate_connection int ACE_Connector public ACE_Proxy_Handler_Connector PoyHnlr*); (Proxy_Handler Proxy_Handler. on the connection // reinitiate) a (or // Initiate // ACE_Supplier_Handler Interface

/Cneto factory Connection Handler // Svc of ACE_SOCK_Connector> Type //

protected: // Receive and process Peer messages. virtual int handle_input (ACE_HANDLE);

// Receive a message from a Peer. virtual int recv_peer (ACE_Message_Block *&);

  // Action that routes a message from a Peer. connections failed restarting by reliability Connector ACE_Proxy_Handler_ that: class factory Connector ACE_Proxy_Handler_ – – int route_message (ACE_Message_Block *); hc hnruemessages route then which ACE_Proxy_Handler Activates ACE_Proxy_Handler produce to Peers with connections Establishes // Keep track of message fragment. ACE_Message_Block *msg_frag_;

ls Interface Class }; loensures also concrete a is oga .Schmidt C. Douglas s, s 238 Vanderbilt University

Advanced ACE Tutorial Do Advanced ACE Tutorial Do ACE_Proxy_Handler_Connector ACE_Consumer_Handler Interface Implementation class Consumer_Handler : public Proxy_Handler { // (re)initiate a connection to a Proxy_Handler public: int Consumer_Handler (void); Proxy_Handler_Connector::initiate_connection (Proxy_Handler *ph) // Send a message to a Gateway { // (may be queued). // Use asynchronous connections... virtual int put (ACE_Message_Block *, if (connect (ph, ACE_Time_Value * = 0); ph->addr (), ACE_Synch_Options::asynch) == -1) { protected: if (errno == EWOULDBLOCK) // Perform a non-blocking put(). // No error, we’re connecting asynchronously. int nonblk_put (ACE_Message_Block *mb); return -1; else // Finish sending a message when // This is a real error, so reschedule // flow control abates. // ourselves to reconnect. virtual int handle_output (ACE_HANDLE); reactor ()->schedule_timer (ph, 0, ph->timeout ()); // Send a message to a Peer. } virtual int send_peer (ACE_Message_Block *); else // We’re connected synchronously! }; return 0; }

Vanderbilt University Vanderbilt University Do

Advanced ACE Tutorial Douglas C. Schmidt The Non-blocking Buffered I/O Pattern Routing Intent Table

 Decouple multiple input find() 1 Message Queue sources from multiple output

n 5: send_peer(msg)

sources to prevent blocking Handler Consumer Consumer Queue Supplier 7: send_peer(msg) 8: enqueue(msg) 9: schedule_wakeup() ------10: handle_output() dequeue(msg) 11: 12: send_peer(msg) Message LAYER

ROUTING Handler Handler Forces Resolved:

handle_input() handle_output() Handler put() Consumer Queue  Keep misbehaving Message connections from disrupting

Event the QoS for well-behaved Reactor (msg) put 4: Handler n 1 6: put (msg) 6: put

LAYER connections REACTIVE Gateway Routing

www.cs.wustl.edu/˜schmidt/PDF/  Different concurrency Handlers Consumer 1: handle_input() 2: recv_peer(msg) TAPOS-00.pdf strategies for Table Supplier_Handlers and Routing

Consumer_Handlers Collaboration in Single-threaded Handler Supplier ID 3: find() ROUTE Note the complex cooperative schedulingrequired logic to handle output flow control correctly Vanderbilt University Vanderbilt University 240 Advanced ACE Tutorial Do Do and ACE_Time_Value *) { Implementations Message Routing Supplier_Handler si.next (out_ph)si.advance != ()) -1; { (ACE_Message_Block *route_addr) newmsg->release (); // Decrement ref count. (mb, &ACE_Time_Value::zero); ACE_Message_Block *newmsgif = (out_ph->put data->duplicate (newmsg) (); == -1) // Drop message. if (errnoelse == return EWOULDBLOCK) n; return 0; route_message (route_addr); *(CONN_ID *) route_addr->rd_ptr (); route_addr->cont (); si (re->destinations ()); // Trynonblk_put to (mb); send the messagemsg_queue_->enqueue_tail *without* blocking! ACE_Message_Block *route_addrint = n 0; // = Try recv_peerif to (route_addr); (n get <= the 0) next { message. } else // DetermineCONN_ID destination route_id address. = const ACE_Message_Block *const dataRouting_Entry = *re = 0; // DetermineRouting_Table::instance route. ()->find (route_id, re); // InitializeSet_Iterator over destination(s). // Multicastfor message. (Proxy_Handler *out_ph; if (msg_queue_->is_empty ()) else // Messages are queued due to flow control. } delete route_addr; Consumer_Handler Supplier_Handler Advanced ACE Tutorial int Supplier_Handler::handle_input (ACE_HANDLE) { Vanderbilt University Advanced ACE Tutorial // Routeint message Supplier_Handler::route_messages from a Peer. { Vanderbilt University } } // Send a messageint to Consumer_Handler::put a (ACE_Message_Block Peer *mb, (queue if necessary). } Advanced ACE Tutorial Do Advanced ACE Tutorial Do Supplier Handler Message Reception Peer_Message Schema

// Pseudo-code for recv’ing msg via non-blocking I/O // Peer address is used to identify the int Supplier_Handler::recv_peer // source/destination of a Peer message. (ACE_Message_Block *&route_addr) class Peer_Addr { { public: if (msg_frag_ is empty) { CONN_ID conn_id_; // Unique connection id. msg_frag_ = new ACE_Message_Block; u_char logical_id_; // Logical ID. receive fixed-sized header into msg_frag_ u_char payload_; // Payload type. if (errors occur) cleanup }; else determine size of variable-sized msg_frag_ // Fixed sized header. } else class Peer_Header { public: /* ... */ }; determine how much of msg_frag_ to skip // Variable-sized message (sdu_ may be non-blocking recv of payload into msg_frag_ // between 0 and MAX_MSG_SIZE). if (entire message is now received) { route_addr = new Message_Block class Peer_Message { (sizeof (Peer_Addr), msg_frag_) public: Peer_Addr addr (id (), msg_frag_->routing_id_, 0); // The maximum size of a message. route_addr->copy (&addr, sizeof (Peer_Addr)); enum { MAX_PAYLOAD_SIZE = 1024 }; return to caller and reset msg_frag_ Peer_Header header_; // Fixed-sized header. } char sdu_[MAX_PAYLOAD_SIZE]; // Message payload. else if (only part of message is received) }; return errno = EWOULDBLOCK else if (fatal error occurs) cleanup }

Vanderbilt University Vanderbilt University dacdAETutorial ACE Advanced adritUniversity Vanderbilt Tutorial ACE Advanced University Vanderbilt

      rce gi ihu oln rblocking? or polling without again proceed Peer a if blocking controlled output flow avoiding becomes with connection deals issue design related A same... the is or policy object handling router error each the for whether different on depends answer The A: Q: hspoie oprtv ut-akn ihnasnl hedof thread single a control within multi-tasking cooperative provides This Reactor the of scheme notification the Use A: Q: – – – –

einItrue iso adigFo Control Flow Handling on Tips Interlude: Design

e.g. cancel_wakeup() i.e. taeypattern: Strategy ehdwe the when method The

htsol apni u( fails? put() if happen should What o a o controlled flow a can How i the via , einItrue sn the Using Interlude: Design faqeebcmsfull? becomes queue a if , ACE_Reactor ACE_Event_Handler::handle_output() ACE_Reactor

oHnl lwControl Flow Handle to ieraoal eal,btalwsubstitution allow but default, reasonable give Proxy_Handler al akt the to back calls

smethods ’s Consumer_Handler sal otasi again transmit to able is handle_output() schedule_wakeup()

ACE_Reactor nwwe to when know oga .Schmidt C. Douglas oga .Schmidt C. Douglas hook and 245 247 Do

Advanced ACE Tutorial Douglas C. Schmidt Performing a Non-blocking put() of a Message int Consumer_Handler::nonblk_put This method is called (ACE_Message_Block *mb) { in two situations: // Try sending message // via non-blocking I/O 1. When first trying if (send_peer (mb) != -1 to send over a && errno == EWOULDBLOCK) { connection // Queue in *front* of the // list to preserve order. 2. When flow control msg_queue_->enqueue_head abates (mb, &ACE_Time_Value::zero); // Tell Reactor to call us // back it’s ok to send again. reactor ()->schedule_wakeup (this, ACE_Event_Handler::WRITE_MASK); } } return errno == EWOULDBLOCK// ? Skip 0mb->rd_ptr over : (n); the n; part we// did Decrement send. mb->release reference (); count. errno = 0; Sending a Message to a Consumer ssize_t n; size_t len = mb->length// (); Tryn to = send peer the ().send message. if (mb->rd_ptr (n (), <= len); 0) else if (n < len) else /* if (n == length) */ { } return n; int Consumer_Handler::send_peer (ACE_Message_Block{ *mb) } Vanderbilt University Vanderbilt University 248 Advanced ACE Tutorial Do Do - - SPECIFIC Table INDEPENDENT APPLICATION APPLICATION Routing Manager Hash Map Hash Class Table Config (mb, &ACE_Time_Value::zero); SUPPLIER HANDLER SUPPLIER CONSUMER HANDLER Object Service Gateway Gateway The Flow Control Abates Finish Sending when (this, ACE_Event_Handler::WRITE_MASK); || errno != EWOULDBLOCK) { reactor ()->cancel_wakeup // If// we (and succeed// as in on a writing// the result msg ), there out not then are completely to tell noif notify the more (msg_queue_->is_empty us msgs () anymore. Proxy Handler ACE_Message_Block *mb = 0; // Takemsg_queue_->dequeue_head the first message off the queue. if (nonblk_put (mb) != -1 } Connector Connector Advanced ACE Tutorial // Finish// sending conditions a// abate. message called when by This flow the method control int Reactor. is automatically Consumer_Handler::handle_output (ACE_HANDLE) { Vanderbilt University Advanced ACE Tutorial This class integrates other application-specificapplication-independent and components Vanderbilt University } Do

Advanced ACE Tutorial Douglas C. Schmidt Dynamically Configuring Gateway into an Application Pool Object Object Service Service Thread Gateway Gateway Thread-per Parameterized by proxy handler Example of the Component Connection template Configurator pattern S { class Gateway // Initialize the daemon and : public Service_Object // dynamically configure services. { ACE_Service_Config::open (argc, public: argv); // Perform initialization. // Run forever, performing the Object

virtual int init Service Reactive // configured services. Gateway Reactor (int argc, char *argv[]); ACE_Reactor::instance ()->

run_reactor_event_loop (); * Service_Object Gateway dynamic 2001" "-p gateway:make_Gateway() // Perform termination. /* NOTREACHED */ virtual int fini (void); } Framework for the Gateway FILE Service Config svc.conf Repository Service SERVICE RUNTIME Using the ACE Service Configurator CONFIGURATOR We can replace the single-threadeda Gateway multi-threaded with Gateway Vanderbilt University Vanderbilt University 252 Advanced ACE Tutorial

Advanced ACE Tutorial Douglas C. Schmidt Advanced ACE Tutorial Douglas C. Schmidt Dynamic Linking a Gateway Service Concurrency Strategies for Patterns

The Gateway service is Dynamically linked factory function configured via scripting in a that allocates a new  The Acceptor-Connector pattern does not constrain the concurrency svc.conf file: single-threaded Gateway strategies of a ACE_Svc_Handler % cat ./svc.conf extern "C"  There are three common choices: static Svc_Manager ACE_Service_Object *make_Gateway (void); "-p 5150" ACE_Service_Object *make_Gateway (void) 1. Run service in same thread of control dynamic Gateway { 2. Run service in a separate thread Service_Object * return new gateway:_make_Gateway() 3. Run service in a separate process "-d -p $PORT" Gateway

Consumer_Handler>;  # .dll or .so suffix Observe how our patterns and ACE framework push this decision to // ACE automatically deletes memory. # added to "gateway" the “edges” of the design } # automatically – This greatly increases reuse, flexibility, and performance tuning

Vanderbilt University 254 Vanderbilt University 255 adritUniversity Vanderbilt Tutorial ACE Advanced sn h afSn/afAycPteni h Gateway the in Pattern Half-Sync/Half-Async the Using ASYNCHRONOUS QUEUEING SYNCHRONOUS Advanced ACE Tutorial Do TASK LAYER LAYER TASK LAYER Using the Active Object Pattern Consumer Supplier Handler Handler Handler for the Gateway Supplier Handler 2: send(msg) 2: dequeue(msg) 1: CONCRETE Supplier Consumer Supplier EVENT MESSAGE QUEUES Supplier Handler Consumer Handler Handler HANDLERS HandlerSupplier Consumer Handler Handler Handler EventHandler 4: enqueue(msg) 4: get_route(msg) 3: 2: recv(msg) Event 4: send(msg) Handler Event LEVEL Event Handler Handler Event Handler

APPLICATION Handler 2: recv(msg) 1: dispatch() 3: route(msg) Consumer Reactor Handler Handler 1: handle_input()

Handle Timer Signal

   Table LEVEL Queue Handlers POSA2 in described as pattern, the Half-Sync/Half-Async of variant common a is configuration particular This layer “sync” of role the plays ACE_Task layer “async” of role ACE_Reactor

FRAMEWORK Reactor

OS EVENT DEMULTIPLEXING INTERFACE LEVEL cieobject active KERNEL ly the plays

oga .Schmidt C. Douglas Each Consumer_Handler is implemented as an Active Object 258 Vanderbilt University

Advanced ACE Tutorial Do Advanced ACE Tutorial Do Class Diagram for Multi-Threaded Collaboration in Multi-threaded Gateway Gateway Routing

- Proxy_Handler SOCK_Connector SOCK_Stream MT_Synch Routing Consumer 1 Proxy Table Handler Handler Supplier/Thr_Consumer

SPECIFIC Connector n Handler Message 5: send_peer(msg) APPLICATION COMPONENTS <> Queue ROUTE ID Consumer

- Consumer SVC_HANDLER PEER_STREAM Handlers PEER_CONNECTOR SYNCH 3: find() Handler

Connector Svc Message ORIENTED Handler 4: put (msg) Queue CONNECTION COMPONENTS

Supplier 6: put (msg) 5: send_peer(msg)

PEER PEER Handler CONNECTOR STREAM 1: handle_input() Stream 2: recv_peer(msg) Connection

ACE IPC_SAP FRAMEWORK COMPONENTS Service Note that this design is much simpler since the OS Configurator thread scheduler handles blocking Concurrency Reactor global

Vanderbilt University Vanderbilt University Advanced ACE Tutorial Douglas C. Schmidt Advanced ACE Tutorial Douglas C. Schmidt Thr_Consumer_Handler Class Interface Thr_Consumer_Handler Class Implementation #define ACE_USE_MT New subclass of

#include Proxy_Handler.h Proxy_Handler uses the Override definition in the  The multi-threaded version Active Object pattern for the Consumer_Handler class of open() is slightly class Thr_Consumer_Handler int : public Consumer_Handler Consumer_Handler different since it spawns a Thr_Consumer_Handler::open (void *) new thread to become an { {  Uses multi-threading and public: // Become an active object by active object! // Initialize the object and synchronous I/O (rather than // spawning a new thread to // spawn new thread. non-blocking I/O) to transmit // transmit messages to Peers.  activate() is a virtual int open (void *); message to Peers pre-defined method on // Send a message to a peer. activate (THR_DETACHED); ACE_Task virtual int put  Transparently improve } (ACE_Message_Block *, ACE_Time_Value *); performance on a // Transmit peer messages multi-processor platform and // in separate thread. simplify design virtual int svc (void); };

Vanderbilt University 260 Vanderbilt University 261 Do

Advanced ACE Tutorial Douglas C. Schmidt Dynamic Linking a Threaded Gateway Service

% cat ./svc.conf Dynamically linked factory Class remove Gateway function that allocates a dynamic Gateway multi-threaded Gateway object Service_Object * extern "C" &ACE_Time_Value::zero); thr_gateway:_make_Gateway() ACE_Time_Value *) ACE_Service_Object *make_Gateway (void); "-d" # .dll or .so suffix added ACE_Service_Object *make_Gateway (void) # to "thr_Gateway" { # automatically return new Gateway;

Implementation // ACE automatically deletes memory. } Thr_Consumer_Handler send_peer (mb); // Performmsg_queue_->enqueue_tail non-blocking (mb, enqueue. ACE_Message_Block *mb = 0; // Since// this is method OK runs to inwhile block its (msg_queue_->dequeue_head on own (mb) output. thread != it -1) Advanced ACE Tutorial // Queue up aint message forThr_Consumer_Handler::put transmission. (ACE_Message_Block *mb, { } // Transmit// messages simplification to resulting the from peerint threads...) (note Thr_Consumer_Handler::svc (void) { Vanderbilt University } Vanderbilt University 263 adritUniversity Vanderbilt Tutorial ACE Advanced    Advanced ACE Tutorial Do h C vn evrwsdsg n mlmne sn ACE using implemented and design Streams was Server Event CCM The the of implementation an is It modules An – – –

aai asdtruhppsbtenajcn les hc can which filters, adjacent re-combined between be pipes through passed is Data filter a in component encapsulated is step processing a Each process that data systems of for stream structure a provides pattern This Call Center Manager (CCM) ACE_Stream

vriwo h C tem Framework Streams ACE the of Overview Event Server Example

SUPER SUPER VISOR SUPER VISOR VISOR losflxbecngrto flyrdprocessing layered of configuration flexible allows

CCM Session Router Stream Module

ie n Filters and Pipes Event Filter Module

MIB Event Analyzer Module

ACE Switch Adapter RUN-TIME Module rhtcuepattern architecture ACE_Module TELECOM

oga .Schmidt C. Douglas SWITCHES EVENT SERVER 266 Vanderbilt University

Advanced ACE Tutorial Do Advanced ACE Tutorial Do Structure of the ACE Streams Patterns in the CCM Event Server Framework Publisher Subscriber

SYNCH SYNCH SYNCH ACE_Task ACE_Module ACE_Stream Pipes & 2 2..* Layers Filters

Acceptor- Component Connector Configurator Framework characteristics STRATEGIC Reactor PATTERNS

 An ACE_Stream contains a stack of ACE_Modules TACTICAL Iterator Composite Factory Proxy Wrapper  Each ACE_Module contains two ACE_Tasks PATTERNS Method Facade

– i.e.,aread task and a write task  Each ACE_Task contains an  The Event Server components are based upon ACE_Message_Queue and a pointer to an a common pattern language ACE_Thread_Manager

 www.cs.wustl.edu/˜schmidt/PDF/ DSEJ-94.pdf

Vanderbilt University Vanderbilt University Advanced ACE Tutorial Do Advanced ACE Tutorial Do Using the ACE Streams Framework Implementing a Stream in ACE for the CCM Event Server APPLICATION APPLICATION Stream Stream SUPER Session Router VISORS Module SUPER STREAM VISORS Head Presentation Module SUPER VISORS

Event Filter Session IO Module Reactor

Event Analysis UPSTREAM Module Multiplexor Switch IO MD110 ERICSSON open()=0 STREAM Presentation DOWNSTREAM close()=0 MD110 ERICSSON Module Tail put()=0 svc()=0 Switch Adapter MD110 ERICSSON NETWORK INTERFACE Module OR PSEUDO-DEVICES TELECOM SWITCHES

MESSAGE MODULE WRITE READ www.cs.wustl.edu/˜schmidt/PDF/ TASK TASK

DSEJ-94.pdf Note similarities to System V STREAMS

Vanderbilt University Vanderbilt University adritUniversity Vanderbilt Tutorial ACE Advanced SWITCHES

rae otx:Etra SfrTlcmSwitches Telecom for OS External Context: Broader Advanced ACE Tutorial Do CLIENT Alternative Concurrency Models for Message Processing CLIENT SERVER

NETWORK ACTIVE ACTIVE ACTIVE DIRECTORY

MANAGER Module A ACTIVE Module EXTENSION MANAGER 4: svc() A CLIENT APPLICATION FRAMEWORK 3: put() 2: put()

CALL CENTER Module Module MANAGER B ACTIVE 2: svc() B CLIENT 1: put() 1: put() Module Module C

Features ACTIVE

  C framework architectural common a on based components existing of reuse Support software switch the modifying without switches telecom of aspects various manage to clients Allow TASK-BASED MESSAGE-BASED PROCESS ARCHITECTURE PROCESS ARCHITECTURE

MESSAGE MODULE WRITE TASK READ TASK PROCESS OR OBJECT OBJECT OBJECT OBJECT THREAD oga .Schmidt C. Douglas Task-based models are more intuitive but less efficient than Message-based models 271 Vanderbilt University Advanced ACE Tutorial Douglas C. Schmidt Advanced ACE Tutorial Douglas C. Schmidt Applying ACE Streams to External OS ACE Stream Example: Parallel I/O Copy

CLIENT DIRECTORY 5: write()  Program copies stdin CLIENT CALL CENTER MANAGER MANAGER to stdout via the use of a multi-threaded Consumer CLIENT Event active ACE_Stream NETWORK Analyzer Module 4: svc() DATABASE

 Stream implements a

SWITCHES Switch Session “bounded buffer” Adapter Router 3: put()

 Since the data flow is ACE Reactor FRAMEWORK Producer active uni-directional the Module 2: svc() ACE_Task EXTENSION “read” is MANAGER always ignored SERVER 1: read()

Vanderbilt University 272 Vanderbilt University 273 Do Do mb->wr_ptr (), mb->size ()); Class Interface ACE_Message_Block (BUFSIZ), -1); interface Class Implementation Producer Producer // Send// shutdown thread messagemb->length and to (0); exit. other this->put_next (mb); break; mb->wr_ptr (n); // Adjust// write Send pointer. this->put_next the (mb); message to the other thread. Producer // activate()activate is (THR_BOUND); inherited from class Task. ACE_Message_Block *mb; // AllocateACE_NEW_RETURN a (mb, new message. // Keepssize_t reading n stdin, = until ACE_OS::read we (ACE_STDIN, reach EOF. if (n <= 0) { } else { } // Initializevirtual Producer. int{ open (void *) } // Readvirtual data int from// svc stdin ... (void); and pass to consumer. for (;;) { } Advanced ACE Tutorial typedef short-hands for templates typedef ACE_Streamtypedef MT_Stream; ACE_Moduletypedef MT_Module; ACE_Task MT_Task; Define the class Producer{ : publicpublic: MT_Task }; Vanderbilt University Advanced ACE Tutorial Runs as an active object in aint separate thread Producer::svc (void) { } Vanderbilt University Advanced ACE Tutorial Do Advanced ACE Tutorial Do Main Driver Function for the Stream Consumer Class Interface

Create Producer and Consumer Modules and Define the Consumer interface push them onto the Stream class Consumer : public MT_Task int main (int argc, char *argv[]) { { public: // Control hierarchically-related // Initialize Consumer. // active objects. virtual int open (void *) MT_Stream stream; { // is inherited from class Task. // All processing is performed in the activate (THR_BOUND); // Stream after ’s complete. } stream.push (new MT_Module ("Consumer", new Consumer); // Enqueue the message on the Message_Queue stream.push (new MT_Module // for subsequent processing in . ("Producer", new Producer)); virtual int put (ACE_Message_Block *, ACE_Time_Value * = 0) // Barrier synchronization: wait for { // the threads, to exit, then exit // is inherited from class Task. // the main thread. return putq (mb, tv); ACE_Thread_Manager::instance ()->wait (); } } // Receive message from producer // and print to stdout. virtual int svc (void); };

Vanderbilt University Vanderbilt University adritUniversity Vanderbilt Tutorial ACE Advanced    Advanced ACE Tutorial Do “interpositioning” omncto between Communication processing new a “pushing” by added ACE_Module be may functionality New an via objects active Structuring – temps nwM_oue(Poue" e Producer)); new Filter)); ("Producer", new MT_Module Consumer)) ("Filter", (new new MT_Module stream.push ("Consumer", (new MT_Module stream.push (new stream.push

i.e. Consumer Class Implementation

iia oadn le naUI pipeline UNIX a in filter a adding to similar , Consumer dequeues a message from the vlaino h C temFramework Stream ACE the of Evaluation ACE_Message_Queue, writes the message to the stderr stream, and deletes the message

noan onto int Consumer::svc (void) { ACE_Message_Block *mb = 0;

ACE_Stream // Keep looping, reading a message from the queue, // until we get a 0 length message, then quit. ACE_Module for (;;) { int result = getq (mb);

ACE_Stream if (result == -1) break;

, int length = mb->length (); e.g.

stypically is s if (length > 0) : ACE_OS::write (ACE_STDOUT, mb->rd_ptr (), length);

allows mb->release (); anonymous if (length == 0) break; } oga .Schmidt C. Douglas }

The Producer sends a 0-sized message to inform the Consumer to stop reading and exit 279 Vanderbilt University Advanced ACE Tutorial Douglas C. Schmidt Advanced ACE Tutorial Douglas C. Schmidt Concurrency Strategies General Threading Guidelines

  Developing correct, efficient, and robust concurrent applications is A threaded program should not arbitrarily enter non-threaded (i.e., challenging “unsafe”) code

  Below, we examine a number of strategies that addresses Threaded code may refer to unsafe code only from the main thread challenges related to the following: – e.g.,bewareoferrno problems – Concurrency control

 Use reentrant OS library routines (‘ r’) rather than non-reentrant – Library design routines – Thread creation

– Deadlock and starvation avoidance  Beware of thread global process operations, such as file I/O

 Make sure that main() terminates cleanly – e.g.,bewareofpthread_exit(), exit(), and “falling off the end”

Vanderbilt University 280 Vanderbilt University 281

Advanced ACE Tutorial Douglas C. Schmidt Advanced ACE Tutorial Douglas C. Schmidt Thread Creation Strategies General Locking Guidelines

 Use threads for independent jobs that must maintain state for the life  Don’t hold locks across long duration operations (e.g., I/O) that can of the job impact performance

 Don’t spawn new threads for very short jobs – Use ACE_Token instead...

 Use threads to take advantage of CPU concurrency  Beware of holding non-recursive mutexes when calling a method outside a class

 Only use “bound” threads when absolutely necessary – The method may reenter the module and deadlock

 If possible, tell the threads library how many threads are expected to

be active simultaneously  Don’t lock at too small of a level of granularity

– e.g.,usethr_setconcurrency()  Make sure that threads obey the global lock hierarchy – But this is easier said than done...

Vanderbilt University 282 Vanderbilt University 283 Advanced ACE Tutorial Douglas C. Schmidt Advanced ACE Tutorial Douglas C. Schmidt Locking Alternatives Single-lock Strategy

 Code locking  One way to simplify locking is use a single, application-wide mutex lock – Associate locks with body of functions

 Typically performed using bracketed mutex locks  Each thread must acquire the lock before running and release it – Often called a Monitor Object upon completion

 Data locking  The advantage is that most legacy code doesn’t require changes

– Associate locks with data structures and/or objects  The disadvantage is that parallelism is eliminated – Permits a more fine-grained style of locking – Moreover, interactive response time may degrade if the lock isn’t

 Data locking allows more concurrency than code locking, but may released periodically incur higher overhead

Vanderbilt University 284 Vanderbilt University 285

Advanced ACE Tutorial Douglas C. Schmidt Advanced ACE Tutorial Douglas C. Schmidt Monitor Object Strategy Active Object Strategy

 A more OO locking strategy is to use a Monitor Object  Each task is modeled as an active object that maintains its own – www.cs.wustl.edu/˜schmidt/POSA/ thread of control

 Messages sent to an object are queued up and processed  Monitor Object synchronization mechanisms allow concurrent method invocations asynchronously with respect to the caller – Either eliminate access to shared data or use synchronization – i.e., the order of execution may differ from the order of invocation objects

 This approach is more suitable to message passing-based – Hide locking mechanisms behind method interfaces concurrency

 Therefore, modules should not export data directly

 The ACE_Task class can be used to implement active objects

 Advantage is transparency – www.cs.wustl.edu/˜schmidt/POSA/

 Disadvantages are increased overhead from excessive locking and lack of control over method invocation order

Vanderbilt University 286 Vanderbilt University 287 Advanced ACE Tutorial Douglas C. Schmidt Advanced ACE Tutorial Douglas C. Schmidt Invariants Run-time Stack Problems

 In general, an invariant is a condition that is always true  Most threads libraries contain restrictions on stack usage

 For concurrent programs, an invariant is a condition that is always – The initial thread gets the “real” process stack, whose size is only true when an associated lock is not held limited by the stacksize limit – All other threads get a fixed-size stack – However, when the lock is held the invariant may be false

 Each thread stack is allocated off the heap and its size is fixed – When the code releases the lock, the invariant must be at startup time re-established

 Therefore, be aware of “stack smashes” when debugging

 e.g., enqueueing and dequeueing messages in the multi-threaded code ACE_Message_Queue class – Overly small stacks lead to bizarre bugs, e.g.,

 Functions that weren’t called appear in backtraces

 Functions have strange arguments

Vanderbilt University 288 Vanderbilt University 289

Advanced ACE Tutorial Douglas C. Schmidt Advanced ACE Tutorial Douglas C. Schmidt Deadlock Avoiding Deadlock in OO Frameworks

 Permanent blocking by a set of threads that are competing for a set  Deadlock can occur due to properties of OO frameworks, e.g., of resources – Callbacks

 Caused by “circular waiting,” e.g., – Inter-class method calls

– A thread trying to reacquire a lock it already holds  There are several solutions – Two threads trying to acquire resources held by the other – Release locks before performing callbacks

1 2 1 2  e.g., T and T acquire locks L and L in opposite order

 Every time locks are reacquired it may be necessary to

 One solution is to establish a global ordering of lock acquisition (i.e., reevaluate the state of the object a lock hierarchy ) – Make private “helper” methods that assume locks are held when called by methods at higher levels – May be at odds with encapsulation... – Use an ACE_Token or ACE_Recursive_Thread_Mutex

Vanderbilt University 290 Vanderbilt University 291 Advanced ACE Tutorial Do Advanced ACE Tutorial Do Releasing and Initializing an ACE_Recursive_Thread_Mutex ACE_Recursive_Thread_Mutex Implementation int ACE_Recursive_Thread_Mutex::release (void) Here is portable implementation of recursive thread { mutexes available in ACE: ACE_thread_t t_id = ACE_Thread::self (); class ACE_Recursive_Thread_Mutex // Automatically acquire mutex. { ACE_GUARD_RETURN (ACE_Thread_Mutex, guard, public: nesting_mutex_, -1); // Initialize a recursive mutex. nesting_level_--; ACE_Recursive_Thread_Mutex (void); // Implicitly release a recursive mutex. if (nesting_level_ == 0) { ˜ACE_Recursive_Thread_Mutex (void); // Put the mutex into a known state. // Acquire a recursive mutex. owner_ = ACE_OS::NULL_thread; int acquire (void); // Inform waiters that the mutex is free. // Conditionally acquire a recursive mutex. mutex_available_.signal (); int tryacquire (void); } // Releases a recursive mutex. return 0; int release (void); } private: ACE_Recursive_Thread_Mutex:: ACE_Thread_Mutex nesting_mutex_; ACE_Recursive_Thread_Mutex (void) ACE_Condition_Thread_Mutex mutex_available_; : nesting_level_ (0), ACE_thread_t owner_; owner_ (ACE_OS::NULL_thread), int nesting_level_; mutex_available_ (nesting_mutex_){} };

Vanderbilt University Vanderbilt University adritUniversity Vanderbilt Tutorial ACE Advanced    Advanced ACE Tutorial Do hspolmmyb ovdvia: solved be may problem This undefined often is scheduling of order The it even releases mutex periodically a thread acquires another never though thread a when occurs Starvation – –  sn nAE“oe”ta tityodr custo n release and acquisition orders strictly that “Token” ACE an Using s f“outr r-mto”mechanisms pre-emption” “voluntary of Use Acquiring an

e.g. ACE_Recursive_Thread_Mutex ,

thr_yield() int ACE_Recursive_Thread_Mutex::acquire (void) { ACE_thread_t t_id = ACE_Thread::self (); ACE_GUARD_RETURN (ACE_Thread_Mutex, guard, nesting_mutex_, -1);

viigStarvation Avoiding // If there’s no contention, grab mutex. if (nesting_level_ == 0) { owner_ = t_id; or nesting_level_ = 1;

Sleep() } else if (t_id == owner_) // If we already own the mutex, then // increment nesting level and proceed. nesting_level_++; else { // Wait until nesting level drops // to zero, then acquire the mutex. while (nesting_level_ > 0) mutex_available_.wait ();

// Note that at this point // the nesting_mutex_ is held... oga .Schmidt C. Douglas owner_ = t_id; nesting_level_ = 1; } return 0; 295 Vanderbilt University Advanced ACE Tutorial Douglas C. Schmidt Advanced ACE Tutorial Douglas C. Schmidt Drawbacks to Multi-threading Lessons Learned using OO Patterns

 Performance overhead

 Benefits of patterns – Some applications do not benefit directly from threads – Synchronization is not free – Enable large-scale reuse of software architectures – Threads should be created for processing that lasts at least – Improve development team communication several 1,000 instructions – Help transcend language-centric viewpoints

 Correctness  Drawbacks of patterns – Threads are not well protected against interference – Do not lead to direct code reuse – Concurrency control issues are often tricky – Can be deceptively simple – Many legacy libraries are not thread-safe – Teams may suffer from pattern overload

 Development effort – Developers often lack experience – Debugging is complicated (lack of tools)

Vanderbilt University 296 Vanderbilt University 297

Advanced ACE Tutorial Douglas C. Schmidt Advanced ACE Tutorial Douglas C. Schmidt Lessons Learned using OO Frameworks Lessons Learned using C++

 Benefits of frameworks  Benefits of C++ – Enable direct reuse of code (cf patterns) – Classes and namespaces modularize the system architecture – Facilitate larger amounts of reuse than stand-alone functions or – Inheritance and dynamic binding decouple application policies individual classes from reusable mechanisms – Parameterized types decouple the reliance on particular types of

 Drawbacks of frameworks synchronization methods or network IPC interfaces – High initial learning curve

 Drawbacks of C++

 Many classes, many levels of abstraction – The flow of control for reactive dispatching is non-intuitive – Some language features are not implemented – Verification and validation of generic components is hard – Some development environments are primitive – Language has many dark corners and sharp edges

 Purify helps alleviate many problems...

Vanderbilt University 298 Vanderbilt University 299 Advanced ACE Tutorial Douglas C. Schmidt Advanced ACE Tutorial Douglas C. Schmidt Lessons Learned using OOD Software Principles for Distributed Applications

 Good designs can be boiled down to a few key principles:  Use patterns/frameworks to decouple policies/mechanisms – Separate interface from implementation – Enhance reuse of common concurrent programming components – Determine what is common and what is variable with an interface  Decouple service functionality from configuration and an implementation – Improve flexibility and performance – Allow substitution of variable implementations via a common

interface  Use classes, inheritance, dynamic binding, and parameterized

 i.e., the “open/closed” principle & Aspect-Oriented types Programming (AOP) – Improve extensibility and modularity – Dividing commonality from variability should be goal-oriented  Enhance performance/functionality with OS features rather than exhaustive – e.g., implicit and explicit dynamic linking and multi-threading

 Design is not simply drawing a picture using a CASE tool, using

 Perform commonality/variability analysis graphical UML notation, or applying patterns – Identify uniform interfaces for variable components and support – Design is a fundamentally creative activity pluggability of variation

Vanderbilt University 300 Vanderbilt University 301

Advanced ACE Tutorial Douglas C. Schmidt Advanced ACE Tutorial Douglas C. Schmidt Conferences and Workshops on Patterns Patterns, Frameworks, and ACE Literature

 Books  Pattern Language of Programs Conferences – PLoP, September, 2002, Monticello, Illinois, USA – GammaObject-Oriented et al., Design Software Patterns: Elements of Reusable – OOPSLA, November, 2002, Seattle, USA AW, ’94 – Pattern Languages of Program Design series by AW, ’95-’99. – hillside.net/patterns/conferences/ – Siemens & Schmidt, Pattern-Oriented Software Architecture , www.posa.uci.edu  Distributed Objects and Applications Conference Wiley,Complexity volumes with ’96ACE & and ’00 Patterns ( ) – Schmidt & Huston, C++ Network Programming: Mastering – Oct/Nov, 2002, UC Irvine ,AW,’02 – www.cs.wustl.edu/˜schmidt/activities-chair.html www.cs.wustl.edu/˜schmidt/ACE/book1/ (Reuse with ACE and Frameworks ) – Schmidt & Huston, C++ Network Programming: Systematic ,AW,’03 (www.cs.wustl.edu/˜schmidt/ACE/book2/)

Vanderbilt University 302 Vanderbilt University 303 Advanced ACE Tutorial Do How to Obtain ACE Software and Technical Support

 All source code for ACE is freely available – www.cs.wustl.edu/˜schmidt/ACE. html

 Mailing lists – [email protected][email protected][email protected][email protected]

 Newsgroup – comp.soft-sys.ace

 Commercial support from Riverace and OCI – www.riverace.com – www.theaceorb.com

Vanderbilt University dacdAETutorial ACE Advanced adritUniversity Vanderbilt

  

Frameworks containing applying by appropriate challenges these resolve developers Successful application-independent largely are recurring that confront challenges software application networked of Developers ytmtcrueo software of reuse systematic – ycrnzto,pritne etc. persistence, concurrency,synchronization, demultiplexing, event control, flow handling, e.g.

evc ofiuainadiiilzto,dsrbto,error distribution, initialization, and configuration service ,

components patterns

and components ocuigRemarks Concluding ocet communication create to

r nefciewyt achieve to way effective an are frameworks oga .Schmidt C. Douglas 305