File Coverage

blib/lib/Deeme.pm
Criterion Covered Total %
statement 86 89 96.6
branch 26 28 92.8
condition 7 16 43.7
subroutine 16 17 94.1
pod 10 10 100.0
total 145 160 90.6


line stmt bran cond sub pod time code
1             package Deeme;
2 4     4   39994 use strict;
  4         10  
  4         127  
3 4     4   100 use 5.008_005;
  4         10  
  4         208  
4             our $VERSION = '0.04';
5 4     4   1089 use Deeme::Obj -base;
  4         9  
  4         44  
6 4     4   19 use Carp 'croak';
  4         6  
  4         265  
7             has 'backend';
8 4     4   25 use Scalar::Util qw(blessed weaken);
  4         8  
  4         473  
9 4   50 4   600 use constant DEBUG => $ENV{DEEME_DEBUG} || 0;
  4         8  
  4         5978  
10              
11             sub new {
12 4     4 1 256 my $self = shift;
13 4         32 $self = $self->SUPER::new(@_);
14 4 100       123 if ( !$self->backend ) {
15 2         727 require Deeme::Backend::Memory;
16 2         22 $self->backend( Deeme::Backend::Memory->new );
17             }
18 4         88 $self->backend->deeme($self);
19 4         11 return $self;
20             }
21              
22 1 50   1 1 558 sub catch { $_[0]->on( error => $_[1] ) and return $_[0] }
23              
24             sub emit {
25 30     30 1 1651 my ( $self, $name ) = ( shift, shift );
26              
27 30 100       756 if ( my $s = $self->backend->events_get($name) ) {
28 18         19 warn "-- Emit $name in @{[blessed $self]} (@{[scalar @$s]})\n"
29             if DEBUG;
30 18         386 my @onces = $self->backend->events_onces($name);
31 18         40 my $i = 0;
32 18         31 for my $cb (@$s) {
33 23 100 33     83 ( $onces[$i] == 1 )
34             ? ( splice( @onces, $i, 1 )
35             and $self->_unsubscribe_index( $name => $i ) )
36             : $i++;
37 23         71 $self->$cb(@_);
38             }
39             }
40             else {
41 12         14 warn "-- Emit $name in @{[blessed $self]} (0)\n" if DEBUG;
42 12 100       32 die "@{[blessed $self]}: $_[0]" if $name eq 'error';
  2         32  
43             }
44              
45 26         109 return $self;
46             }
47              
48             sub emit_safe {
49 5     5 1 592 my ( $self, $name ) = ( shift, shift );
50              
51 5 100       119 if ( my $s = $self->backend->events_get($name) ) {
52 4         5 warn "-- Emit $name in @{[blessed $self]} safely (@{[scalar @$s]})\n"
53             if DEBUG;
54 4         89 my @onces = $self->backend->events_onces($name);
55 4         8 my $i = 0;
56 4         9 for my $cb (@$s) {
57             $self->emit( error => qq{Event "$name" failed: $@} )
58 9 100       10 unless eval {
59 9 100 33     27 ( $onces[$i] == 1 )
60             ? ( splice( @onces, $i, 1 )
61             and $self->_unsubscribe_index( $name => $i ) )
62             : $i++;
63 9         22 $self->$cb(@_);
64 6         34 1;
65             };
66             }
67             }
68             else {
69 1         3 warn "-- Emit $name in @{[blessed $self]} safely (0)\n" if DEBUG;
70 1 50       5 die "@{[blessed $self]}: $_[0]" if $name eq 'error';
  1         13  
71             }
72              
73 3         8 return $self;
74             }
75              
76 3     3 1 9 sub has_subscribers { !!@{ shift->subscribers(shift) } }
  3         8  
77              
78             sub on {
79 11     11 1 1122 my ( $self, $name, $cb ) = @_;
80 11         13 warn "-- on $name in @{[blessed $self]}\n"
81             if DEBUG;
82 11   50     250 return $self->backend->event_add( $name, $cb ||= [], 0 );
83             }
84              
85             sub once {
86 18     18 1 1611 my ( $self, $name, $cb ) = @_;
87 18         18 warn "-- once $name in @{[blessed $self]}\n"
88             if DEBUG;
89 18   50     416 return $self->backend->event_add( $name, $cb ||= [], 1 );
90             }
91              
92 18 100   18 1 445 sub subscribers { shift->backend->events_get( shift(), 0 ) || [] }
93              
94             sub unsubscribe {
95 6     6 1 12 my ( $self, $name, $cb ) = @_;
96              
97             # One
98 6 100       13 if ($cb) {
99 5         7 my @events = @{ $self->backend->events_get( $name, 0 ) };
  5         153  
100 5         108 my @onces = $self->backend->events_onces($name);
101              
102 5         14 my ($index) = grep { $cb eq $events[$_] } 0 .. $#events;
  12         39  
103 5 100       19 if ( defined $index ) {
104              
105 4         8 splice @events, $index, 1;
106 4         8 splice @onces, $index, 1;
107 4 100 50     33 $self->backend->event_delete($name) and return $self
108             unless @events;
109 3         63 $self->backend->event_update( $name, \@events, 0 );
110 3         62 $self->backend->once_update( $name, \@onces );
111             }
112             }
113              
114             # All
115 1         30 else { $self->backend->event_delete($name); }
116              
117 5         13 return $self;
118             }
119              
120             sub reset {
121 0     0 1 0 my $self = shift;
122 0         0 $self->backend->events_reset;
123 0         0 return $self;
124             }
125              
126             sub _unsubscribe_index {
127 17     17   24 my ( $self, $name, $index ) = @_;
128              
129 17         19 my @events = @{ $self->backend->events_get( $name, 0 ) };
  17         359  
130 17         356 my @onces = $self->backend->events_onces($name);
131              
132 17         32 splice @events, $index, 1;
133 17         18 splice @onces, $index, 1;
134 17 100 50     295 $self->backend->event_delete($name) and return $self
135             unless @events;
136 4         87 $self->backend->event_update( $name, [@events], 0 );
137 4         84 $self->backend->once_update( $name, \@onces );
138              
139 4         12 return $self;
140             }
141              
142              
143             1;
144             __END__