/
POE.pm
827 lines (564 loc) · 24.5 KB
/
POE.pm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
# $Id$
# Copyrights and documentation are after __END__.
package POE;
use strict;
use Carp;
use vars qw($VERSION);
$VERSION = '0.1206';
sub import {
my $self = shift;
my @sessions = grep(/^(Session|NFA)$/, @_);
my @modules = grep(!/^(Kernel|Session|NFA)$/, @_);
croak "POE::Session and POE::NFA export conflicting constants"
if grep(/^(Session|NFA)$/, @sessions) > 1;
# Add Kernel back it, whether anybody wanted it or not.
unshift @modules, 'Kernel';
# If a session was specified, use that. Otherwise use Session.
if (@sessions) {
unshift @modules, @sessions;
}
else {
unshift @modules, 'Session';
}
my $package = (caller())[0];
my @failed;
foreach my $module (@modules) {
my $code = "package $package; use POE::$module;";
eval($code);
if ($@) {
warn $@;
push(@failed, $module);
}
}
@failed and croak "could not import qw(" . join(' ', @failed) . ")";
}
#------------------------------------------------------------------------------
sub new {
my $type = shift;
croak "$type is not meant to be used directly";
}
#------------------------------------------------------------------------------
1;
__END__
=head1 NAME
POE - perl application kernel with event driven threads
=head1 SYNOPSIS
#!/usr/bin/perl -w
use strict;
# Use POE!
use POE;
# Every session must handle a special event, _start. It's used to
# tell the session that it has been successfully instantiated.
# $_[KERNEL] is a reference to the program's global POE::Kernel
# instance; $_[HEAP] is the session's local storage; $_[SESSION] is
# a reference to the session itself.
sub handler_start {
my ($kernel, $heap, $session) = @_[KERNEL, HEAP, SESSION];
print "Session ", $session->ID, " has started.\n";
$heap->{count} = 0;
$kernel->yield('increment');
}
sub handler_increment {
my ($kernel, $heap, $session) = @_[KERNEL, HEAP, SESSION];
print "Session ", $session->ID, " counted to ", ++$heap->{count}, ".\n";
$kernel->yield('increment') if $heap->{count} < 10;
}
# The _stop event is special but, handling it is not required. It's
# used to tell a session that it's about to be destroyed. _stop
# handlers perform shutdown things like resource cleanup or
# termination logging.
sub handler_stop {
print "Session ", $_[SESSION]->ID, " has stopped.\n";
}
# Start ten sessions. POE::Session constructors map event names to
# the code that handles them.
for (0..9) {
POE::Session->create(
inline_states =>
{ _start => \&handler_start,
increment => \&handler_increment,
_stop => \&handler_stop,
}
);
}
# Start the kernel, which will run as long as there are sessions.
$poe_kernel->run();
exit;
=head1 DESCRIPTION
Please see the SEE ALSO section for conceptual summary of all POE's
documentation.
POE is an acronym of "Persistent Object Environment". It originally
was designed as the core of a persistent object server and runtime
environment, but it's evolved into a general purpose application (as
opposed to system) kernel.
POE's core contains two types of module. First there's POE::Kernel;
this is the main resource manager and event loop. Second are the
sessions or state machines which implement the actual threads. The
sessions are POE::Session (not quite a proper state machine) and
POE::NFA.
The remainder of this distribution consists of convenience and helper
modules, most of which aren't required to begin using POE.
=head1 USING POE
Using POE can be pretty tedious. Consider this example, which pulls
in the necessary modules for a line-based TCP server:
use POE::Kernel;
use POE::Session;
use POE::Wheel::SocketFactory;
use POE::Wheel::ReadWrite;
use POE::Filter::Line;
use POE::Driver::SysRW;
The POE.pm module fixes some of this tedium. When POE.pm is used
directly, it automatically includes POE::Kernel and POE::Session. It
also includes each of the C<use> statement's parameters, first
prepending "POE::" to them. An example is in order:
This C<use> statement is equivalent to the previous six.
use POE qw( Wheel::SocketFactory Wheel::ReadWrite
Filter::Line Driver::SysRW
);
=head1 WRITING POE PROGRAMS
Basic POE programs have four parts.
=over 2
=item Preliminary program setup
This is the usual overhead for writing a Perl program: a shebang line,
perhaps some C<use> statements to import things, and maybe some global
variables or configuration constants. It's all pretty standard stuff.
#!/usr/bin/perl -w
use strict;
use POE;
=item Define the program's event handlers or states
Declare functions which will handle events here. This is deceptive,
since the functions can be declared anywhere, including as anonymous
subroutines in a session constructor call.
sub handler_start {
...
}
sub handler_increment {
...
}
sub handler_stop {
...
}
=item Start initial sessions or machines
The Kernel only runs as long as there is something for it to do. It's
main loop returns after the last session has stopped. The obvious
corolary to this rule is that the main loop will return immediately if
nothing is set up when it's called.
for (0..9) {
POE::Session->create(
inline_states =>
{ _start => \&handler_start,
increment => \&handler_increment,
_stop => \&handler_stop,
}
);
}
=item Start the kernel's main loop
_start handlers are invoked immediately when sessions are
instantiated. Everything else happens because the kernel makes it so,
and the kernel can't do that 'til it's started. Most programs exit
afterwards since the kernel only returns after everything is done.
$poe_kernel->run();
exit 0;
=back
=head1 POE's ARCHITECTURE
POE is built in separate layers. Each layer requires the ones beneath
it, but no low-level layer requires a higher one.
=over 2
=item Events layer
The events layer consists of an event dispatcher, POE::Kernel, and the
sessions or state machines it runs: POE::Session (a generic event
driven thread) and POE::NFA (an event driven nondeterministic finite
automaton).
=item One or more I/O layers
I/O layers are built upon the event layer, and that allows them to
coexist in the same program. POE only includes one I/O layer: Wheels.
"Wheels" is a whimsical name for interlocking cogs that together make
things go. They're also reinvented a lot, and this is no exception.
POE comes with four wheels.
=over 2
=item POE::Wheel::FollowTail
FollowTail follows the tail of an ever-growing file. It's useful for
watching logs and things of that nature.
=item POE::Wheel::ListenAccept
ListenAccept performs ye olde non-blocking socket listen and accept.
It's great for programs that can't use SocketFactory and instead must
listen and accept connections from sockets created elsewhere.
=item POE::Wheel::ReadWrite
ReadWrite is the star of POE's default I/O layer. It performs
buffered, flow-controlled I/O on non-blocking, unbuffered filehandles.
It almost acts like a Unix stream which can't stack protocol layers,
but that may change.
ReadWrite uses two other classes to do its dirty work: Driver and
Filter. Drivers do the actual work of reading and writing
filehandles. Filters translate between raw streams and cooked chunks
of tasty dada.
D comes before F, so Drivers go first.
=over 2
=item POE::Driver::SysRW
Nobody has needed another driver yet, so this is the only one
currently available. It performs sysread and syswrite in a generic
way so that ReadWrite can use it and future drivers interchangeably.
Other drivers will use the same interface, should they ever be
written.
=back
Filters next. There are a few.
=over 2
=item POE::Filter::Block
This filter parses input as fixed-length blocks. On the output side,
it merely passes data through unscathed.
=item POE::Filter::HTTPD
The HTTPD filter parses input as HTTP requests and translates them
into HTTP::Request objects. On the output side, it takes
HTTP::Response objects and turns them into something suitable to be
sent to a web client/user-agent.
=item POE::Filter::Line
The Line filter parses incoming streams into lines and turns outgoing
lines into streams. It used to be very basic, but recent improvements
have added interesting features like newline autodetection.
=item POE::Filter::Reference
The Reference filter is used to sond Perl structures between POE
programs or between POE and other Perl programs. On the input side,
frozen data (via Storable, FreezeThaw, or some other data mechanism)
is thawed into Perl data structures. On output, references given to
the filter are frozen. Data may also be compressed on request if
Compress::Zlib is installed.
=item POE::Filter::Stream
The stream filter does nothing. It merely passes data through without
any change.
=back
=item POE::Wheel::SocketFactory
SocketFactory creates all manner of connectionless and connected
network sockets. It also listens on TCP server sockets, only
returning accepted client connections as they arrive.
=back
=back
=head1 POE COMPONENTS
Components consist of one or more sessions or state machines that
encapsulate a very high level procedure. For example,
POE::Component::IRC (not included) performs nearly all the functions
of a full-featured IRC client. POE::Component::UserBase (not
included) is a user authentication and data persistence servlet.
Components tend to be highly reusable core libraries that handle
tedious tasks, freeing programmers to focus on more interesting
things. This should be true for any library, though.
=over 2
=item POE::Component::Server::TCP
This is a thin wrapper around POE::Wheel::SocketFactory. It provides
the core of a very simple TCP server and is customized by giving it
coderefs to execute when connections arrive or errors occur.
=head1 Support Modules
Finally, there are some files which POE uses but aren't required
elsewhere. These include POE::Preprocessor and the base classes:
POE::Component, POE::Driver, POE::Filter and POE::Wheel. There also
are some development files in the lib directory.
=over 2
=item POE::Preprocessor
This is a macro preprocessor. It also implements plain and enumerated
constants. POE::Kernel uses it to inline smaller functions and make
the source generally more readable. There seem to be two drawbacks:
First, code is more difficult to examine in perl's debugger since it
doesn't necessarily look like the original source. Second, programs
take longer to start up because every source line must first pass
through a perl filter. The compile-time penalty is negligible in
long-running programs, and the runtime boost from fewer function calls
can make up for it over time.
POE::Component, POE::Driver and POE::Filter exist to document their
classes of objects. POE::Wheel contains some base functions for
tracking unique wheel IDs.
=head1 OBJECT LAYER
The object layer has fallen into disrepair again. In fact, it never
really got to a good start. It's scheduled to be removed from this
distribution in version 0.1301. When it does return, it will be as a
separate component.
=head1 SAMPLE PROGRAMS
The sample programs are scheduled for removal from this distribution
in version 0.1301. They will be moved to a separate distribution and
documented better.
This distribution contains 28 example and/or tutorial programs in the
archive's ./samples directory. Be advised, however, that many of them
date from the early days of POE's development and may not exhibit the
best coding practices.
The author's always looking for new example ideas.
=head1 COMPATIBILITY ISSUES
POE has tested favorably on as many Perl versions as the author can
find or harass people into trying. This includes Linux, FreeBSD, OS/2
and at least one unspecified version of Windows. As far as anyone can
tell, nobody ever has tried it on any version of MacOS.
POE has been tested with Perl versions as far back as 5.004_03 and as
recent as 5.6.0. The CPAN testers are a wonderful bunch of people who
have dedicated resources to running new modules on a variety of
platforms. The latest POE tests are visible at
<http://testers.cpan.org/search?request=dist&dist=POE>. Thanks,
people!
Please let the author know of breakage or success that hasn't been
covered already. Thanks!
Specific issues:
=over 2
=item Various Unices
No known problems.
=item OS/2
No known problems.
=item Windows
Windows support lapsed in version 0.0806 when I took out some code I
wasn't sure was working. Well, it was working, and removing it broke
POE on Windows.
Douglas Couch reported that POE worked with the latest stable
ActivePerl prior to version 5.6.0-RC1. He said that RC1 supported
fork and other Unix compatibilities, but it still seemed like beta
level code. This seems to have changed with the release of 5.6.0-GA.
Douglas writes:
I've done some preliminary testing of the 0.0903 version and the
re-addition of the Win32 support seems to be a success. I'll do
some more intensive testing in the next few days to make sure
nothing else is broken that I haven't missed.
And later:
After testing out my own program and having no problems with the
newest version (with Win32 support), I thought I'd test out some of
the samples and relay my results.
filterchange.perl and preforkedserver.perl both contain fork
commands which are still unsupported by ActiveState's port of Perl,
so they were both unsuccessful. (this was anticipated for anything
containing fork)
ref-type.perl, refsender.perl, thrash.perl and wheels2.perl all ran
up against the same unsupported POSIX macro. According to the error
message, my vendor's POSIX doesn't support the macro EINPROGRESS.
[EINPROGRESS is fixed as of version 0.1003; see the Changes]
Other than those particular problems all of the other sample scripts
ran fine.
As far as I know, POE works okay on Windows these days.
=item MacOS
I have heard rumors from MacOS users that POE might work with MacPerl,
but so far nobody has stepped forward with an actual status report.
I'd be happy to hear either way.
=back
=head1 SYSTEM REQUIREMENTS
POE's module recommendations have been codified as part of the `make
test' procedure. Any missing dependencies will be reported on, and
POE will refuse to test itself if critical modules aren't found.
Some of POE's sample programs use fork(). They won't work wherever
fork() isn't available; sorry.
POE relies heavily on constants in the POSIX module. Some of the
constants aren't defined by ActiveState Perl for Windows, but POE
defines them itself to work around this.
POE::Preprocessor needs Filter::Util::Call version 1.18 or later for
source filtering. Everything else relies on POE::Preprocessor.
Some of POE's sample programs require a recent IO bundle, but you get
that for free with recent versions of Perl.
Filter::Reference needs Storable or FreezeThaw or some other data
freezer/thawer package. Storable tends to be the fastest, and so it's
preferred. Compress::Zlib is needed if you want to compress frozen
data.
B<Important Filter::Reference note:> If you're using Filter::Reference
to pass data to another machine, make sure every machine has the same
versions of the same libraries. Subtle differences, even in different
versions of modules like Storable, can cause mysterious errors when
data is reconstituted at the receiving end. Whe all else fails,
upgrade to the latest versions.
Filter::HTTPD uses a small world of modules including HTTP::Status;
HTTP::Request; HTTP::Date and URI::URL. The httpd.perl sample program
uses Filter::HTTPD, which uses all that other stuff.
=head1 SUPPORT RESOURCES
These are Internet resources where you may find more information about
POE.
=over 2
=item The POE Mailing List
POE has a mailing list at perl.org. You can receive subscription
information by sending e-mail:
To: poe-help@perl.org
Subject: (anything will do)
The message body is ignored.
All forms of feedback are welcome.
=item The POE Web Site
POE has a web site where the latest development snapshot, along with
the Changes file and other stuff may be found: <http://poe.perl.org/>
=item SourceForge
POE's development has moved to SourceForge as an experiment in project
management. You can reach POE's project summary page at
<http://sourceforge.net/projects/poe/>.
=back
=head1 SEE ALSO
This is a summary of POE's modules and the things documented in each.
=head2 Events Layer
These are POE's core modules.
=over 2
=item POE (this document)
The POE manpage includes a sample program and walkthrough of its
parts, a summary of the modules which comprise this distribution,
POE's general system requirements, how to use POE (literally), and
where to get help. It also has a table of contents which you're even
now reading.
=item POE::Kernel
The POE::Kernel manpage includes information about debugging traces
and assertions; FIFO events; filehandle watchers; Kernel data
accessors; posting events from traditional callbacks (postbacks);
redefining sessions' states; resource management; session aliases;
signal types, handlers, and pitfalls; signal watchers; synchronous
vs. asynchronous events; and timed events (alarms and delays).
=item POE::NFA
The POE::NFA manpage covers this session's additional predefined
events, how NFA differs from Session, state changing methods, and the
spawn constructor.
=item POE::Session
The POE::Session manpage covers different kinds of states (inline
coderef, object methods, and package methods); postback mechanics;
predefined event names and the parameters included with them; resource
management and its effects on sessions; session constructors (new and
create); session data accessors; synchronous vs. asynchronous events
in more detail; why sessions don't stop by themselves, and how to
force them to.
=back
=head2 I/O Layer
These modules comprise POE's "Wheels" I/O abstraction.
=over 2
=item POE::Driver
The POE::Driver manpage covers drivers in general and their common
interface.
=item POE::Driver::SysRW
The SysRW driver's manpage describes the sysread/syswrite abstraction
and covers parameters which can be used to customize a SysRW driver's
operation.
=item POE::Filter
The POE::Filter manpage covers filters in general and their common
interface. It discusses the pitfalls involved in switching filters
on a running wheel.
=item POE::Filter::HTTPD
The HTTPD filter's manpage covers using POE as a web server.
=item POE::Filter::Line
The Line filter's manpage discusses how to read and write data by
lines; how to change the newline literal or regular expression; and
how to enable newline autodetection when working with strange peers.
=item POE::Filter::Reference
The Reference filter's manpage talks about marshalling data and
passing it between POE programs; and customizing the way data is
frozen, thawed and optionally compressed.
=item POE::Filter::Stream
The Stream filter's manpage is pretty empty since it doesn't do much
of anything.
=item POE::Wheel
The Wheel's manpage talks about wheels in general and their common
interface.
=item POE::Wheel::FollowTail
The FollowTail wheel's manpage discusses how to watch the end of an
ever-growing file (not to be confused with that orb tune) and how to
change aspects of the wheel's behavior with constructor parameters.
=item POE::Wheel::ListenAccept
The ListenAccept wheel's manpage discusses how to listen and accept
connections using sockets created from sources other than
SocketFactory.
=item POE::Wheel::ReadWrite
The ReadWrite wheel's manpage covers non-blocking I/O with optional
flow control.
=item POE::Wheel::SocketFactory
The SocketFactory wheel's manpage discusses how socket factories
create and manage sockets; the events they emit on connection,
acceptance, and failure; and the parameters which govern what they do.
=back
=head2 Object Layer
These modules comprise the object layer. They will be removed after
0.13 and made into a separate component some time after that. I'm not
going to bother explaining them since they're doomed.
POE::Curator; POE::Object; POE::Repository; POE::Attribute::Array;
POE::Runtime
=head2 Standard Components
These components are included with POE because they're nearly
universally useful.
=over 2
=item POE::Component
The POE::Component manpage discusses what components are and why they
exist.
=item POE::Component::Server::TCP
The TCP server component explains how to create TCP servers with a
minimum of fuss.
=back
=head2 Supporting Cast
These modules help in the background.
=over 2
=item POE::Pipe::OneWay
This creates unbuffered one-way pipes. It tries various methods in
the hope that one of them will work on any given platform.
=item POE::Pipe::TwoWay
This creates unbuffered two-way pipes. It tries various methods in
the hope that one of them will work on any given platform. It's
preferred over two OneWay pipes because sometimes two-way transports
are available and it can save you a couple filehandles.
=item POE::Preprocessor
POE's preprocessor covers inline constant replacement, enumerated
constants, and macro substitutions in perl programs.
=back
=head1 BUGS
The t/*.t tests only cover about 70% of POE. The latest numbers are
in the README file.
=head1 AUTHORS & COPYRIGHT
POE is the combined effort of more people than I can remember
sometimes. If I've forgotten someone, please let me know.
=over 2
=item Arnar M. Hrafnkelsson
Arnar is <addi@umich.edu>. Addi tested POE and POE::Component::IRC on
Windows, finding bugs and testing fixes. He appears throughout the
Changes file.
=item Artur Bergman
Artur Bergman is <artur@vogon-solutions.com>. He contributed many
hours' work into POE and quite a lot of ideas. Years later, I decide
he's right and actually implement them.
Artur is the author of Filter::HTTPD and Filter::Reference, as well as
bits and pieces throughout POE. His intangible contributions include
feedback, testing, conceptual planning and inspiration. POE would
never have come this far without his support.
=item Douglas Couch
Douglas Couch is <dscouch@purdue.edu>. He was the brave soul who
stepped forward to offer valuable testing on the Windows platforms.
His reports helped get POE working on Win32 and are summarized earlier
in this document.
=item Philip Gwyn
Philip Gwyn is <gwynp@artware.qc.ca>. He extended the Wheels I/O
abstraction to support hot-swappable filters, and he eventually
convinced me of the utility of unique session and kernel IDs. They
rock, by the way, and I'm sorry I didn't apply his patches sooner.
Philip also enhanced Filter::Reference to support different
serialization methods. His intangible contributions include the
discovery and/or destruction of several bugs (see the Changes file)
and a thorough code review around version 0.06.
=item Dave Paris
Dave Paris is <dparis@w3works.com>. Dave tested and benchmarked POE
around version 0.05, discovering some subtle (and not so subtle)
timing problems. The pre-forking server sample was his idea.
Versions 0.06 and later should scale to higher loads because of his
work. His intangible contributions include lots of testing and
feedback, much of which is tagged in the Changes file as a-mused.
And I do mean *lots* of testing. I go and announce a new development
version, and he's, like, "All tests passed!" just a few minutes later.
If that wasn't enough, he investigates any bugs that turn up, and
often fixes them. The man's scarily good.
=item Dieter Pearcey
Dieter Pearcey is <dieter@bullfrog.perlhacker.org>. He goes by
several Japanese nicknames. Dieter patched Wheel::FollowTail to be
more useful and has contributed the basic Filter::Block and its
documentation.
=item Robert Seifer
Robert Seifer is <e-mail unknown>. He rotates IRC nicknames
regularly.
Robert contributed entirely too much time, both his own and his
computers, towards the detection and eradication of a memory
corruption bug that POE tickled in earlier Perl versions. In the end,
his work produced a simple compile-time hack that worked around a
problem relating to anonymous subs, scope and @{} processing.
In short, he squashed a coredump with a reliable work-around.
=item Dennis Taylor
Dennis Taylor is <dennis@funkplanet.com>. Dennis has been testing,
debugging and patching bits here and there, such as Filter::Line which
he improved by leaps in 0.1102. He's also the author of
POE::Component::IRC, which isn't included here but may be found at
either <http://www.infobot.org/dev/POE/>.
=item Others?
Please contact the author if you've been forgotten.
=back
=head2 Author
=over 2
=item Rocco Caputo
Rocco Caputo is <troc+poe@netrus.net>. POE is his brainchild.
Except where otherwise noted, POE is Copyright 1998-2000 Rocco Caputo.
All rights reserved. POE is free software; you may redistribute it
and/or modify it under the same terms as Perl itself.
=back
Thank you for reading!
=cut