On Sat, Dec 20, 2003 at 06:32:40PM -0800, Dave Roe wrote:
> 
> I have an application which I am trying to use POE for. The first part 
> was simple: change a pre-forking socket server into a pre-forking POE 
> server. A good beginners test.

There is a pre-forking HTTP server at
http://poe.perl.org/?Poe_cookbook/web_server_with_forking

It may not be ideal for your purposes, but it may help map familiar
ideas into POE land.

> This is how I would start to translate this to POE: I would have a 
> POE::Session object for MySession, and POE::Session objects for 
> MyDataManager and MyDispatcher. by aliasing these last two, they will 
> persist as interfaces that I can send events to. No need to store 
> references on MySession because I can call/post/yield to the alias. Am 
> I right, so far?

You are correct.  The message-based interfaces might not be necessary,
though.  If you can get aawy with direct calling objects, it's better.
You avoid message-passing overhead for what amounts to simple calls.

I think the best mix of flexibility and speed is to use plain objects
when you don't absolutely need messages.  Keep the POE::Session layer
thin, only using events where you want concurrency.

For example, use POE::Component::Server::TCP to create a server, but
have its handlers drive objects---even singletons---instead of passing
messages to subsystems.  It's simpler and faster.

You'd want to create subsystems and pass messages to them when those
subsystems need to work asynchronously.  For example, if your system is
a web crawler with a web server interface, you'd want one subsystem to
act as the server and another to act as the clients.

The server component would handle user interaction.  The client
component would handle asynchronous fetches.  Some sort of singleton
object in the middle can act as a database, and both asynchronous
subsystems can call it directly.

If the database object is too slow, you can switch to a subsystem that
manages DBI connections in child processes.  There are a few components
on the CPAN to do this.  But you usually can skip it if your program's
working fast enough.

> My next point of confusion: does it go against POE thinking to use 
> "call" over "post"/"yield" for the majority of events? The reason I ask 
> is as follows: the MyDataManager package exists as an interface whose 
> methods are called from other interfaces in such ways as "what is the 
> answer to such and such variable?". It seems that I would never "post" 
> an event to MyDataManager but would always use "call", as the calling 
> interface would need the answer immediately before being able to 
> proceed.

It depends on your program's data flow.  You mentioned later that you
understand call() isn't cooperative.  You should also know that it's
slower because of added POE overhead.  The only benefits are:

1. It dispatches an event synchronously.
2. You get a return value immediately.
3. The called code is executed in another session's context.

If you don't need one of them, it's a sign that you might not need
call() at all.

> Finally, another thing on my mind is how I wrap existing packages with 
> a POE interface that exposes their existing methods without too much 
> modification.
>
> The approach I am most likely to take is this: a package, for example 
> MyDataManager, will remain unchanged. I will define a new package 
> called POE::MyDataManager which will create a POE::Session and an 
> instance of MyDataManager which is stored on the session heap. The 
> events handled by POE::MyDataManager will call the existing methods on 
> the heap's MyDataManager and return the result. Ultimately, a POE event 
> to object method handler, which should allow me to continue to use 
> these objects in a non-POE environment.

There is a POE::Component::SubWrapper on the CPAN.  It autotmatically
wraps packages with event handlers.  It might save you a big chunk of
work.

> What this all says to me is that I would be using POE to manage 
> sessions that can send events to one another but I wouldn't get any of 
> the multi-tasking functionality (as I am usually sending events to the 
> top of the queue with "call"). I do have an interesting loop within the 
> application that I want to tackle using POE events, which itself is the 
> biggest reason I am trying to integrate POE. Is there anything 
> glaringly wrong about the other approaches described above?

You're correct.  You can use call(), but it's pointless if you never
return back to POE so it can dispatch events and generate new ones.

It sounds like your "interesting loop" can be ported to POE.  If so,
this gives you the event-driven core that drives the other objects with
call().  When the other objects return, and your event handlers do,
POE::Kernel can iterate through run() again.  This should be enough to
regain multitasking.

POE's pretty easy to port to if your existing code can be driven by
select().  See http://poe.perl.org/?Evolution_of_a_POE_Server which
takes an IO::Select based server through several POE-based incarnations.

-- 
Rocco Caputo - [EMAIL PROTECTED] - http://poe.perl.org/

Reply via email to