E81 CSE 532S: Advanced Multi-Paradigm Software Development
Event Handling Pattern Languages
Chris Gill
Department of Computer Science and Engineering
Washington University, St. Louis
cdgill@cse.wustl.edu
Thanks to Carol Brickman for raising the UDP
and simulation server issues covered here
Thanks to Doug Schmidt for timer expiration
example (ace-users post)
What is a Pattern Language?
• A narrative that composes patterns
– Not just a catalog of the patterns
– Reconciles design forces among patterns
– Provides an ordered outline for design steps
• Not necessarily a procedure (details may be unspecified)
• A generator for a complete design
– Patterns may leave consequences
– Other patterns can resolve them
– Generative designs resolve all forces
• Internal tensions don’t “pull design apart”
When Should We Use a Design Pattern?
• Two forms of guidance are given by (good) patterns
– The pattern’s context
• States conditions under which the pattern is relevant
• May state conditions under which the pattern doesn’t apply
– The design forces that the pattern resolves
• How the design will evolve when that pattern is applied
• We can compare these to the current design setting
– I.e., is the pattern even appropriate? (context)
– I.e., is this the pattern to apply next? (design forces)
• Consequences of one pattern may produce context,
design forces that affect pattern choices made later
Event Handling Patterns (Review)
• (Pattern Language Level) Context
– Programs often have limited knowledge, learn about things via events
• (Pattern Language Level) Intent
– Reconcile event handling design forces with concurrency & distribution
• Uses of Event Handling Pattern Languages
– Time triggered systems
– Distributed (networked) systems
– Proactive systems
– Reactive systems
• Design patterns
– Asynchronous Completion Token
– Acceptor-Connector
• Architectural patterns
– Reactor
– Proactor
• Pattern languages for (distributed) event handling
Event Handling Patterns (review, continued)
• ACT
– Allows de-multiplexing of completion handling
• Reactor
– Synchronous notification of asynchronous events
– De-multiplexing and dispatch mechanisms
• Proactor
– Asynchronous notification of completion events
• Acceptor-Connector
– Decouples connection establishment from its use
– (Often) used with the reactor
When Should We Use ACT?
• (Pattern Level) Context
– Event-driven systems
– Invocation/response are (could be) asynchronous
• Design forces
– Completion events must be de-multiplexed
– Service does not know what a client needs to be
able to de-multiplex responses
– Communication overhead must be minimal
– De-multiplexing should be efficient
– Need to design appropriate “cookie format”
Reactor Context
• An architectural pattern
– Context is system event architecture
• Synchronous/asynchronous events
• Event multiplexing/de-multiplexing
– In contrast ACT is a design pattern
• Context is smaller: application/middleware layer
• De-multiplex service requests
– Decide which handler should be called
• Dispatch service requests
– Call the appropriate handler
• Also known as
– Dispatcher, Notifier
Reactor Design Forces
• Enhance scalability
• Maximize throughput
• Minimize latency
• Reduce effort to integrate new services
• Reduce concurrency complexity
– E.g., instruction vs. handler interleaving
• Handle multiple channels
– E.g., sockets
• May not scale as well as proactive approach
• May cause undue handler blocking times
Proactor Context
• Asynchronous operations used by application
• Application thread should not block
• Application needs to know when an operation
completes
• Decoupling application/infrastructure is useful
• Reactive performance is insufficient
• Multi-threading incurs excessive overhead or
programming model complexity
Proactor Design Forces
• Separation of application from infrastructure
• Flexibility to add new application components
• Performance benefits of concurrency
– Reactive has coarse interleaving (handlers)
– Multi-threaded has fine interleaving (instructions)
• Complexity of multi-threading
– Concurrency hazards: deadlock, race conditions
– Coordination of multiple threads
• Performance issues with multi-threading
– Synchronization re-introduces coarser granularity
– Overhead of thread context switches
– Sharing resources across multiple threads
• Limitations on mechanism availability/portability
Acceptor/Connector Context
• Networked system or application
– I.e., communication between remote hosts
• Connection-oriented protocols
– E.g., TCP/IP
• Peer services
– I.e., client and server roles
• Connected via endpoints
– E.g., IP ports
Acceptor/Connector Design Forces
• Flexibility and performance loss if we tightly couple
– Configuration establishment/initialization by application
– Application logic for service processing
– Protocol-specific details
• Need to resolve four key design forces
– Changing connection roles to vary application behavior
– Adding new services, implementations, and protocols
– Connection establishment/initialization vs. protocols/services
• Protocols and services more likely to be changed or enhanced
• Should not be tightly coupled with connection management
– Reduce connection establishment latency
• Via advanced OS features and new protocols (e.g., SCTP)
• May be more expensive than other approaches
– E.g., Singleton access in same process address space
Pattern Language I: Logging Server
• Want to collect and record system events
– For example, printer out of paper, new clients, etc.
• Events from many clients to a central server
• Want to add event-specific processing
– And add new processing flexibly
From http://www.cs.wustl.edu/~schmidt/patterns-ace.html
Pattern Language I: Logging Server
Reactor
Handler
• Design forces
– Server needs to add/remove logging features dynamically
– Logging actions are short lived, and event driven
• Solution
– Apply Reactor to manage registration and dispatching
• Consequences
– Need a way to match events to particular logging actions
Pattern Language I: Logging Server
ACT
ACT
Reactor
Handler
ACT
• Design forces
– Need a way to match events to particular logging actions
– Clients can specify what events they will report
• Solution
– Apply ACT to identify the kinds of handlers to create
• Consequences
– Need to define how ACT is handled
– Need to create correct handlers for the ACT
Pattern Language I: Logging Server
ACT
Accepto
ACT r
Reactor
Handler
ACT
Connecto
r
• Design forces
– Need to define how ACT is handled
– Need to create correct handlers for the ACT
– Clients (dynamic) need to tell server when they join
• Solution
– Apply Acceptor/Connector with server taking passive role and clients
taking active role in connection establishment
• Consequences
– Reactive logging with dynamic connection establishment and dynamic
identification/creation of events/handlers
Pattern Language I: Logging Server
• One subtle design/implementation issue remains
– How to pass ACT to acceptor so it knows what kind of
handler to create?
• Could use the new socket for additional handshaking
between the connector and the acceptor
– Like in lab 0 where client and server exchanged names
– However, this lengthens the time spent in acceptor upcall
• Another option
– Acceptor binds a separate UDP port
– Client connectors can “mail” it ACTs via UDP
– Need to add retry, etc. above UDP level (see Stevens UNP)
() Pattern Language II: Simulation Server
• Scripted simulation server (physics, avionics, etc.)
– Each simulation has (possibly distinct) set of clients
– Clients may observe, provide control actions, inputs, etc.
– Similar to previous pattern language, except last pattern
Pattern Language II: Simulation Server
Listening port Listening port
Server Client 2
Client 1
• Design forces
– Clients are static and passive (known set of simulation components)
– Server is dynamic and active (runs different simulation scenarios)
– Server (dynamic) needs to tell clients when to start, reset, run, etc.
• Solution
– Apply Acceptor/Connector with clients taking passive role and server
taking active role in connection establishment (reverse of lab 1 roles)
• Consequences
– Similarly reactive simulation but with dynamic connection establishment
triggered by server
Pattern Language II: Simulation Server
data Timer ACT
structure Handler
Code that
schedules
Timer Timer Queue
• Design forces
– Simulation client or server logic may need to respond to passage of time
– Reactor can dispatch handlers when timers expire
– How can application pass data to handler, and vice versa?
• Solution
– Apply ACT pattern (pass address: schedule call’s timer_act parameter);
• Consequences
– Arbitrary data structure can pass between application and handler
– Creates a critical section (access to data structure) if multi-threaded
() Pattern Language III: Data Streams
• Want to coordinate groups of different data streams
– For example, display multiple streams consistently locally
• Water temperatures and flow rates across a river basin
• Video frames from multiple cameras tracking an animal
• Poker hands dealt from multiple games at once
– Also, may pass-through streams to other endsystems
• Apply ACT to identify each stream’s source, id, etc.
– Lets end-user switch among streams transiting endsystem
– Lets end-user buffer/write related messages together
• Need high throughput for content rich data streams
– Apply Proactor to manage registration and dispatching
• Need to update streaming topology dynamically
– Apply Acceptor/Connector to set up remote connections
– May involve both active and passive roles on an endsystem
Concluding Remarks
• A single pattern is often insufficient
– May leave unresolved design consequences
• Understand how patterns fit together
– How one may reconcile forces from another …
– … and/or leave/introduce un-reconciled forces
• Successful pattern languages in a context can
generate complete designs
– Weave patterns together coherently
• There are many more pattern languages than
patterns (cardinality argument)