Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 92 lines (72 sloc) 2.494 kb
5a5072e Rocco Caputo 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.