On Tue, Dec 14, 2004 at 11:39:03AM -0800, Ofer Nave wrote: > I can see how you would frequently want to design states that could be > invoked in both blocking and non-blocking mode. > > For example, imagine you had a session acting as a http client. You > might want to design the request() handler to work in both models: > > 1) [NON-BLOCKING] You could post a request event to the session, which > would perform the request and then send an event back to let you know > when it is done, or if it errored out. > > 2) [BLOCKING] You could use call instead of post, if you insist on > performing the request immediately and getting the results back, in > which case there is no reason to mess with the http client session > sending an event back when it can simply return the web page (or error > code) as the return value of the call. > > But, how do you elegantly implement that request method in such a way > that it knows what the caller wants it to do without additional "mode" > parameters (which are ugly)? > > I suppose the blocking/call() form is akin to calling a function as > opposed to sending an event, and arguably shouldn't be supported in the > event-driven model of POE, but it is convenient sometimes. :)
The person writing code to use the method knows whether she wants it to block before compile time. Why make a runtime check to determine the intent of a coding-time decision? I suggest having three methods: The first method sends a request and returns immediately. The second method assumes that part or all of a response is ready. Perhaps it's called as a result of IO::select() or $kernel->select_read(). It reads what it can, builds a response, and returns a full response. It returns undef or another indication if it can't return a response. The third method combines the two above, using IO::Select to block until the response arrives. For example: sub do_everything { my ($self, $request) = @_; $self->send_request($request); while ($self->wait_for_data()) { my $response = $self->receive_response(); return $response if $response; } } Then you'd write a component around it. The core of which would be a session like this one: POE::Session->create( inline_states => { _start => sub { $_[KERNEL]->alias_set(...); my $object = Object->new(); $_[HEAP]->{object} = $object; $_[KERNEL]->select_read($object->{socket}, "got_data"); ...; }, request => sub { $_[HEAP]->{object}->send_request(@_[ARG0..$#_]); store_request_info_in_heap(); }, got_data => sub { my $response = $_[HEAP]->{object}->receive_response(); if ($response) { look_up_request_info_in_heap(); send_response_to_other_session(); clean_up_request_info_from_heap(); } }, } ); Or something. This is all spur of the moment, and I'm sure the idea could be refined in a lot of ways. Maybe a set of base clasess could handle most of the work (request tracking, response posting, do_everything(), etc.). What would remain is customizing the object for a particular type of transaction. -- Rocco Caputo - http://poe.perl.org/