25.07.2014 Views

Asynchronous Completion Token - Ingeniørhøjskolen i Århus

Asynchronous Completion Token - Ingeniørhøjskolen i Århus

Asynchronous Completion Token - Ingeniørhøjskolen i Århus

SHOW MORE
SHOW LESS

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

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!