File Coverage

blib/lib/IO/Async/Loop/Mojo.pm
Criterion Covered Total %
statement 102 103 99.0
branch 32 38 84.2
condition 4 6 66.6
subroutine 18 18 100.0
pod 8 8 100.0
total 164 173 94.8


line stmt bran cond sub pod time code
1             # You may distribute under the terms of either the GNU General Public License
2             # or the Artistic License (the same terms as Perl itself)
3             #
4             # (C) Paul Evans, 2012-2013 -- leonerd@leonerd.org.uk
5              
6             package IO::Async::Loop::Mojo;
7              
8 11     11   14671 use strict;
  11         30  
  11         388  
9 11     11   65 use warnings;
  11         14  
  11         576  
10              
11             our $VERSION = '0.05';
12 11     11   205 use constant API_VERSION => '0.49';
  11         20  
  11         818  
13              
14 11     11   55 use base qw( IO::Async::Loop );
  11         22  
  11         13695  
15             IO::Async::Loop->VERSION( '0.49' );
16              
17 11     11   165666 use Carp;
  11         32  
  11         838  
18              
19 11     11   10285 use Mojo::Reactor;
  11         4593728  
  11         146  
20 11     11   12044 use Mojo::IOLoop;
  11         4026086  
  11         72  
21              
22             =head1 NAME
23              
24             C - use C with C
25              
26             =head1 SYNOPSIS
27              
28             use IO::Async::Loop::Mojo;
29              
30             my $loop = IO::Async::Loop::Mojo->new();
31              
32             $loop->add( ... );
33              
34             ...
35             # Rest of Mojolicious code here
36              
37             =head1 DESCRIPTION
38              
39             This subclass of L uses L to perform its IO
40             operations. It allows the use of L-based code or modules from
41             within a L application.
42              
43             =head1 CONSTRUCTOR
44              
45             =cut
46              
47             =head2 $loop = IO::Async::Loop::Mojo->new()
48              
49             This function returns a new instance of a C object. It
50             takes no special arguments.
51              
52             =cut
53              
54             sub new
55             {
56 11     11 1 1025 my $class = shift;
57 11         118 my $self = $class->__new( @_ );
58              
59 11         869 $self->{reactor} = Mojo::IOLoop->singleton->reactor;
60              
61 11         423 return $self;
62             }
63              
64             =head1 METHODS
65              
66             There are no special methods in this subclass, other than those provided by
67             the C base class.
68              
69             =cut
70              
71             sub watch_io
72             {
73 12     12 1 153813 my $self = shift;
74 12         103 my %params = @_;
75              
76 12 50       91 my $handle = $params{handle} or croak "Expected 'handle'";
77 12         105 my $fd = $handle->fileno;
78              
79 12         83 my $reactor = $self->{reactor};
80              
81 12         25 my $cbs;
82 12   66     118 $cbs = $self->{io_cbs}{$fd} ||= do {
83             # Install the watch function
84             $reactor->io( $handle => sub {
85 24     24   1777724 my ( $reactor, $writable ) = @_;
86 24 100       103 if( $writable ) {
87 2         8 $cbs->[1]->();
88             }
89             else {
90 22         122 $cbs->[0]->();
91             }
92 11         292 } );
93              
94 11         1622 [];
95             };
96              
97 12 100       99 if( my $on_read_ready = $params{on_read_ready} ) {
98 11         34 $cbs->[0] = $on_read_ready;
99             }
100              
101 12 100       45 if( my $on_write_ready = $params{on_write_ready} ) {
102 3         7 $cbs->[1] = $on_write_ready;
103             }
104              
105 12         71 $reactor->watch( $handle => defined $cbs->[0], defined $cbs->[1] );
106             }
107              
108             sub unwatch_io
109             {
110 7     7 1 6199 my $self = shift;
111 7         35 my %params = @_;
112              
113 7 50       34 my $handle = $params{handle} or croak "Expected 'handle'";
114 7         71 my $fd = $handle->fileno;
115              
116 7         56 my $reactor = $self->{reactor};
117              
118 7 50       34 my $cbs = $self->{io_cbs}{$fd} or return;
119              
120 7 100       25 if( $params{on_read_ready} ) {
121 6         20 undef $cbs->[0];
122             }
123              
124 7 100       40 if( $params{on_write_ready} ) {
125 3         7 undef $cbs->[1];
126             }
127              
128 7 100 66     64 if( defined $cbs->[0] or defined $cbs->[1] ) {
129 1         5 $reactor->watch( $handle => defined $cbs->[0], defined $cbs->[1] );
130             }
131             else {
132 6         28 $reactor->remove( $handle );
133 6         586 delete $self->{io_cbs}{$fd};
134             }
135             }
136              
137             sub watch_time
138             {
139 26     26 1 85268 my $self = shift;
140 26         312 my ( %params ) = @_;
141              
142 26         98 my $reactor = $self->{reactor};
143              
144 26         49 my $delay;
145 26 100       187 if( exists $params{at} ) {
    50          
146 1 50       7 my $now = exists $params{now} ? $params{now} : $self->time;
147              
148 1         8 $delay = delete($params{at}) - $now;
149             }
150             elsif( exists $params{after} ) {
151 25         90 $delay = delete $params{after};
152             }
153             else {
154 0         0 croak "Expected either 'at' or 'after' keys";
155             }
156              
157 26 100       116 $delay = 0 if $delay < 0;
158              
159 26         98 my $code = delete $params{code};
160              
161 26         59 my $id;
162              
163             my $once;
164             my $callback = sub {
165 12     12   8599975 my $reactor = shift;
166 12 50       132 $code->() unless $once++;
167 26         274 };
168              
169 26         315 return $reactor->timer( $delay => $callback );
170             }
171              
172             sub unwatch_time
173             {
174 15     15 1 889 my $self = shift;
175 15         34 my ( $id ) = @_;
176              
177 15         40 my $reactor = $self->{reactor};
178              
179 15         60 $reactor->remove( $id );
180              
181 15         203 return;
182             }
183              
184             sub loop_once
185             {
186 45     45 1 31783 my $self = shift;
187 45         75 my ( $timeout ) = @_;
188 45         95 my $reactor = $self->{reactor};
189              
190 45         334 $self->_adjust_timeout( \$timeout );
191              
192 45         729 my $timeout_id;
193 45 100       150 if( defined $timeout ) {
194 44     15   508 $timeout_id = $reactor->timer( $timeout => sub {} );
  15         8406160  
195             }
196              
197 45         2630 $reactor->one_tick;
198              
199 45         3718 $self->_manage_queues;
200              
201 45 100       986 $reactor->remove( $timeout_id ) if $timeout_id;
202             }
203              
204             sub run
205             {
206 5     5 1 464 my $self = shift;
207 5         11 my $reactor = $self->{reactor};
208              
209 5         15 my $result = [];
210             # Not all Mojo::Reactor classes cope well with nested invocations
211 5 100       23 if( !exists $self->{result} ) {
212 4         13 local $self->{result} = $result;
213 4         17 $reactor->start;
214             }
215             else {
216 1         5 local $self->{result} = $result;
217 1         5 local $self->{running} = 1;
218 1         17 $reactor->one_tick while $self->{running};
219             }
220              
221 5 100       186 return wantarray ? @$result : $result->[0];
222             }
223              
224             sub stop
225             {
226 5     5 1 90 my $self = shift;
227 5         13 @{ $self->{result} } = @_;
  5         27  
228              
229 5 100       47 $self->{running} ? undef $self->{running} : $self->{reactor}->stop;
230             }
231              
232             =head1 AUTHOR
233              
234             Paul Evans
235              
236             =cut
237              
238             0x55AA;