rcaputo's Journal
http://use.perl.org/~rcaputo/journal/
rcaputo's use Perl Journalen-ususe Perl; is Copyright 1998-2006, Chris Nandor. Stories, comments, journals, and other submissions posted on use Perl; are Copyright their respective owners.2012-01-25T02:48:28+00:00pudgepudge@perl.orgTechnologyhourly11970-01-01T00:00+00:00rcaputo's Journalhttp://use.perl.org/images/topics/useperl.gif
http://use.perl.org/~rcaputo/journal/
Reflex Progress
http://use.perl.org/~rcaputo/journal/40313?from=rss
<p>
I've been making good progress on Reflex lately. I have to: I've
applied to talk about it at YAPC::NA, so I need something to talk
about! The code has been moving too fast for CPAN right now, but you
can follow along at
<a href="http://github.com/rcaputo/reflex/">Reflex's repository on github</a>.
Here's a summary of the latest changes:
</p><p>
I've added support for as many callback mechanisms as I could think of,
including one I'm not sure existed before. Callback consumers (the things
being called back into) decide the kinds of callbacks they prefer. Objects
doing the calling use a single, consistent method: emit(). Reflex handles the
rest. The callback types supported so far:
</p><ul>
<li> <a href="http://github.com/rcaputo/reflex/blob/master/eg/eg-20-rcb-coderef.pl">Plain coderefs.</a> Great for the closure addicts among us.</li>
<li> <a href="http://github.com/rcaputo/reflex/blob/master/eg/eg-21-rcb-method.pl">Class and Object methods.</a> The Moose troop may approve.</li>
<li> <a href="http://github.com/rcaputo/reflex/blob/master/eg/eg-24-rcb-role.pl">Role-based methods</a>, which I'll have to explain later.</li>
<li>Condvar- or promise-like <a href="http://github.com/rcaputo/reflex/blob/master/eg/eg-32-promise-tiny.pl">wait() polling</a>. This one isn't really a callback. It's here for people who would rather not use them.</li>
</ul><p>
There's even an example that runs with
<a href="http://github.com/rcaputo/reflex/blob/master/eg/eg-33-all-callbacks.pl">every supported callback type at once</a>. Just because it can!
</p><p>
I've also implemented a few classes that support TCP (and maybe UNIX)
clients and servers.
</p><p>
<a href="http://github.com/rcaputo/reflex/blob/master/lib/Reflex/Stream.pm">Reflex::Stream</a>
is a base class for stream I/O. It extends Reflex::Handle, adding sysread(),
syswrite() and buffering.
<a href="http://github.com/rcaputo/reflex/blob/master/eg/EchoStream.pm">Example usage.</a>
</p><p>
<a href="http://github.com/rcaputo/reflex/blob/master/lib/Reflex/Listener.pm">Reflex::Listener</a>
is a base class for connection-based servers. Give it an IO::Socket, and it
will listen() for and accept() client connections. It also extends
Reflex::Handle.
<a href="http://github.com/rcaputo/reflex/blob/master/eg/eg-34-tcp-server-echo.pl">See TcpEchoServer in this example.</a>
</p><p>
<a href="http://github.com/rcaputo/reflex/blob/master/lib/Reflex/Connector.pm">Reflex::Connector</a>
is the other side of the connection-based client/server dialog. It will
perform a non-blocking connect() on the IO::Socket you provide. Eventually
it'll return that socket in its connected state, or notify you of failure.
Reflex::Connector also extends Reflex::Handle. Reflex::Client (below) uses it.
</p><p>
<a href="http://github.com/rcaputo/reflex/blob/master/lib/Reflex/Client.pm">Reflex::Client</a>
extends Reflex::Connector and integrates Reflex::Stream for a basic but usable
non-blocking client class. Here's
<a href="http://github.com/rcaputo/reflex/blob/master/eg/eg-35-tcp-client.pl">a small subclass of Reflex::Client.</a>
</p><p>
And
<a href="http://github.com/rcaputo/reflex/blob/master/lib/Reflex/Collection.pm">Reflex::Collection</a>
is a small object manager.
<a href="http://github.com/rcaputo/reflex/blob/master/eg/eg-34-tcp-server-echo.pl">The
TcpEchoServer</a> uses it to automatically clean up client objects when they
disconnect. This is another common and tedious task that Reflex automates.
</p><p>
Still to do: Document and release all this new goodness, then (presuming it's
accepted) write my talk! I hope to see you at YAPC::NA either way.
</p>rcaputo2010-04-16T06:04:36+00:00journalPOE 1.280 is Faster
http://use.perl.org/~rcaputo/journal/39749?from=rss
<p>
POE 1.280 has just been released, but it may take up to a day before
your favorite CPAN mirror catches wind of it. You'll also need the
latest POE::Test::Loops, version 1.030.
</p><p>
Those following along may notice that the version numbers jumped a
little. That's because POE has undergone a couple optimizations that
alter its behavior a little.
</p><p> <b>I/O Dispatch is Faster</b> </p><p>
I/O events jump the queue in POE 1.280. Skipping an enqueue and
dequeue saves significant time. The drawback is that I/O is
dispatched in a different order relative to other kinds of events.
Most people won't care, but it has affected one of
POE::Component::Client::HTTP's tests. See below for contact
information if you think it's affected you.
</p><p> <b>Session Cleanup is Faster</b> </p><p>
In POE 1.280, session cleanup is done just before the event loop would
wait for new events. Programs that aren't event bound should show
decreased latency because the cleanup will be scheduled during idle
times. This optimization changes the timing of session cleanup and
their resulting _stop events. While I don't think it affects many
people, it has already bitten Adam Kennedy. Please let us know if you
suspect it's gnawing on you, too.
</p><p> <b>Staying in Touch</b> </p><p>
People who need realtime notice of POE changes may watch them at
<a href="http://sourceforge.net/projects/poe/">SourceForge</a>,
<a href="http://www.ohloh.net/p/poe">Ohlo</a> and
<a href="http://cia.vc/stats/project/POE">CIA</a>.
</p><p>
POE's community may be found everywhere. Several members tend to
accumulate in
<a href="mailto:poe-subscribe@perl.org">POE's mailing list</a>
and
<a href="irc:ircperlorgpoe">IRC channel</a> at irc.perl.org #poe.
You're welcome to join us, even if you don't have problems to report.
</p><p>Thank you.</p>rcaputo2009-10-14T05:19:58+00:00journalUpcoming POE Changes
http://use.perl.org/~rcaputo/journal/39736?from=rss
<p>
Those of you who use POE for serious things should be aware of a
couple changes introduced after 1.269.
</p><p>
First, here's a public service annoucement from POE: Developers who
want to keep up with POE's latest changes are encouraged to follow its
<a href="https://poe.svn.sourceforge.net/svnroot/poe/trunk/poe/">repository</a>.
You'll get instant notification of changes as often as you'd like, and
you'll have maximum lead time to
<a href="http://rt.cpan.org/Public/Dist/Display.html?Name=POE">report
new bugs</a>
or port production code to new features. I've also released
<a href="http://search.cpan.org/dist/POE/">Version 1.269_002</a>
to the CPAN for developers who are more comfortable with that.
Remember: CPAN shells don't install developer releases by default.
And now back to the changes!
</p><p> <b>Synchronous I/O Dispatch</b> </p><p>
POE::Kernel dispatches I/O events synchronously after 1.269.
Previously these events would be enqueued along with everything else,
only to be dequeued and dispatched as soon as possible. Now they're
dispatched as they happen, saving the overhead of a round trip through
the event queue. Developers should notice an improvement in I/O bound
programs.
</p><p>
This naturally changes the timing of I/O events. Where in the past
they may have been enqueued behind other events, they now come first.
This could cause problems for users who depend on the relative timing
of I/O events compared to other kinds of events. I expect most
developers won't notice the difference.
</p><p>
This optimization is most effective for code that uses POE::Kernel's
select_read() and select_write() watchers directly. Additional layers
of abstraction, such as POE::Component::Server::TCP or AnyEvent add
overhead that has not been reduced by this optimization.
</p><p> <b>Mark and Sweep Session Garbage Collection</b> </p><p>
Session termination and memory reclamation have been combined and
delayed. Combining them reduces the overhead of POE::Kernel's
dispatcher by eliminating a few method calls per event. Delaying
garbage collection allows POE to do this work when it's likely to be
idle anyway. While the latter optimization doesn't reduce CPU
consumption, it should reduce callback latency in the common case.
</p><p>
People who require _stop to be called immediately when a session
releases its last resource may be disappointed. _stop events are
dispatched as a side effect of garbage collection, which as I've
mentioned has been delayed. Adam Kennedy's Test::POE::Stopping has
been affected. I hope his is a special case.
</p><p> <b>More to Come</b> </p><p>
There will be more improvements in the future, but that's all for now.
Stay tuned, and please report any problems you encounter early and
often. Thanks!
</p>rcaputo2009-10-09T17:40:13+00:00journalPOE Supports Other Event Loops, Really
http://use.perl.org/~rcaputo/journal/39612?from=rss
<p>Lately I've been hearing, <a href="http://www.catalyzed.org/2009/06/poe-anyevent321-fight.html">repeatedly</a> and <a href="http://www.slideshare.net/miyagawa/asynchronous-programming-with-anyevent">loudly</a>, that POE doesn't work with other event loops. I wrote the first bridge between POE and another event loop in May of 2000, so this is rather shocking news to me. I've had to rerun "make test" just to be sure I wasn't dreaming!<nobr> <wbr></nobr><tt>:)</tt> </p><p>Here is a slightly edited repost of my reply to <a href="http://bulknews.typepad.com/blog/2009/09/asynchronous-programming-with-anyevent.html">Tatsuhiko Miyagawa</a>, who writes in regards to his YAPC::Asia presentation:</p><blockquote><div><p>Rocco, the author of POE pointed out that slides 19-21 are misleading since POE also has the POE::Loop concept so that you can run your event loop under different backends like EV or Gtk. While that is true (and that is great), POE still can't run with the other main loop, like IO::Async::Loop->loop_forever. You still need to call POE::Kernel->run and to do so you should rewrite your main program to use POE everywhere, since existent IO::Async based program can't run any of POE::Component, which is totally possible with AnyEvent and AnyEvent::* modules.</p></div>
</blockquote><p>I respectfully disagree, and I have code to back me up.</p><p>POE runs with other main loops. In fact, POE::Kernel->run() is often implemented in terms of native event dispatchers. POE::Loop classes implement event watchers using native watchers, and native callbacks are used to generate POE events. Your call to $kernel->select_read() becomes Event->io(), Gtk::Gdk->input_add(), etc.</p><p>Depending on the POE::Loop implementation, POE::Kernel->run() need not be called upon to dispatch events. This is CPAN, so your mileage may vary. If you're interested in improving CPAN, submit bug reports to the appropriate queues.</p><p>I mentioned I had code. Here's a working example of POE code and native Glib code running together in the same program, using Glib's MainLoop:</p><blockquote><div><p> <tt>use Glib; # Install POE::Loop::Glib.<br>use POE;<br> <br>POE::Session->create(<br> inline_states => {<br> _start => sub { $_[KERNEL]->delay(tick => 1) },<br> tick => sub {<br> print "poe tick at ", time(), "...\n";<br> $_[KERNEL]->delay(tick => 1);<br> },<br> },<br>);<br> <br>my $glib_timer = Glib::Timeout->add(<br> 500, sub {<br> print "glib tick at ", time(), "...\n";<br> return 1;<br> }<br>);<br> <br># Dispatches Glib and POE events.<br>Glib::MainLoop->new->run();</tt></p></div> </blockquote><p>Of course you can call POE::Kernel->run() instead of Glib's main loop. This is a good thing. A single, portable run() method covers every supported event loop.</p><p>
<b>Addendum:</b>
</p><p>Things get really interesting when you realize that POE can be loaded into event loops that are already running. For example, Martijn van Beers and Chris Williams have been <a href="http://use.perl.org/~BinGOs/journal/31221">running POE inside irssi</a> for years. Chris has even embedded <a href="http://use.perl.org/~BinGOs/journal/32846">an entire POE-based IRC server in irssi</a>, which got a little mind-bendy when he connected to irssi from itself. Both cases work without rewriting irssi's main program.</p>rcaputo2009-09-11T05:57:26+00:00journalHelp me rename Lexical::Persistence
http://use.perl.org/~rcaputo/journal/39588?from=rss
<p>
"Persistence" implies that data will be saved and loaded from disk, to
a database, or some other persistent storage. That's not what the
module does, so I think it needs a new name.
</p><p>
Lexical::Persistence objects are closures that make the values of
lexical variables stick (or persist) in everything they call. In the
following example, the Lexical::Persistence object makes sure that
getter()'s version of $x contains the value stored by setter().</p><blockquote><div><p> <tt>use Lexical::Persistence;<br> <br>my $lp = Lexical::Persistence->new();<br>$lp->call(\&setter);<br>$lp->call(\&getter);<br> <br>sub setter { my $x = "some value" }<br>sub getter { print my $x, "\n" }</tt></p></div> </blockquote><p>
Lexical::Persistence's closures are objects. Programs may examine and
manipulate their contents between calls. The following code displays
something like this:</p><blockquote><div><p> <tt>My mind is going. I can feel it.<br>My is going. I can feel it.<br>My is going. I feel it.<br>My going. I feel it.<br>My going. I feel<br>My I feel<br>My I<br>My</tt></p></div> </blockquote><p>Here's the example:</p><blockquote><div><p> <tt>use Lexical::Persistence;<br> <br>my $lp = Lexical::Persistence->new();<br>$lp->set_context(<br> _ => {<br> '@mind' => [qw(My mind is going. I can feel it.)]<br> }<br>);<br> <br>while (1) {<br> $lp->call(\&display);<br> my $mind = $lp->get_context("_")->{'@mind'};<br> splice @$mind, rand(@$mind), 1;<br> last unless @$mind;<br>}<br> <br>sub display {<br> my @mind;<br> print "@mind\n";<br>}</tt></p></div> </blockquote><p>
So, what would be a better name for this module?
</p>rcaputo2009-09-06T06:51:42+00:00journalTrying Out this Git Thing
http://use.perl.org/~rcaputo/journal/39423?from=rss
<b>Distributing Development</b>
<p>
Distributed version control is great. It'll bring on the patches,
establish world peace, and get you laid. It adds extra steps to your
workflow, but they make everything easier. Don't ask me how. Even if
I understood that trick, the Magician's Code wouldn't let me explain
it to you.
</p><p>
There's more than one way to distribute development, and many of them
are free.
<a href="http://bazaar-vcs.org/">Bazaar</a>
stood out as having the best mix of flexibility, extensibility and
usability. It also has
<a href="https://launchpad.net/">Launchpad</a>,
which provides frameworks for distributed project management and
feature design.
</p><p>
While Bazaar looks nicer, doing DVCS right means going where the
people are. For Perl, that's
<a href="http://git-scm.com/">Git</a>.
Sorry, Bazaar, it's not you, it's me.
</p><p>
<b>Getting my Feet Wet</b>
</p><p>
<a href="http://search.cpan.org/dist/POE/">POE</a>
is a perfect project to migrate to a distributed development model.
It's large, it's popular, and it can always benefit from more
developers. I mean, what <em>can't</em>, right?
</p><p>
POE's size and visibility also make it a bad choice for a first foray
into distributed development. New software solutions, like new
cleaning solutions, are best tried somewhere that won't show if they
stain.
</p><p>
POE's
<a href="http://edp.org/monkey.htm">scratch monkey</a>
is
<a href="http://search.cpan.org/dist/POE-Stage">POE::Stage</a>,
a much smaller, much less visible project that, needless to say, can
benefit from more developers. I recently migrated it from Subversion
using
<a href="http://blog.woobling.org/2009/06/git-svn-abandon.html">Yuval Kogman's tools and advice</a>.
The popular svn2git alternative didn't work well for me.
</p><p>
<b>Decisions, Decisions</b>
</p><p>
There's more than one way to host a Git project. GitHub and Gitorious
have been recommended for different reasons, but neither is a clear
winner. Fortunately, a distributed repository can be hosted in more
than one place. POE::Stage is available at both
<a href="http://github.com/rcaputo/poe-stage/tree">GitHub</a>
and
<a href="http://gitorious.org/poe-stage">Gitorious</a> until I decide.
</p><p>
<b>What Next?!</b>
</p><p>
So I'm all set up. I've successfully migrated a project to Git,
hosted it publicly (twice) and even awkwardly pushed a few changes.
</p><p>
The journey's only beginning, though. I have plenty of small projects
to migrate while I commit the DVCS dance to muscle memory. I also have
some
<a href="http://poe.perl.org/?How_to_Help">specific Achievements</a>
to acquire before tackling the Boss Level, migrating POE itself.
</p><p>
It should be fun, or at least a good challenge. I'll keep you posted.
</p>rcaputo2009-08-08T21:38:29+00:00journalPOE Changes Coming Soon
http://use.perl.org/~rcaputo/journal/39340?from=rss
<p>
POE::Test::Loops 1.020 will be released tonight. This is a suite of
reusable tests for developers who want to add external event loop
support to POE. Version 1.020 acquires more signal handler tests from
POE. Existing POE::Loop authors should try the new tests at their
earliest convenience. Those who need the code right away can track
the repository:</p><blockquote><div><p> <tt> svn co \<br> https://poe.svn.sourceforge.net/svnroot/poe/trunk/poe-test-loops ptl</tt></p></div> </blockquote><p>
A developer version of POE will be released shortly after the new
tests work their way around CPAN. The upcoming POE release
incorporates Philip Gwyn's fixes for race conditions in POE's signal
handlers. Users who have noticed strange behavior during prolonged
periods of signal activity should test against this release as soon as
possible. Those who want to get a jump on the changes can track POE's
latest development through its repository:</p><blockquote><div><p> <tt> svn co \<br> https://poe.svn.sourceforge.net/svnroot/poe/trunk/poe poe</tt></p></div> </blockquote><p>
POE changes are also tracked at
<a href="http://sourceforge.net/projects/poe/">SourceForge</a>,
<a href="http://www.ohloh.net/p/poe">Ohlo</a> and
<a href="http://cia.vc/stats/project/POE">CIA</a>.
</p><p>
POE 1.007 will officially go out after a successful round of testing.
You're welcome to join us in irc.perl.org #poe to watch the CPAN
tester fallout.
</p><p>
POE 1.008 will be released shortly afterward. It will spin off some
optional dependencies, mainly POE's "core" support for optional,
external event loops. POE::Loop::Event, POE::Loop::Gtk and
POE::Loop::Tk will join
<a href="http://search.cpan.org/search?query=POE%3A%3ALoop&mode=dist">their siblings on the CPAN</a>.
Their test coverage should improve, and POE's distribution size and
installation footprint will shrink.
</p><p>Thank you.</p>rcaputo2009-07-24T04:30:21+00:00journalTest post, please ignore.
http://use.perl.org/~rcaputo/journal/39282?from=rss
<p>
BinGOs pointed out WWW::UsePerl::Journal and kindly pasted the code
he uses to drive it. I've hacked it a little to embed the article
title into a header block on the article. Since I'm writing these
offline, I figure the title should be associated with the article
for posterity.
</p><p>
Here's my hacked version of BinGOs' posting script:</p><blockquote><div><p> <tt>#!/usr/bin/env perl<br> <br>use warnings;<br>use strict;<br> <br>use WWW::UsePerl::Journal;<br> <br>my $user = 'rcaputo';<br>my $pass = '********';<br> <br># Headers.<br> <br>my $title;<br>my $comments = 1;<br> <br>while (<>) {<br> chomp;<br> last if<nobr> <wbr></nobr>/^\s*$/;<br> <br> unless (/^\s*([^:]+?)\s*:\s*(\S.*?)\s*$/) {<br> die "Unknown header line ($_)\n";<br> }<br> <br> my ($header, $value) = (lc($1), $2);<br> <br> # Avoid the lulz.<br> $value =~ s/\Q$pass/********/g;<br> <br> if ($header eq "title") {<br> $title = $value;<br> next;<br> }<br> <br> if ($header eq "comments") {<br> if (lc($value) eq "yes") {<br> $comments = 1;<br> }<br> elsif (lc($value) eq "no") {<br> $comments = 0;<br> }<br> else {<br> die "Comments header may only be yes or no.\n";<br> }<br> }<br>}<br> <br># Body HTML.<br> <br>my $text = '';<br>while (<>) {<br> # Only one per line.<br> if (/^\s*<ecode\s*file="([^"]+)"\s*\/*\s*>\s*$/) {<br> my $code = `/bin/cat $1`;<br> $code =~ s/\n+$//;<br> <br> # Break up the ecode tags so this script can<br> # present itself.<br> $_ = "<" . "ecode>\n$code\n<" . "/ecode>";<br> }<br> <br> $text<nobr> <wbr></nobr>.= $_;<br>}<br> <br># Avoid the lulz.<br>$text =~ s/\Q$pass/********/g;<br> <br>die "Article needs a Title header.\n" unless $title;<br>die "Article needs body HTML.\n" unless $text;<br> <br># Post.<br> <br>my $journal = WWW::UsePerl::Journal->new($user);<br>my $post = $journal->login($pass);<br> <br>unless (<br> $post->postentry(<br> title => $title,<br> text => $text,<br> topic => 34, # user journal<br> comments => $comments, # allow comments?<br> type => 2, # ???<br> promote => 'publish', # ???<br> )<br>) {<br> die "Failure.\n";<br>}<br> <br>print "Success.\n";<br>exit;</tt></p></div> </blockquote><p>
Here's the source of this article:</p><blockquote><div><p> <tt>Title: Test post, please ignore.<br> <br><p><br> BinGOs pointed out WWW::UsePerl::Journal and kindly pasted the code<br> he uses to drive it. I've hacked it a little to embed the article<br> title into a header block on the article. Since I'm writing these<br> offline, I figure the title should be associated with the article<br> for posterity.<br></p><br> <br><p><br> Here's my hacked version of BinGOs' posting script:<br> <ecode file="~/bin/useperlpost.pl"/><br></p><br> <br><p><br> Here's the source of this article:<br> <ecode file="~/Documents/useperl/testing-www-useperl-journal.html"/><br></p><br> <br><p><br> Thanks for reading anyway.<br></p></tt></p></div> </blockquote><p>
Thanks for reading anyway.
</p>rcaputo2009-07-13T06:17:14+00:00journal