Asynchronous Completion Token - Ingeniørhøjskolen i Århus
Asynchronous Completion Token - Ingeniørhøjskolen i Århus
Asynchronous Completion Token - Ingeniørhøjskolen i Århus
Create successful ePaper yourself
Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.
Distributed Real-Time<br />
Systems<br />
(TI-DRTS)<br />
POSA2: <strong>Asynchronous</strong> <strong>Completion</strong><br />
<strong>Token</strong> Design Pattern<br />
Version: 21-09-2009
Abstract<br />
The <strong>Asynchronous</strong> <strong>Completion</strong> <strong>Token</strong> (ACT)<br />
design pattern allows an application to<br />
demultiplex and process efficiently the responses<br />
of asynchronous operations it invokes on services<br />
© <strong>Ingeniørhøjskolen</strong> i <strong>Århus</strong><br />
Slide 2
Context<br />
• An event-driven system in which<br />
applications invoke operations<br />
asynchronously on services and<br />
subsequently process the associated<br />
service completion event responses<br />
© <strong>Ingeniørhøjskolen</strong> i <strong>Århus</strong><br />
Slide 3
Problem<br />
• A client application invokes one or more<br />
services asynchronously<br />
• Each service returns its response via a<br />
completion event<br />
• The client application must demultiplex<br />
this event to the appropriate handler (as<br />
fast as possible)<br />
© <strong>Ingeniørhøjskolen</strong> i <strong>Århus</strong><br />
Slide 4
Solution<br />
• Together with each asynchronous operation<br />
invocation:<br />
– transmit information that identifies how the initiator<br />
should process the service’s response<br />
• create an <strong>Asynchronous</strong> <strong>Completion</strong> <strong>Token</strong> (ACT)<br />
• the ACT is passed to the service, which hold it – but does<br />
not modify it<br />
• Return this information to the initiator when the<br />
operation finishes<br />
• The initiator uses the ACT to identify the<br />
completion handler<br />
© <strong>Ingeniørhøjskolen</strong> i <strong>Århus</strong><br />
Slide 5
ACT Structure<br />
«demultiplexes»<br />
1..*<br />
<strong>Completion</strong><br />
Handler<br />
+handle_event()<br />
Initiator<br />
completion_action()<br />
«uses»<br />
calls<br />
operations<br />
1 1<br />
1..*<br />
<strong>Asynchronous</strong><br />
<strong>Completion</strong><br />
<strong>Token</strong><br />
Service<br />
async_operation()<br />
1<br />
1..*<br />
© <strong>Ingeniørhøjskolen</strong> i <strong>Århus</strong><br />
Slide 6
Sequence Diagram<br />
:Initiator<br />
:<strong>Completion</strong><br />
Handler<br />
:Service<br />
«create»<br />
:ACT<br />
ACT<br />
async_operation()<br />
notify()<br />
ACT result<br />
completion_action()<br />
result<br />
handle_event()<br />
© <strong>Ingeniørhøjskolen</strong> i <strong>Århus</strong><br />
Slide 7
Implementation Steps<br />
1. Define the ACT representation<br />
2. Select a strategy for holding the ACT at the<br />
initiator<br />
3. Determine how to pass the ACT from the<br />
initiator to the service<br />
4. Determine a strategy for holding the ACT in<br />
the service<br />
5. Determine the number of times an ACT can<br />
be used<br />
6. Determine the initiator strategy for<br />
demultiplexing ACTs to completion handler<br />
hook methods<br />
© <strong>Ingeniørhøjskolen</strong> i <strong>Århus</strong><br />
Slide 8
1. Define the ACT Representation<br />
• Pointer ACTs<br />
– pointer to completion handler object (ok for<br />
homogeneous platforms)<br />
• Object reference ACTs<br />
– e.g. CORBA’s object references provides a standard,<br />
portable and inter-operable solution (initiator use<br />
CORBA_narrow() operation to downcast)<br />
• Index ACTs<br />
– represented as an index into a table of completion<br />
handlers<br />
• for persistent completion handlers: use database identifiers or<br />
offsets into memory-mapped files<br />
© <strong>Ingeniørhøjskolen</strong> i <strong>Århus</strong><br />
Slide 9
2. Select a Strategy for holding the ACT<br />
at the Initiator<br />
• Implicit ACTs<br />
– Defining it to be the address of the initiator<br />
completion handler object<br />
– Benefits: efficient time and space utilization<br />
• Explicit ACTs<br />
– The initiator hold its ACTs in an explicit data<br />
structure<br />
• for example a table of completion handlers<br />
– Benefits: increased robustness and authenticity<br />
• Initiators are responsible for freeing any<br />
resources associated with ACTs<br />
© <strong>Ingeniørhøjskolen</strong> i <strong>Århus</strong><br />
Slide 10
6. Determine the initiator demultiplexing<br />
strategy<br />
1. Queued completion events<br />
– ACTs is placed in a completion event queue by a<br />
service or by a local service proxy<br />
– An initiator removes the ACT from a completion<br />
event queue<br />
– As shown in the Proactor pattern description (see<br />
next slide)<br />
2. Callbacks<br />
– An initiator passes a callback function/object to the<br />
service<br />
– The ACTs can be returned as a parameter to the<br />
callback object (can often be a Singleton)<br />
© <strong>Ingeniørhøjskolen</strong> i <strong>Århus</strong><br />
Slide 11
6.1 Win32_Proactor_Implementation<br />
void Win32_Proactor_Implementation::handle_events(<br />
Time_value *wait_time) {<br />
u_long num_bytes;<br />
OVERLAPPED *act;<br />
Bool status= GetQueued<strong>Completion</strong>Status(completion_port_,<br />
&num_bytes, 0, &act, wait_time ==0 ? 0 : wait_time->msec());<br />
}<br />
Async_Result *async_result= static_cast (act);<br />
async_result->status(status);<br />
if (status)<br />
async_result->bytes_transferred(num_bytes);<br />
else<br />
async_result->error(GetLastError());<br />
async_result->complete();<br />
delete async_result;<br />
(from proactor presentation)<br />
© <strong>Ingeniørhøjskolen</strong> i <strong>Århus</strong><br />
Slide 12
6.1 Async_Stream_Read_Result (ACT)<br />
class Async_Stream_Read_Result: public Async_Result {<br />
public:<br />
Async_Stream_Read_Result(<strong>Completion</strong>_Handler *ch) :<br />
completion_handler_(ch) { }<br />
// Adapter that dispatches the hook method<br />
// on the cached completion handler<br />
virtual void complete() {<br />
completion_handler_->handle_event(<br />
completion_handler_->get_handle(), READ_EVENT, *this);<br />
}<br />
private:<br />
<strong>Completion</strong>_Handler *completion_handler_;<br />
};<br />
(from proactor presentation)<br />
© <strong>Ingeniørhøjskolen</strong> i <strong>Århus</strong><br />
Slide 13
6.2 Generic Callback_Handler class<br />
class <strong>Completion</strong>_Handler_ACT {<br />
public:<br />
virtual void handle_event(const <strong>Completion</strong>_Event &event)=0;<br />
};<br />
class Callback_Handler {<br />
public: // Callback method<br />
virtual void notify(const <strong>Completion</strong>_Event &event,<br />
<strong>Completion</strong>_Handler_ACT *act) {<br />
completion_event(event, act);<br />
}<br />
protected:<br />
virtual void completion_event(const <strong>Completion</strong>_Event &event,<br />
<strong>Completion</strong>_Handler_ACT *act) {<br />
act->handle_event(event);<br />
}<br />
};<br />
© <strong>Ingeniørhøjskolen</strong> i <strong>Århus</strong><br />
Slide 14
Management Example (1)<br />
2<br />
Window<br />
2<br />
Logger<br />
Management<br />
Application<br />
1 subscribes at<br />
<strong>Completion</strong>_<br />
Handler_ACT<br />
1<br />
Management_<br />
Agent_Proxy<br />
+subscribe()<br />
stores<br />
Callback_<br />
Handler<br />
+notify()<br />
© <strong>Ingeniørhøjskolen</strong> i <strong>Århus</strong><br />
1<br />
1<br />
Slide 15<br />
Management_<br />
<strong>Completion</strong>_<br />
Handler<br />
2<br />
*
Management Example(2)<br />
main<br />
:Callback<br />
Handler<br />
event_<br />
loop<br />
topology_<br />
window<br />
callback_<br />
handler<br />
topology_<br />
window<br />
:Window<br />
EVENT<br />
database_<br />
logger<br />
database_<br />
logger:<br />
Logger<br />
connection_act<br />
connection_act<br />
:Management_<br />
<strong>Completion</strong>_<br />
Handler<br />
notify() connection_act event<br />
subscribe()<br />
agent_proxy:<br />
Management_<br />
Agent_Proxy<br />
completion_<br />
event()<br />
event<br />
handle_event()<br />
update()<br />
event<br />
update()<br />
event<br />
© <strong>Ingeniørhøjskolen</strong> i <strong>Århus</strong><br />
Slide 16
Management Example (3)<br />
class Management_Agent_Proxy {<br />
public:<br />
enum Event_Type { NEW_CONNECTIONS, FILE_TRANSFERS };<br />
};<br />
void subscribe( Callback_Handler *handler, Event_Type type;<br />
<strong>Completion</strong>_Handler_ACT *act);<br />
// ….<br />
// ….<br />
© <strong>Ingeniørhøjskolen</strong> i <strong>Århus</strong><br />
Slide 17
Management Example (4)<br />
class Management_<strong>Completion</strong>_Handler :<br />
public <strong>Completion</strong>_Handler_ACT {<br />
public:<br />
Management_<strong>Completion</strong>_Handler(Window *w, Logger *l) :<br />
window_(w), logger_(l) { }<br />
virtual void handle_event(const <strong>Completion</strong>_Event &event) {<br />
window_->update(event);<br />
logger_->update(event);<br />
}<br />
private:<br />
Window *window_;<br />
Logger *logger_;<br />
};<br />
© <strong>Ingeniørhøjskolen</strong> i <strong>Århus</strong><br />
Slide 18
Management Example (5)<br />
int main() {<br />
Callback_Handler callback_handler; // shared !<br />
Management_Agent_Proxy agent_proxy = // …<br />
Logger database_logger(DATABASE);<br />
Logger console_logger(CONSOLE);<br />
Window main_window(200,200);<br />
Window topology_window(100,20);<br />
Management_<strong>Completion</strong>_Handler connection_act(<br />
&topology_window,&database_logger);<br />
Management_<strong>Completion</strong>_Handler file_transfer_act(<br />
&main_window,&console_logger);<br />
agent_proxy.subscribe(&callback_handler,<br />
Management_Agent_Proxy::NEW_CONNECTIONS, &connection_act);<br />
agent_proxy.subscribe(&callback_handler,<br />
Management_Agent_Proxy::FILE_TRANSFERS, &file_transfer_act);<br />
run_event_loop();<br />
}<br />
© <strong>Ingeniørhøjskolen</strong> i <strong>Århus</strong><br />
Slide 19
ACT Benefits<br />
• Simplified initiator data structures<br />
• Efficient state acquisition (time efficient)<br />
• Space efficiency<br />
• Flexibility<br />
• Non-dictatorial concurrency policies<br />
© <strong>Ingeniørhøjskolen</strong> i <strong>Århus</strong><br />
Slide 20
ACT Liabilities<br />
• Memory leaks<br />
– if initiators use ACTs as pointers to<br />
dynamically memory and services fails to<br />
return the ACTs<br />
• Authentication<br />
– the initiator may need to authenticate the<br />
ACT before using it<br />
• Application re-mapping<br />
© <strong>Ingeniørhøjskolen</strong> i <strong>Århus</strong><br />
Slide 21
Known Uses<br />
• HTTP-Cookies<br />
• Windows NT uses ACT in conjunction<br />
with handles (see Proactor)<br />
• POSIX <strong>Asynchronous</strong> I/O API<br />
• CORBA demultiplexing (TAO Corba)<br />
• Electronic medical image system<br />
management<br />
• Jini handback object – a Java based<br />
example of ACT<br />
© <strong>Ingeniørhøjskolen</strong> i <strong>Århus</strong><br />
Slide 22
Relation to other POSA2 Patterns<br />
© <strong>Ingeniørhøjskolen</strong> i <strong>Århus</strong><br />
Slide 23