File Coverage

blib/lib/IO/Async/Loop/Mojo.pm
Criterion Covered Total %
statement 103 104 99.0
branch 34 42 80.9
condition 4 6 66.6
subroutine 19 19 100.0
pod 8 9 88.8
total 168 180 93.3


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-2020 -- leonerd@leonerd.org.uk
5              
6             package IO::Async::Loop::Mojo;
7              
8 12     12   5596 use strict;
  12         24  
  12         295  
9 12     12   48 use warnings;
  12         23  
  12         424  
10              
11             our $VERSION = '0.07';
12 12     12   57 use constant API_VERSION => '0.76';
  12         21  
  12         718  
13              
14 12     12   60 use base qw( IO::Async::Loop );
  12         16  
  12         8213  
15             IO::Async::Loop->VERSION( '0.49' );
16              
17 12     12   149878 use Carp;
  12         31  
  12         610  
18              
19 12     12   4978 use Mojo::Reactor;
  12         2108062  
  12         128  
20 12     12   5475 use Mojo::IOLoop;
  12         980567  
  12         70  
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 new
48              
49             $loop = IO::Async::Loop::Mojo->new()
50              
51             This function returns a new instance of a C object. It
52             takes no special arguments.
53              
54             =cut
55              
56             sub new
57             {
58 12     12 1 608 my $class = shift;
59 12         98 my $self = $class->__new( @_ );
60              
61 12         608 $self->{reactor} = Mojo::IOLoop->singleton->reactor;
62              
63 12         103 return $self;
64             }
65              
66             sub is_running
67             {
68 1     1 0 16 my $self = shift;
69 1         6 return $self->{reactor}->is_running;
70             }
71              
72             =head1 METHODS
73              
74             There are no special methods in this subclass, other than those provided by
75             the C base class.
76              
77             =cut
78              
79             sub watch_io
80             {
81 16     16 1 152082 my $self = shift;
82 16         112 my %params = @_;
83              
84 16 50       92 my $handle = $params{handle} or croak "Expected 'handle'";
85 16         62 my $fd = $handle->fileno;
86              
87 16         91 my $reactor = $self->{reactor};
88              
89 16         27 my $cbs;
90 16   66     160 $cbs = $self->{io_cbs}{$fd} ||= do {
91             # Install the watch function
92             $reactor->io( $handle => sub {
93 30     30   2498298 my ( $reactor, $writable ) = @_;
94 30 100       92 if( $writable ) {
95 3 50       14 $cbs->[1]->() if $cbs->[1];
96             }
97             else {
98 27 50       251 $cbs->[0]->() if $cbs->[0];
99             }
100 15         191 } );
101              
102 15         568 [];
103             };
104              
105 16 100       406 if( my $on_read_ready = $params{on_read_ready} ) {
106 13         43 $cbs->[0] = $on_read_ready;
107             }
108              
109 16 100       37 if( my $on_write_ready = $params{on_write_ready} ) {
110 5         9 $cbs->[1] = $on_write_ready;
111             }
112              
113 16         62 $reactor->watch( $handle => defined $cbs->[0], defined $cbs->[1] );
114             }
115              
116             sub unwatch_io
117             {
118 10     10 1 6424 my $self = shift;
119 10         39 my %params = @_;
120              
121 10 50       31 my $handle = $params{handle} or croak "Expected 'handle'";
122 10         34 my $fd = $handle->fileno;
123              
124 10         61 my $reactor = $self->{reactor};
125              
126 10 50       27 my $cbs = $self->{io_cbs}{$fd} or return;
127              
128 10 100       25 if( $params{on_read_ready} ) {
129 7         27 undef $cbs->[0];
130             }
131              
132 10 100       23 if( $params{on_write_ready} ) {
133 5         15 undef $cbs->[1];
134             }
135              
136 10 100 66     46 if( defined $cbs->[0] or defined $cbs->[1] ) {
137 1         4 $reactor->watch( $handle => defined $cbs->[0], defined $cbs->[1] );
138             }
139             else {
140 9         25 $reactor->remove( $handle );
141 9         210 delete $self->{io_cbs}{$fd};
142             }
143             }
144              
145             sub watch_time
146             {
147 30     30 1 49028 my $self = shift;
148 30         275 my ( %params ) = @_;
149              
150 30         113 my $reactor = $self->{reactor};
151              
152 30         60 my $delay;
153 30 100       139 if( exists $params{at} ) {
    50          
154 1 50       7 my $now = exists $params{now} ? $params{now} : $self->time;
155              
156 1         7 $delay = delete($params{at}) - $now;
157             }
158             elsif( exists $params{after} ) {
159 29         69 $delay = delete $params{after};
160             }
161             else {
162 0         0 croak "Expected either 'at' or 'after' keys";
163             }
164              
165 30 100       101 $delay = 0 if $delay < 0;
166              
167 30         59 my $code = delete $params{code};
168              
169 30         61 my $id;
170              
171             my $once;
172             my $callback = sub {
173 12     12   7601903 my $reactor = shift;
174 12 50       87 $code->() unless $once++;
175 30         340 };
176              
177 30         249 return $reactor->timer( $delay => $callback );
178             }
179              
180             sub unwatch_time
181             {
182 19     19 1 1004 my $self = shift;
183 19         46 my ( $id ) = @_;
184              
185 19         37 my $reactor = $self->{reactor};
186              
187 19         59 $reactor->remove( $id );
188              
189 19         208 return;
190             }
191              
192             sub loop_once
193             {
194 51     51 1 33514 my $self = shift;
195 51         109 my ( $timeout ) = @_;
196 51         99 my $reactor = $self->{reactor};
197              
198 51         414 $self->_adjust_timeout( \$timeout );
199              
200 51         642 my $timeout_id;
201 51 100       126 if( defined $timeout ) {
202 50     16   362 $timeout_id = $reactor->timer( $timeout => sub {} );
203             }
204              
205 51         2373 $reactor->one_tick;
206              
207 51         3170 $self->_manage_queues;
208              
209 51 100       1090 $reactor->remove( $timeout_id ) if $timeout_id;
210             }
211              
212             sub run
213             {
214 5     5 1 390 my $self = shift;
215 5         10 my $reactor = $self->{reactor};
216              
217 5         8 my $result = [];
218             # Not all Mojo::Reactor classes cope well with nested invocations
219 5 100       16 if( !exists $self->{result} ) {
220 4         11 local $self->{result} = $result;
221 4         16 $reactor->start;
222             }
223             else {
224 1         3 local $self->{result} = $result;
225 1         4 local $self->{running} = 1;
226 1         9 $reactor->one_tick while $self->{running};
227             }
228              
229 5 100       114 return wantarray ? @$result : $result->[0];
230             }
231              
232             sub stop
233             {
234 5     5 1 36 my $self = shift;
235 5         8 @{ $self->{result} } = @_;
  5         15  
236              
237 5 100       24 $self->{running} ? undef $self->{running} : $self->{reactor}->stop;
238             }
239              
240             =head1 AUTHOR
241              
242             Paul Evans
243              
244             =cut
245              
246             0x55AA;