c++ network programming mastering complexity with ace & patterns

49
C++ Network C++ Network Programming Programming Mastering Complexity with Mastering Complexity with ACE & Patterns ACE & Patterns Dr. Douglas C. Schmidt [email protected] www.cs.wustl.edu/~schmidt/tutorials- ace.html Professor of EECS Vanderbilt University Nashville, Tennessee

Upload: bina

Post on 15-Jan-2016

45 views

Category:

Documents


0 download

DESCRIPTION

Dr. Douglas C. Schmidt [email protected] www.cs.wustl.edu/~schmidt/tutorials-ace.html. C++ Network Programming Mastering Complexity with ACE & Patterns. Professor of EECS Vanderbilt University Nashville, Tennessee. Introduction (1/3). ACE Adaptive Communication Environment - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: C++ Network Programming Mastering Complexity with  ACE & Patterns

C++ Network C++ Network ProgrammingProgramming

Mastering Complexity with Mastering Complexity with ACE & PatternsACE & Patterns

Dr. Douglas C. [email protected]

www.cs.wustl.edu/~schmidt/tutorials-ace.html

Professor of EECS Vanderbilt University Nashville, Tennessee

Page 2: C++ Network Programming Mastering Complexity with  ACE & Patterns

2

Introduction (1/3)

ACE Adaptive Communication Environment

The key contribution: Creation of uniform models which capture a broad spectrum of services Easier to do on a specific domain Easier to do when dealing with small building blocks

• For instance: The scoped-locking constructs

The motivation: Development of a concurrent server program (socket-based)

Page 3: C++ Network Programming Mastering Complexity with  ACE & Patterns

3

Comments (2/3)

Huge scope General overview Specific inspection of certain parts Our goal: A brief introduction (Slides per minute – High rate)

API Specifications (Doxygen) http://www.dre.vanderbilt.edu/Doxygen/Current/html/a

ce/hierarchy.html

Page 4: C++ Network Programming Mastering Complexity with  ACE & Patterns

4

Introduction (3/3)

ACE is somewhat outdated does not use exceptions

C++ oriented Some of the ideas seem trivial to Java programmers Some of the ideas cannot be supported on Java Thru ACE we can understand the design rationale Useful for C++ developers Useful for any developer of concurrent/distributed

programs

Example: Java’s thread class is a realization of ACE’s Active Objects pattern (see next slide)

Page 5: C++ Network Programming Mastering Complexity with  ACE & Patterns

5

Active Object: intent

Decouples method execution from method invocation and simplifies synchronized

access to shared resources by concurrent threads

Decouples method execution from method invocation and simplifies synchronized

access to shared resources by concurrent threads

Page 6: C++ Network Programming Mastering Complexity with  ACE & Patterns

6

Terminology

Framework

Toolkit

Patterns

Page 7: C++ Network Programming Mastering Complexity with  ACE & Patterns

7

Motivation: Challenges of Networked ApplicationsObservation• Building robust, efficient, & extensible concurrent & networked applications is hard• e.g., we must address many complex topics that are less problematic for non-concurrent, stand-alone applications

Accidental Complexities• Low-level APIs•Poor debugging tools•Algorithmic decomposition•Continuous re-invention/discovery of core concepts & components

Inherent Complexities• Latency•Reliability•Load balancing•Causal ordering•Scheduling & synchronization•Deadlock

Complexities in networked applications

Page 8: C++ Network Programming Mastering Complexity with  ACE & Patterns

8

Event Handling & IPCService Access & Control

Concurrency Synchronization

Key Capabilities Provided by ACE

Page 9: C++ Network Programming Mastering Complexity with  ACE & Patterns

9

The Layered Architecture of ACEFeatures•Open-source•200,000+ lines of C++

•40+ person-years of effort

•Ported to many OS platforms

www.cs.wustl.edu/~schmidt/ACE.html

Page 10: C++ Network Programming Mastering Complexity with  ACE & Patterns

10

The Pattern Language for ACEPattern Benefits• Preserve crucial design information used by applications & middleware frameworks & components

• Facilitate reuse of proven software designs & architectures

• Guide design choices for application developers

Page 11: C++ Network Programming Mastering Complexity with  ACE & Patterns

11

The Frameworks in ACE

ACE Framework Inversion of Control

Reactor & Proactor Calls back to application-supplied event handlers to perform processing when events occur synchronously & asynchronously

Service Configurator Calls back to application-supplied service objects to initialize, suspend, resume, & finalize them

Task Calls back to an application-supplied hook method to perform processing in one or more threads of control

Acceptor-Connector Calls back to service handlers to initialize them after they are connected

Streams Calls back to initialize & finalize tasks when they are pushed & popped from a stream

Page 12: C++ Network Programming Mastering Complexity with  ACE & Patterns

12

Example: Applying ACE in Real-time Avionics

Key System Characteristics• Deterministic & statistical deadlines

• ~20 Hz• Low latency & jitter

• ~250 usecs• Periodic & aperiodic processing• Complex dependencies• Continuous platform upgrades

• Test flown at China Lake NAWS by Boeing OSAT II ‘98, funded by OS-JTF• www.cs.wustl.edu/~schmidt/TAO-boeing.html

• Also used on SOFIA project by Raytheon• sofia.arc.nasa.gov

• First use of RT CORBA in mission computing• Drove Real-time CORBA standardization

• Test flown at China Lake NAWS by Boeing OSAT II ‘98, funded by OS-JTF• www.cs.wustl.edu/~schmidt/TAO-boeing.html

• Also used on SOFIA project by Raytheon• sofia.arc.nasa.gov

• First use of RT CORBA in mission computing• Drove Real-time CORBA standardization

Key Results

Goals• Apply COTS & open systems to mission-critical real-time avionics

Page 13: C++ Network Programming Mastering Complexity with  ACE & Patterns

13

Limitations with the Socket APIs (1/2)

Poorly structured, non-uniform, & non-portable

• API is linear rather than hierarchical

• i.e., the API is not structured according to the different phases of connection lifecycle management and the roles played by the participants

• No consistency among the names

• Non-portable & error-prone

• Function names: read() & write() used for any I/O handle on Unix but Windows needs ReadFile() & WriteFile()

• Function semantics: different behavior of same function on different OS e.g., accept () can take NULL client address parameter on Unix/Windows, but will crash on some operating systems, such as VxWorks

• Socket handle representations: different platforms represent sockets differently e.g., Unix uses unsigned integers whereas Windows uses pointers

• Header files: Different platforms use different names for header files for the socket API

Page 14: C++ Network Programming Mastering Complexity with  ACE & Patterns

14

Limitations with the Socket APIs (2/2)Lack of type safety• I/O handles are not amenable to strong type checking at compile time

• e.g., no type distinction between a socket used for passive listening & a socket used for data transfer

Steep learning curve due to complex semantics• Multiple protocol families & address families

• Options for infrequently used features such as broadcasting, async I/O, non blocking I/O, urgent data delivery

• Communication optimizations such as scatter-read & gather-write

• Different communication and connection roles, such as active & passive connection establishment, & data transfer

Too many low-level details• Forgetting to use the network byte order before data transfer

• Possibility of missing a function, such as listen()

• Possibility of mismatch between protocol & address families

• Forgetting to initialize underlying C structures e.g., sockaddr

• Using a wrong socket for a given role

Page 15: C++ Network Programming Mastering Complexity with  ACE & Patterns

15

1 #include <sys/types.h>

2 #include <sys/socket.h>

3

4 const int PORT_NUM = 10000;

5

6 int echo_server ()

7 {

8 struct sockaddr_in addr;

9 int addr_len;

10 char buf[BUFSIZ];

11 int n_handle;

12 // Create the local endpoint.

Example of Socket API Limitations (1/3)

Forgot to initialize to sizeof (sockaddr_in)

Use of non-portable handle type

Possible differences in header file names

Page 16: C++ Network Programming Mastering Complexity with  ACE & Patterns

16

13 int s_handle = socket (PF_UNIX, SOCK_DGRAM, 0);

14 if (s_handle == -1) return -1;

15

16 // Set up address information where server listens.

17 addr.sin_family = AF_INET;

18 addr.sin_port = PORT_NUM;

19 addr.sin_addr.addr = INADDR_ANY;

20

21 if (bind (s_handle, (struct sockaddr *) &addr,

22 sizeof addr) == -1)

23 return -1;

24

Use of non-portable return value

Unused structure members not zeroed out

Protocol and address family mismatch

Wrong byte order

Missed call to listen()

Example of Socket API Limitations (2/3)

Page 17: C++ Network Programming Mastering Complexity with  ACE & Patterns

17

25 // Create a new communication endpoint.

26 if (n_handle = accept (s_handle, (struct sockaddr *) &addr,

27 &addr_len) != -1) {

28 int n;

29 while ((n = read (s_handle, buf, sizeof buf)) > 0)

30 write (n_handle, buf, n);

31

32 close (n_handle);

33 }

34 return 0;

35 }

SOCK_DGRAM handle illegal here

Reading from wrong handle

No guarantee that “n” bytes will be written

Example of Socket API Limitations (3/3)

Page 18: C++ Network Programming Mastering Complexity with  ACE & Patterns

18

The Wrapper Facade Pattern (1/2)

Problem•The diversity of hardware & operating systems makes it hard to build portable & robust networked application software

•Programming directly to low-level OS APIs is tedious, error-prone, & non-portable

Context •Networked applications must manage a variety of OS services, including processes, threads, socket connections, virtual memory, & files

•OS platforms provide low-level APIs written in C to access these services

Win2K Linux LynxOS

Solaris VxWorks

Applications

Page 19: C++ Network Programming Mastering Complexity with  ACE & Patterns

19

The Wrapper Facade Pattern (2/2)

This pattern encapsulates data & functions provided by existing non-OO APIs within more concise, robust, portable, maintainable, & cohesive OO class interfaces

: Application

method()

: WrapperFacade

: APIFunctionA

functionA()

: APIFunctionB

functionB()

Applicationcalls methods

callsAPI FunctionA()

callsAPI FunctionB()

calls API FunctionC()

void methodN(){functionA();

}

void method1(){functionA();

}functionB();

Wrapper Facade

data

method1()…methodN()

Solution•Apply the Wrapper Facade design pattern to avoid accessing low-level operating system APIs directly

Solution•Apply the Wrapper Facade design pattern to avoid accessing low-level operating system APIs directly

Page 20: C++ Network Programming Mastering Complexity with  ACE & Patterns

20

ACE Socket Wrapper Facade Classes

These classes are designed in accordance

with the Wrapper Facade design pattern

ACE defines a set of C++ classes that address the limitations with the Socket API•Enhance type-safety•Ensure portability•Simplify common use cases

•Building blocks for higher-level abstractions

Page 21: C++ Network Programming Mastering Complexity with  ACE & Patterns

21

Roles in the ACE Socket Wrapper Facade

•The active connection role (ACE_SOCK_Connector) is played by a peer application that initiates a connection to a remote peer

•The passive connection role (ACE_SOCK_Acceptor) is played by a peer application that accepts a connection from a remote peer &

•The communication role (ACE_SOCK_Stream) is played by both peer applications to exchange data after they are connected

Page 22: C++ Network Programming Mastering Complexity with  ACE & Patterns

22

Connector/Acceptor: intent

Decouples active/passive connection establishment from the service performed

once the connection is established

Decouples active/passive connection establishment from the service performed

once the connection is established

Page 23: C++ Network Programming Mastering Complexity with  ACE & Patterns

23

The ACE_SOCK_Connector ClassMotivation

•There is a confusing asymmetry in the Socket API between (1) connection roles & (2) socket modes

•e.g., an application may accidentally call recv() or send() on a data-mode socket handle before it's connected

•This problem can't be detected until run time since C socket handles are weakly-typed

int buggy_echo_client (u_short port_num, const char *s) { int handle = socket (PF_UNIX, SOCK_DGRAM, 0); write (handle, s, strlen (s) + 1);

sockaddr_in s_addr; memset (&s_addr, 0, sizeof s_addr); s_addr.sin_family = AF_INET; s_addr.sin_port = htons (port_num); connect (handle, (sockaddr *) &s_addr, sizeof s_addr);}

Operations called in wrong order

Page 24: C++ Network Programming Mastering Complexity with  ACE & Patterns

24

The ACE_SOCK_Connector Class

Class Capabilities

•ACE_SOCK_Connector is factory that establishes a new endpoint of communication actively & provides capabilities to

•Initiate a connection with a peer acceptor & then to initialize an ACE_SOCK_Stream object after the connection is established

•Initiate connections in either a blocking, nonblocking, or timed manner

Page 25: C++ Network Programming Mastering Complexity with  ACE & Patterns

25

int main (int argc, char *argv[]) { const char *server_hostname = argv[1];

ACE_SOCK_Connector connector; ACE_SOCK_Stream peer; ACE_INET_Addr peer_addr; if (peer_addr.set (80, server_hostname) == -1) return 1; else if (connector.connect (peer, peer_addr) == -1) return 1;

Using the ACE_SOCK_Connector

• Block until connection established or connection request failure

• Instantiate the connector, data transfer, & address objects

•This example shows how the ACE_SOCK_Connector can be used to connect a client application to a Web server

Page 26: C++ Network Programming Mastering Complexity with  ACE & Patterns

26

The ACE_SOCK_Acceptor Class (1/2)

Motivation

•The C functions in the Socket API are weakly typed, which makes it easy to apply them incorrectly in ways that can’t be detected until run-time

•The ACE_SOCK_Acceptor class ensures type errors are detected at compile-time

int buggy_echo_server (u_short port_num) { sockaddr_in s_addr; int acceptor = socket (PF_UNIX, SOCK_DGRAM, 0); s_addr.sin_family = AF_INET; s_addr.sin_port = port_num; s_addr.sin_addr.s_addr = INADDR_ANY; bind (acceptor, (sockaddr *) &s_addr, sizeof s_addr); int handle = accept (acceptor, 0, 0); for (;;) { char buf[BUFSIZ]; ssize_t n = read (acceptor, buf, sizeof buf); if (n <= 0) break; write (handle, buf, n); }}

Reading from wrong handle

Page 27: C++ Network Programming Mastering Complexity with  ACE & Patterns

27

Class Capabilities

•This class is a factory that establishes a new endpoint of communication passively & provides the following capabilities:

The ACE_SOCK_Acceptor Class (2/2)

•It accepts a connection from a peer connector & then initializes an ACE_SOCK_Stream object after the connection is established

•Connections can be accepted in either a blocking, nonblocking, or timed manner

•C++ traits are used to support generic programming techniques that enable the wholesale replacement of functionality via C++ parameterized types

Page 28: C++ Network Programming Mastering Complexity with  ACE & Patterns

28

Using the ACE_SOCK_Acceptor

extern char *get_url_pathname (ACE_SOCK_Stream *);int main (){ ACE_INET_Addr server_addr; ACE_SOCK_Acceptor acceptor; ACE_SOCK_Stream peer;

if (server_addr.set (80) == -1) return 1; if (acceptor.open (server_addr) == -1) return 1;

for (;;) { if (acceptor.accept (peer) == -1) return 1; peer.disable (ACE_NONBLOCK); // Ensure blocking <send_n>.

ACE_Auto_Array_Ptr<char *> pathname (get_url_pathname (peer)); ACE_Mem_Map mapped_file (pathname.get ());

if (peer.send_n (mapped_file.addr (), mapped_file.size ()) == -1) return 1; peer.close (); }

return acceptor.close () == -1 ? 1 : 0;}

• Instantiate the acceptor, data transfer, & address objects

• Initialize a passive mode endpoint to listen for connections on port 80

• Accept a new connection

• Send the requested data

• Close the connection to the sender

• Stop receiving any connections

•This example shows how an ACE_SOCK_Acceptor & ACE_SOCK_Stream can be used to accept connections & send/receive data to/from a web client

Page 29: C++ Network Programming Mastering Complexity with  ACE & Patterns

29

Reactor: intent

Decouples event demultiplexing and event handler dispatching from application

services performed in response to events

Decouples event demultiplexing and event handler dispatching from application

services performed in response to events

Page 30: C++ Network Programming Mastering Complexity with  ACE & Patterns

30

*

Reactor

Reactor

handleEvents()registerHandler()removeHandler()

IEventHandler

handleEvent()getHandle()

ConcreteHandler

handleEvent()getHandle()Iterator handles = select();

while(handles.hasNext()) { Handle h = handles.next(); IEventHandler eh = table[h]; eh.handleEvent();}

Page 31: C++ Network Programming Mastering Complexity with  ACE & Patterns

31

Proactor: intent

Demultiplexes and dispatches service requests that are triggered by the completion

of asynchronous events.

Demultiplexes and dispatches service requests that are triggered by the completion

of asynchronous events.

Page 32: C++ Network Programming Mastering Complexity with  ACE & Patterns

32

<<create>>

*

Proactor

Proactorread()write()

IEventHandler

handleEvent()

ConcreteHandler

handleEvent()

AsyncIODevice

read()write()

CompletionDispatcher

completed()<<implements>>

Page 33: C++ Network Programming Mastering Complexity with  ACE & Patterns

33

Half-Sync/Half-Async: intent

Decouples synchronous I/O from asynchronous I/O in a system to simplify concurrent programming effort without

degrading execution efficiency

Decouples synchronous I/O from asynchronous I/O in a system to simplify concurrent programming effort without

degrading execution efficiency

Page 34: C++ Network Programming Mastering Complexity with  ACE & Patterns

34

The Half-Sync/Half-Async Pattern

This pattern yields two primary benefits:

1.Threads can be mapped to separate CPUs to scale up server performance via multi-processing

2.Each thread blocks independently, which prevents a flow-controlled connection from degrading the QoS that other clients receive

SyncServiceLayer

AsyncService Layer

QueueingLayer

<<read/write>><<read/write>>

<<read/write>>

<<dequeue/enqueue>> <<interrupt>>

Sync Service 1 Sync Service 2 Sync Service 3

ExternalEvent Source

Queue

Async Service

Page 35: C++ Network Programming Mastering Complexity with  ACE & Patterns

35

Half-Sync/Half-Async Pattern Dynamics

•This pattern defines two service processing layers—one async & one sync—along with a queueing layer that allows services to exchange messages between the two layers

: External EventSource

: Async Service : Queue

notification

read()

enqueue()

message

: Sync Service

work()

message

read()

message

work()

notification

•The pattern allows sync services (such as processing log records from different clients) to run concurrently, relative both to each other & to async/reactive services (such as event demultiplexing)

Page 36: C++ Network Programming Mastering Complexity with  ACE & Patterns

36

Drawbacks with Half-Sync/Half-Async

Problems:•Overhead when crossing inter-layer boundary•Lack of support for Async. operations in the sync. Layer•Solution: Leader/Followers pattern

<<get>><<get>>

<<get>>

<<put>>

Worker Thread 1

Worker Thread 3

Event source

Request Queue

acceptorhandlers

Worker Thread 2

Page 37: C++ Network Programming Mastering Complexity with  ACE & Patterns

37

The ACE_TSS Class (2/2)

Class Capabilities•This class implements the Thread-Specific Storage pattern, which encapsulates & enhances the native OS Thread-Specific Storage (TSS) APIs to provide the following capabilities:

•It supports data that are ``physically'' thread specific, that is, private to a thread, but allows them to be accessed as though they were ``logically'' global to a program

•It uses the C++ delegation operator: operator->()

•It encapsulates the management of the keys associated with TSS objects

•For platforms that lack adequate TSS support natively (such as VxWorks) ACE_TSS emulates TSS efficiently

Page 38: C++ Network Programming Mastering Complexity with  ACE & Patterns

38

The Thread-Specific Storage Pattern• The Thread-Specific Storage pattern allows multiple threads to use one ‘logically global’ access point to retrieve an object that is local to a thread, without incurring locking overhead on each object access

key 1

key n

thread m

Thread-SpecificObjectaccesses

manages

[k,t]

thread 1

Page 39: C++ Network Programming Mastering Complexity with  ACE & Patterns

39

Using ACE_TSS (1/3)

template <class TYPE> TYPE *ACE_TSS<TYPE>::operator-> () { if (once_ == 0) { // Ensure that we're serialized. ACE_GUARD_RETURN(ACE_Thread_Mutex, guard, keylock_, 0);

if (once_ == 0) { ACE_OS::thr_keycreate(&key_); once_ = 1; } }

• In this implementation, each thread gets its own request count that resides in thread-specific storage to alleviate race conditions on the request count without requiring a mutex

• This example illustrates how to implement & apply ACE_TSS to our thread-per-connection logging server

We used the double-checked locking optimization pattern here

Page 40: C++ Network Programming Mastering Complexity with  ACE & Patterns

40

Using ACE_TSS (2/3)

TYPE *ts_obj = 0;

// Initialize <ts_obj> from thread-specific storage. ACE_OS::thr_getspecific (key_, (void **) &ts_obj);

// Check if this method's been called in this thread. if (ts_obj == 0) { // Allocate memory off the heap and store it in a pointer. ts_obj = new TYPE;

// Store the dynamically allocated pointer in TSS. ACE_OS::thr_setspecific (key_, ts_obj); } return ts_obj;}

Page 41: C++ Network Programming Mastering Complexity with  ACE & Patterns

41

Using ACE_TSS (3/3)class Request_Count {public: Request_Count (): count_ (0) {} void increment () { ++count_; } int value () const { return count_; }

private: int count_;};

static ACE_TSS<Request_Count> request_count;

virtual int handle_data (ACE_SOCK_Stream *) { while (logging_handler_.log_record () != -1) // Keep track of number of requests. request_count->increment ();

ACE_DEBUG ((LM_DEBUG, "request_count = %d\n", request_count->value ())); }

This call increments variable in thread-specific storage

Page 42: C++ Network Programming Mastering Complexity with  ACE & Patterns

42

Reminder: Using Window’s critical-section

CRITICAL_SECTION cs; // Global variable

void main() { if(!InitializeCriticalSection(&cs)) return; // Create threads...

DeleteCriticalSection(&cs)}

DWORD WINAPI ThreadProc(LPVOID lpParameter){ EnterCriticalSection(&cs);

// Access the shared resource.

LeaveCriticalSection(&cs);}

•Now, let’s think about a CriticalSection class…

•How should its interface look like?

Page 43: C++ Network Programming Mastering Complexity with  ACE & Patterns

43

The ACE Synchronization Wrapper Facades

•Different operating systems provide different synchronization mechanisms with different semantics using different APIs•Some of these APIs conform to international standards, such as Pthreads•Other APIs conform to de facto standards, such as Win32

•Below we describe the following ACE classes that networked applications can use to synchronize threads and/or processes portably

Page 44: C++ Network Programming Mastering Complexity with  ACE & Patterns

44

The ACE_Lock* Pseudo-Class

•The ACE mutex, readers/writer, semaphore, & file lock mechanisms all support the ACE_LOCK* interface shown below

•ACE_LOCK* is a “pseudo-class,” i.e., it's not a real C++ class in ACE

•We use it to illustrate the uniformity of the signatures supported by many of the ACE synchronization classes

•e.g., ACE_Thread_Mutex, ACE_Process_Mutex, & ACE_Thread_Semaphore

Page 45: C++ Network Programming Mastering Complexity with  ACE & Patterns

45

The ACE_Guard ClassesMotivation

•When acquiring and releasing locks explicitly, it can be hard to ensure that all paths through the code release the lock, especially when C++ exceptions are thrown

•ACE provides the ACE_Guard class & its associated subclasses to help assure that locks are acquired & released properly

Class Capabilities•These classes implement the Scoped Locking idiom, which leverages the semantics of C++ class constructors & destructors to ensure a lock is acquired & released automatically upon entry to and exit from a block of C++ code, respectively

Page 46: C++ Network Programming Mastering Complexity with  ACE & Patterns

46

The Scoped Locking IdiomMotivation•Code that shouldn’t execute concurrently must be protected by some type of lock that is acquired/released when control enters/leaves a critical section

•If programmers must acquire & release locks explicitly, it is hard to ensure that the locks are released in all paths through the code

•e.g., in C++ control can leave a scope due to a return, break, continue, or goto statement, as well as from an unhandled exception being propagated out of the scopevoid method () { lock_.acquire (); // The implementation may return prematurely… lock_.release (); } •The Scoped Locking idiom defines a guard class whose constructor

automatically acquires a lock when control enters a scope & whose destructor automatically releases the lock when control leaves the scope void method () { ACE_Guard <ACE_Thread_Mutex> guard (lock_); // The lock is released when the method returns}

Page 47: C++ Network Programming Mastering Complexity with  ACE & Patterns

47

Implementing Scoped Locking in ACEtemplate <class LOCK> class ACE_Guard {public: // Store a pointer to the lock and acquire the lock. ACE_Guard (LOCK &lock) : lock_ (&lock) { lock_->acquire (); }

// Release the lock when the guard goes out of scope, ~ACE_Guard () { lock_->release (); }

// Other methods omitted…

private: // Pointer to the lock we’re managing. LOCK *lock_;};

Generic ACE_Guard Wrapper Facade

•ACE_Write_Guard & ACE_Read_Guard acquire write locks & read locks, respectively

•Instances of the ACE_Guard<T> classes can be allocated on the run-time stack to acquire & release locks in method or block scopes that define critical sections

Page 48: C++ Network Programming Mastering Complexity with  ACE & Patterns

48

ACE Condition Variable Classes (1/2)Motivation

•Condition variables allow threads to coordinate & schedule their processing efficiently

•Condition variables are more appropriate than mutexes or semaphores when complex condition expressions or scheduling behaviors are needed

•e.g., condition variables are often used to implement synchronized message queues that provide “producer/consumer” communication to pass messages between threads

usesuses 2

Request Queue

put()get()

ACE_Thread_Mutex

acquire()release()

Producer Thread

ACE_Thread_Condition

wait()signal()broadcast()

ConsumerThread

<<put>> <<get>>

Page 49: C++ Network Programming Mastering Complexity with  ACE & Patterns

49

Class Capabilities

•The ACE_Condition_Thread_Mutex uses the Wrapper Façade pattern to guide its encapsulation of process-scoped condition variable semantics

•The ACE_Null_Condition is a zero-cost class whose interface conforms to the ACE_Condition_Thread_Mutex

ACE Condition Variable Classes (2/2)