Title: COTS Challenges for Embedded Systems
1E81 CSE 532S 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_at_cse.wustl.edu
2Motivating Example A Logging Server
From http//www.cs.wustl.edu/schmidt/patterns-ace
.html
3Evolving to Concurrent Event Handling
Goal process multiple service requests
concurrently
Logging Server
Port27098
Port26545
4Where Were Starting From (Lab 0 style)
- main()
-
- bind listening port listen
- for ()
-
- new_conn_socket accept ()
-
-
- run(handler(new_conn_socket)) // write, read
-
5Logging Server Threaded Approach
- main()
-
- bind listening port listen
- for ()
-
- new_conn_socket accept ()
-
- fork a new process or thread for handler
- thread.run(handler(new_conn_socket))
-
6Problems with Threaded Approach
- 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?
- 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., embedded ones)
7Alternative Event Driven Server
(reusable from ACE) Event Dispatching Logic
(pluggable you write for your application) Event
Handling Logic
Connection Acceptor
handle_connection_request
Event Handlers
handle_data_read
Data Reader
- Inversion of control
- Hollywood principle Dont call us, well call
you (there is no main)
8Reactor 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)
9Design Forces
- Enhance scalability
- Maximize throughput
- Minimize latency
- Reduce effort that is needed to integrate new
services into server
10Solution Separation of Concerns
Application
De-multiplexing Dispatching
Application logic
Event Handlers
Event sources
Reactor
Synchronous wait
Serial Dispatching
11Reactor Pattern Structure
a.k.a the reactor
From http//www.cs.wustl.edu/schmidt/patterns-ace
.html
12Synchronous vs. Reactive Read
Clients
Server
Clients
Server
read()
select()
data
data
read()
HandleSet
HandleSet
13Serial Event Dispatching
Application
Reactor
read()
select()
Clients
Event Handlers
handle_()
read()
HandleSet
14Interactions among Participants
Synchronous Event Demultiplexer
Concrete Event Handler
Reactor
Main Program
register_handler(handler, event_types)
get_handle()
handle_events()
select()
event
handle_event()
15Implementation
- 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)
16Event Handler Interface
- Determine type of dispatching target
- Objects vs. functions
- Can have pointers to either
- Command pattern can unify these
- 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)
Note singular, not plural
17Reactor Interface
- Handler registration/deregistration
- E.g., register_handler() deregister_handler()
- Consider visitor, observer patterns
- Event loop
- E.g., handle_events()
Note plural
18Reactor Implementation
- Reactor implementation hierarchy
- Abstract base class or template concept
- Concrete platform-specific implementations
- Synchronous event de-multiplexing mechanism
- E.g., WaitForMultipleObjects() on Win32
- E.g., select() or poll() on UNIX platforms
- Implement a dispatch table
- Complete concrete reactor implementation
- Hook dispatch table into de-mux mechanism
19Multiple Reactors
- A single reactor instance will work in most cases
- Sometimes desirable, e.g., for handler
serialization - Can use Singleton (e.g., ACE_Reactorinstance())
- Limits on number of OS handles may restrict this
- Total available (rarely an issue in
general-purpose OS) - Max a single thread can wait for
- E.g., 64 in Win32
- May need multiple reactors, each with its own
thread - Note that handlers are not serialized across
Reactor instances treat remote/concurrent
reactors similarly
20Concrete 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
21Example Resolved part 1
a.k.a. the reactor
- Steps performed when a client connects to the
logging server
From http//www.cs.wustl.edu/schmidt/patterns-ace
.html
22Example Resolved Part 2
a.k.a. the reactor
- Steps performed by reactive logging server to for
each record
From http//www.cs.wustl.edu/schmidt/patterns-ace
.html
23Variant 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 handlers 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
24Variant Re-entrant Reactors
- Event handlers re-invoke
- reactor-gthandle_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 reactors
logical stack frame
25Variant Thread-Safe Reactor
- Synchronized reactor
- Lock to synchronize access to the reactors
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
handle-set could be updated - Much more on this later in the semester
- I.e., when we discuss synchronization, concurrency
26Variant 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
- More on this too when we get to concurrency
27Variant Concurrent Event De-multiplexer
- Event de-multiplexer concurrent in multiple
threads - E.g., WaitForMultipleObjects()
- Benefits
- Can improve throughput significantly for some
applications - Drawbacks
- Need a thread-safe event de-multiplexer wrapper
façade - Less portable (fewer platforms support this)
- Implementation can become more complex
28Questions for Discussion
- What key issues do event-driven applications
face? - What problem does the Reactor pattern address?
- What are Reactors benefits and limitations?
- How is Reactors solution structured? Why?
- What are several event handling dispatch
interface strategies?