E 81 CSE 532 S Advanced MultiParadigm Software

























- Slides: 25
E 81 CSE 532 S: Advanced Multi-Paradigm Software Development Reactor Pattern Venkita Subramonian, Christopher Gill, Guandong Wang, Zhenning Hu, Zhenghui Xie Department of Computer Science and Engineering Washington University, St. Louis cdgill@cse. wustl. edu
Motivating Example: A Logging Server From http: //www. cs. wustl. edu/~schmidt/patterns-ace. html
Providing Responsive Event Handling Client 1 Port: 27098 Goal: process multiple service requests responsively Logging Server CO NN E CT Port: 30000 listen Client 2 C CT E N ON Port: 24467 accept Port: 25667 accept Port: 26545
What about Thread-per-Connection? • Multi-threading may increase code complexity • Multi-threading/processing adds overhead – Context switching (especially among processes) – Synchronization for shared data, other resources • What if we could make 1 thread responsive? – Using a top-half/bottom-half like approach – Better resource utilization by aligning threading strategy to # of available resources (like CPUs) – Also, multi-threading may not be available in all OS platforms (e. g. , small embedded ones)
Design Idea for Event Driven Server (reusable: e. g. , from ACE) Event Dispatching Logic _ le d n a h (pluggable: you write your own) Event Handling Logic Connection Acceptor st e u q re _ n o i ct e n n co Event Handlers hand le_d • Inversion of control • Hollywood principle – Don’t call us, we’ll call you (“there is no main”) ata_ read Data Reader
Reactor Pattern (Dispatching Logic) • An architectural pattern – Context: event-driven application – Concurrent reception of multiple service requests, but serial processing of each one • Dispatch service requests – Calls the appropriate event handler • Also known as – Dispatcher, Notifier, Selector (see Java NIO)
Design Forces • • Enhance scalability Maximize throughput Minimize latency Reduce effort that is needed to integrate new services into server
Solution Approach – Separates Concerns Application De-multiplexing & Dispatching Event sources Application logic Event Handlers Reactor Synchronous wait Serial Dispatching
Reactor Pattern Solution Structure a. k. a “the reactor” From http: //www. cs. wustl. edu/~schmidt/patterns-ace. html
Synchronous vs. Reactive Read Clients Server read() data select() read() Handle. Set
Serial Event Dispatching Reactor Application read() Clients select() Handle. Set read() handle_*() Event Handlers
Interactions among Participants Main Program Concrete Event Handler Synchronous Event Demultiplexer Reactor register_handler(handler, event_types) get_handle() handle_events() select() event handle_event()
Implementation • De-multiplexer/dispatcher infrastructure – Anonymous de-multiplexing of events to handlers – Assumes specific event handler hook methods • Application – Defines concrete event handlers – Handlers perform service-specific processing (“Service Handlers”)
Event Handler Interface • Determine type of dispatching target – – Objects vs. functions Can have pointers to either Command pattern can unify these Note: singular, not plural E. g. , handle_event () • Event handling dispatch interface strategy – Single-method dispatch • handle_event (handle, event_type) – Multi-method dispatch • handle_input (handle) • handle_output (handle) • handle_timeout (handle)
Reactor Interface • Handler registration/deregistration – E. g. , register_handler() deregister_handler() • Consider visitor, observer patterns • Event loop – E. g. , handle_events() Note: plural, not singular
Reactor Implementation • Reactor implementation hierarchy – Abstract base class or template concept – Concrete platform-specific implementations • Synchronous event de-multiplexing mechanism – E. g. , Wait. For. Multiple. Objects() on Win 32 – E. g. , select() or poll() on UNIX platforms • Implement a dispatch table • Complete concrete reactor implementation – Hook dispatch table into de-mux mechanism
Multiple Reactors • A single reactor instance will work in most cases – Sometimes desirable, e. g. , for handler serialization – Can use Singleton (e. g. , ACE_Reactor: : instance()) • Limits on number of OS handles may restrict this – Total available (rarely an issue in a general-purpose OS) – Max a single thread can wait for • E. g. , 64 in some Win 32 platforms – May need multiple reactors, each with its own thread – Note that handlers are not serialized across Reactor instances – treat remote/concurrent reactors similarly
Concrete Event Handlers • Implement base interface / model concept • Determine policies for handler state – Stateless, stateful, or a combination • ACTs (cookies) can help offload some of the state • I. e. , can keep state outside the handler objects, but index into a data structure, etc. using the ACT • Implement event handler functionality – I. e. , add application logic to handler methods
Logging Server++ Part 1 a. k. a. “the reactor” Steps performed when a client connects to the logging server (we’ll cover Acceptor/Connector in a subsequent lecture) From http: //www. cs. wustl. edu/~schmidt/patterns-ace. html
Logging Server++ Part 2 a. k. a. “the reactor” Steps performed by reactive logging server for each record From http: //www. cs. wustl. edu/~schmidt/patterns-ace. html
Variant: Integrated De-multiplexing of Timer and I/O Events • Timer-based and I/O-based events in same reactor • Extend reactors and event handlers – Register concrete event handlers for some time trigger • Relative vs. absolute time triggers • Periodic vs. one time invocation – Reactor calls handler’s handle_timeout() method • Can use same handler for time and event dispatching • E. g. , an alert watchdog timer for some logging handler – Various timer strategies • • E. g. , select/WFMO timeout E. g. , hardware timer interrupt E. g. , polling Pentium tick counter Key trade-offs between portability, overhead and responsiveness
Variant: Re-entrant Reactors • Event handlers re-invoke reactor->handle_events() – Result: nested event handlers – E. g. , CORBA AMI nested work_pending() • Reactor implementation must be re-entrant – Copy the handle set state onto the run-time stack – Any changes to handle set are local to that nesting level of the reactor – Use thread stack frame to record reactor’s logical “stack frame”
Variant: Thread-Safe Reactor • Synchronized reactor – Lock to synchronize access to the reactor’s internal state • Multiple threads could register/remove event handlers – Preventing self-deadlock • An event handler could register/remove other event handlers or itself – Explicitly notifying a waiting event loop thread • Notify the reactor of a change so that the wait handleset could be updated
Variant: Concurrent Event Handlers • Event handlers with their own threads – In addition to event loop thread(s) • Related concurrency patterns – the Active Object – the Leader/Followers – the Half-Sync/Half-Async
Variant: Concurrent Event De-multiplexer • Event de-multiplexer concurrent in multiple threads • E. g. , Windows Wait. For. Multiple. Objects() • Benefits – Can improve throughput significantly for some applications • Drawbacks – Need a thread-safe event de-multiplexer wrapper façade – Less portable (few platforms support this) – Implementation can become more complex