Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 92 lines (72 sloc) 2.494 kB
5a5072e @rcaputo Add an example of handling POE sig('DIE') from Reflex.
authored
1 #!/usr/bin/perl
2
3 # Build a new kind of Interval timer with a POE exception handler
4 # built into it. Jams the Reflex role for an interval timer together
5 # with the role for a signal handler.
6 #
7 # The goal is to have a convenient interval timer which can safely
8 # expose exceptions thrown from its callbacks. It's based on
9 # http://blog.afoolishmanifesto.com/archives/1682 and a question from
10 # fREW Schmidt on irc.perl.org #poe.
11 #
12 # Unfortunately lower-level event dispatchers (i.e., POE and the event
13 # loops it uses) don't know enough about higher-level consumers like
14 # Reflex to map exceptions back to specific objects. The
15 # RobustInterval catches die() globally via $SIG{__DIE__}. It doesn't
16 # know which object died, so it reports unhandled exceptions from
17 # anywhere.
18 #
19 # We need to think more carefully about what it means to throw
20 # exceptions from Reflex event handler callbacks. What extensible,
21 # sane things can be done with those exceptions?
22
23 {
24
25 package RobustInterval;
26
27 use Moose;
28 extends 'Reflex::Base';
29 use Reflex::Callbacks qw(make_emitter);
30
31 # Incorporate an interval timer.
32
33 has interval => (isa => 'Num', is => 'rw');
34 has auto_repeat => (isa => 'Bool', is => 'rw', default => 1);
35 has auto_start => (isa => 'Bool', is => 'ro', default => 1);
36
37 with 'Reflex::Role::Interval' => {
38 att_auto_repeat => "auto_repeat",
39 att_auto_start => "auto_start",
40 att_interval => "interval",
41 cb_tick => make_emitter(on_tick => "tick"),
42 method_repeat => "repeat_interval",
43 method_start => "start_interval",
44 method_stop => "stop_interval",
45 };
46
47 # Incorporate a signal watcher.
48
49 has signal => (is => 'ro', isa => 'Str', default => 'DIE');
50 has active => (is => 'ro', isa => 'Bool', default => 1);
51
52 with 'Reflex::Role::SigCatcher' => {
53 att_signal => 'signal',
54 att_active => 'active',
55 cb_signal => make_emitter(on_die => "die"),
56 method_start => 'start_signal',
57 method_stop => 'stop_signal',
58 method_pause => 'pause_signal',
59 method_resume => 'resume_signal',
60 };
61 }
62
63 ### Main.
64
65 use warnings;
66 use strict;
67
68 use Reflex;
69
70 sub event {
71 print "looped\n";
72 die "lol" if rand() < .5;
73 }
74
75 sub stumble {
76 my ($self) = @_;
77
78 warn "$self callback died... stumbling on";
79
80 $self->resume_signal(); # Resume watching for signals.
81 $self->repeat_interval(); # Continue the timer.
82 }
83
84 my $ct = RobustInterval->new(
85 interval => 1,
86 auto_repeat => 1,
87 on_tick => \&event,
88 on_die => \&stumble,
89 );
90
91 Reflex->run_all();
Something went wrong with that request. Please try again.