File Coverage

blib/lib/IO/Async/Loop/Mojo.pm
Criterion Covered Total %
statement 101 102 99.0
branch 34 42 80.9
condition 4 6 66.6
subroutine 18 18 100.0
pod 8 8 100.0
total 165 176 93.7


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-2019 -- leonerd@leonerd.org.uk
5              
6             package IO::Async::Loop::Mojo;
7              
8 11     11   22190 use strict;
  11         22  
  11         264  
9 11     11   45 use warnings;
  11         22  
  11         402  
10              
11             our $VERSION = '0.06';
12 11     11   48 use constant API_VERSION => '0.49';
  11         13  
  11         718  
13              
14 11     11   52 use base qw( IO::Async::Loop );
  11         18  
  11         7027  
15             IO::Async::Loop->VERSION( '0.49' );
16              
17 11     11   137912 use Carp;
  11         25  
  11         544  
18              
19 11     11   4709 use Mojo::Reactor;
  11         1976200  
  11         156  
20 11     11   5775 use Mojo::IOLoop;
  11         702860  
  11         61  
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 630 my $class = shift;
57 11         157 my $self = $class->__new( @_ );
58              
59 11         543 $self->{reactor} = Mojo::IOLoop->singleton->reactor;
60              
61 11         89 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 14     14 1 144350 my $self = shift;
74 14         59 my %params = @_;
75              
76 14 50       103 my $handle = $params{handle} or croak "Expected 'handle'";
77 14         63 my $fd = $handle->fileno;
78              
79 14         111 my $reactor = $self->{reactor};
80              
81 14         56 my $cbs;
82 14   66     81 $cbs = $self->{io_cbs}{$fd} ||= do {
83             # Install the watch function
84             $reactor->io( $handle => sub {
85 24     24   1562064 my ( $reactor, $writable ) = @_;
86 24 100       66 if( $writable ) {
87 3 50       14 $cbs->[1]->() if $cbs->[1];
88             }
89             else {
90 21 50       132 $cbs->[0]->() if $cbs->[0];
91             }
92 13         178 } );
93              
94 13         437 [];
95             };
96              
97 14 100       296 if( my $on_read_ready = $params{on_read_ready} ) {
98 11         33 $cbs->[0] = $on_read_ready;
99             }
100              
101 14 100       32 if( my $on_write_ready = $params{on_write_ready} ) {
102 5         12 $cbs->[1] = $on_write_ready;
103             }
104              
105 14         49 $reactor->watch( $handle => defined $cbs->[0], defined $cbs->[1] );
106             }
107              
108             sub unwatch_io
109             {
110 9     9 1 8174 my $self = shift;
111 9         29 my %params = @_;
112              
113 9 50       26 my $handle = $params{handle} or croak "Expected 'handle'";
114 9         30 my $fd = $handle->fileno;
115              
116 9         50 my $reactor = $self->{reactor};
117              
118 9 50       28 my $cbs = $self->{io_cbs}{$fd} or return;
119              
120 9 100       21 if( $params{on_read_ready} ) {
121 6         22 undef $cbs->[0];
122             }
123              
124 9 100       22 if( $params{on_write_ready} ) {
125 5         15 undef $cbs->[1];
126             }
127              
128 9 100 66     40 if( defined $cbs->[0] or defined $cbs->[1] ) {
129 1         4 $reactor->watch( $handle => defined $cbs->[0], defined $cbs->[1] );
130             }
131             else {
132 8         24 $reactor->remove( $handle );
133 8         187 delete $self->{io_cbs}{$fd};
134             }
135             }
136              
137             sub watch_time
138             {
139 26     26 1 40714 my $self = shift;
140 26         189 my ( %params ) = @_;
141              
142 26         88 my $reactor = $self->{reactor};
143              
144 26         59 my $delay;
145 26 100       119 if( exists $params{at} ) {
    50          
146 1 50       7 my $now = exists $params{now} ? $params{now} : $self->time;
147              
148 1         7 $delay = delete($params{at}) - $now;
149             }
150             elsif( exists $params{after} ) {
151 25         60 $delay = delete $params{after};
152             }
153             else {
154 0         0 croak "Expected either 'at' or 'after' keys";
155             }
156              
157 26 100       87 $delay = 0 if $delay < 0;
158              
159 26         52 my $code = delete $params{code};
160              
161 26         47 my $id;
162              
163             my $once;
164             my $callback = sub {
165 12     12   8601864 my $reactor = shift;
166 12 50       148 $code->() unless $once++;
167 26         284 };
168              
169 26         340 return $reactor->timer( $delay => $callback );
170             }
171              
172             sub unwatch_time
173             {
174 15     15 1 817 my $self = shift;
175 15         35 my ( $id ) = @_;
176              
177 15         34 my $reactor = $self->{reactor};
178              
179 15         47 $reactor->remove( $id );
180              
181 15         145 return;
182             }
183              
184             sub loop_once
185             {
186 45     45 1 24263 my $self = shift;
187 45         95 my ( $timeout ) = @_;
188 45         85 my $reactor = $self->{reactor};
189              
190 45         298 $self->_adjust_timeout( \$timeout );
191              
192 45         630 my $timeout_id;
193 45 100       116 if( defined $timeout ) {
194 44     16   315 $timeout_id = $reactor->timer( $timeout => sub {} );
195             }
196              
197 45         2116 $reactor->one_tick;
198              
199 45         2369 $self->_manage_queues;
200              
201 45 100       868 $reactor->remove( $timeout_id ) if $timeout_id;
202             }
203              
204             sub run
205             {
206 5     5 1 339 my $self = shift;
207 5         11 my $reactor = $self->{reactor};
208              
209 5         12 my $result = [];
210             # Not all Mojo::Reactor classes cope well with nested invocations
211 5 100       15 if( !exists $self->{result} ) {
212 4         11 local $self->{result} = $result;
213 4         15 $reactor->start;
214             }
215             else {
216 1         3 local $self->{result} = $result;
217 1         4 local $self->{running} = 1;
218 1         10 $reactor->one_tick while $self->{running};
219             }
220              
221 5 100       106 return wantarray ? @$result : $result->[0];
222             }
223              
224             sub stop
225             {
226 5     5 1 45 my $self = shift;
227 5         18 @{ $self->{result} } = @_;
  5         17  
228              
229 5 100       35 $self->{running} ? undef $self->{running} : $self->{reactor}->stop;
230             }
231              
232             =head1 AUTHOR
233              
234             Paul Evans
235              
236             =cut
237              
238             0x55AA;