80 likes | 195 Views
E81 CSE 532S: Advanced Multi-Paradigm Software Development. Event Handling Patterns Asynchronous Completion Token. Chris Gill, Derek Chen-Becker, Frank Hunleth Department of Computer Science and Engineering Washington University, St. Louis cdgill@cse.wustl.edu.
E N D
E81 CSE 532S: Advanced Multi-Paradigm Software Development Event Handling Patterns Asynchronous Completion Token Chris Gill, Derek Chen-Becker, Frank Hunleth Department of Computer Science and Engineering Washington University, St. Louis cdgill@cse.wustl.edu
Motivation for Event Handling Patterns • Context • Programs often have limited knowledge, learn about things via events • Limitations of synchronous architectures • Latency and jitter due to blocking, deadlock potential • But, a common trade-off is less complicated programs • Common Intent for Event Handling Patterns • Reconcile event handling, concurrency, distribution design forces in canonical ways, to reduce accidental complexity
Event Handling Patterns (continued) • Asynchronous Completion Token (Design Pattern) • Passes information between asynchronous activities • Reactor (Architectural Pattern) • Asynchronous notification of ready events • De-multiplexing and dispatch mechanisms for initiation • Acceptor-Connector (Design Pattern) • Decouples connection establishment from connection use • Decouples passive role from active role during connection establishment • Often used with the reactor • Proactor (Architectural Pattern) • Asynchronous notification of completion events • Small pattern languages involving event handling • Active object + ACT (asynch computations) • Reactor + Acceptor/Connector + ACT (distributed systems)
Asynchronous Completion Token (ACT) Photo Courtesy of Derek Chen-Becker and Frank Hunleth Also Known as the “Cookie” Pattern
When Should We Use ACT? • Context • Event-driven systems • Invocation and response are asynchronous • E.g., functions dispatched using std::async, std::packaged_task, or in separate threads • Problem • 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
ACT Solution • Service (eventually) passes “cookie” to client • Examples with C++11 futures and promises • A future (eventually) holds ACT (or an exception) from which initiator can obtain the result • Client thread can block on a call to get the data or can repeatedly poll (with timeouts if you’d like) for it • A future can be packaged up with an asynchronously running service in several ways • Directly: e.g., returned by std::async • Bundled: e.g., via a std::packaged_task • As a communication channel: e.g., via std::promise • A promise can be kept or broken • If broken, an exception is thrown to client
Some ACT Representations • Data ACTs • The most straightforward variation, holds result directly • Pointer ACTs • E.g. use T* to pass event handler’s memory location • Issues: portability, inheritance/interface polymorphism • Iterator-style ACTs • Index into an array, STL iterator, etc. • Watch out for copy/move semantics, etc. • Memento/Command ACTs • Holds all necessary information for response handler upcall
Potential Liabilities • Memory (and ) leaks • Especially in client, if service doesn’t return ACT • Need to use RAII, reference counted smart pointers, etc., to ensure entries are cleaned up • Race conditions and deadlock • Global vs. local identity, expire/retry • Application remapping • Affects pointer ACTs, sequence numbers etc. • E.g., application crashes and restarts may remap pointer addresses • Security implications • Authentication, authorization, privacy