File Coverage

blib/lib/Reflex/Callback/Promise.pm
Criterion Covered Total %
statement 13 19 68.4
branch 1 2 50.0
condition 2 3 66.6
subroutine 4 5 80.0
pod 2 3 66.6
total 22 32 68.7


line stmt bran cond sub pod time code
1             package Reflex::Callback::Promise;
2             # vim: ts=2 sw=2 noexpandtab
3             $Reflex::Callback::Promise::VERSION = '0.100';
4 13     13   65 use Moose;
  13         14  
  13         72  
5             extends qw(Reflex::Callbacks Reflex::Callback);
6 13     13   54485 use Carp qw(confess);
  13         16  
  13         3393  
7              
8             has queue => (
9             is => 'rw',
10             isa => 'ArrayRef[ArrayRef]',
11             default => sub { [] },
12             );
13              
14             # TODO - 100 is hardcoded, but some people may want more or fewer.
15              
16             # Delivering to a promise enqueues the message.
17             sub deliver {
18 3     3 1 5 my ($self, $event) = @_;
19             confess "promise queue overflow in $self" if (
20 3 50       4 push(@{$self->queue()}, $event) > 100
  3         89  
21             );
22             }
23              
24             sub next {
25 3     3 1 39 my $self = shift;
26              
27 3         70 my $queue = $self->queue();
28              
29             # Run while the queue is empty and POE has things to do.
30 3   66     19 1 while (
31             @$queue < 1 and $POE::Kernel::poe_kernel->run_one_timeslice()
32             );
33              
34 3         146 return shift @$queue;
35             }
36              
37             sub merge_into {
38 0     0 0   my ($self, $other_promise) = @_;
39              
40             # Retain old queue for the moment.
41 0           my $old_queue = $self->queue();
42              
43             # Redirect this promise into the other promise's queue.
44 0           $self->queue( $other_promise->queue() );
45              
46             # If this promise contains events, move then into the other queue.
47             # TODO - Order is not maintained.
48 0           push @{$other_promise->queue()}, @$old_queue;
  0            
49              
50 0           undef;
51             }
52              
53             __PACKAGE__->meta->make_immutable;
54              
55             1;
56              
57             __END__
58              
59             =pod
60              
61             =encoding UTF-8
62              
63             =for :stopwords Rocco Caputo
64              
65             =head1 NAME
66              
67             Reflex::Callback::Promise - Non-callback, inline Promise adapter
68              
69             =head1 VERSION
70              
71             This document describes version 0.100, released on April 02, 2017.
72              
73             =head1 SYNOPSIS
74              
75             Used within Reflex:
76              
77             use Reflex::Interval;
78             use ExampleHelpers qw(eg_say);
79              
80             my $pt = Reflex::Interval->new(
81             interval => 1 + rand(),
82             auto_repeat => 1,
83             );
84              
85             while (my $event = $pt->next()) {
86             eg_say("promise timer returned an event (@$event)");
87             }
88              
89             Low-level usage:
90              
91             use Reflex::Callback::Promise;
92              
93             my $cb = Reflex::Callback::Promise->new();
94             $cb->deliver( greet => { name => "world" } );
95              
96             my $event = $cb->next();
97             print "event '$event->{name}': hello, $event->{arg}{name}\n";
98              
99             =head1 DESCRIPTION
100              
101             "In computer science, future, promise, and delay refer to constructs
102             used for synchronization in some concurrent programming languages.
103             They describe an object that acts as a proxy for a result that is
104             initially not known, usually because the computation of its value has
105             not yet completed." --
106             http://en.wikipedia.org/wiki/Promise_%28programming%29
107              
108             Reflex::Callback::Promise enables Reflex objects to be used as inline
109             event streams. Reflex::Callback::Promise and Reflex::Role::Reactive
110             transparently handle the conversion. Reflex objects do not need
111             special code to be used this way.
112              
113             In most cases, Reflex::Callbacks::cb_promise() or other syntactic
114             sweeteners will be used instead of raw Reflex::Callback::Promise
115             objects. For example, promises are implicitly enabled if no callbacks
116             are defined:
117              
118             my $t = Reflex::Interval->new(
119             interval => 1,
120             auto_repeat => 1,
121             );
122              
123             while (my $event = $t->next()) {
124             print "next() returned an event\n";
125             }
126              
127             =head2 new
128              
129             Reflex::Callback::Promise's constructor takes no parameters. It
130             creates a promise queue that is populated by deliver() and drained by
131             next(). Furthermore, next() will block as necessary until it can
132             return an event. This requires the help of some form of concurrency,
133             currently hardcoded to use POE.
134              
135             A future version may delegate the POE dependency to a subclass.
136              
137             =head2 next
138              
139             Reflex::Callback::Promise's next() method retrieves the next pending
140             event held in the object's queue. If the queue is empty, next() will
141             dispatch other events until some asynchronous code enqueues a new event
142             in the promise's queue.
143              
144             =head2 deliver
145              
146             Reflex::Callback::Promise's deliver() enqueues events for the promise.
147             As with other Reflex::Callback subclasses, this deliver() accepts two
148             positional parameters: an event name (which IS used), and a hashref of
149             named parameters to be passed to the callback.
150              
151             Deliver doesn't return anything meaningful, since the code to handle
152             the event isn't executed at the time of delivery.
153              
154             =for Pod::Coverage merge_into
155              
156             =head1 SEE ALSO
157              
158             Please see those modules/websites for more information related to this module.
159              
160             =over 4
161              
162             =item *
163              
164             L<Reflex|Reflex>
165              
166             =item *
167              
168             L<Reflex>
169              
170             =item *
171              
172             L<Reflex::Callback>
173              
174             =item *
175              
176             L<Reflex::Callbacks>
177              
178             =item *
179              
180             L<Reflex/ACKNOWLEDGEMENTS>
181              
182             =item *
183              
184             L<Reflex/ASSISTANCE>
185              
186             =item *
187              
188             L<Reflex/AUTHORS>
189              
190             =item *
191              
192             L<Reflex/BUGS>
193              
194             =item *
195              
196             L<Reflex/BUGS>
197              
198             =item *
199              
200             L<Reflex/CONTRIBUTORS>
201              
202             =item *
203              
204             L<Reflex/COPYRIGHT>
205              
206             =item *
207              
208             L<Reflex/LICENSE>
209              
210             =item *
211              
212             L<Reflex/TODO>
213              
214             =back
215              
216             =head1 BUGS AND LIMITATIONS
217              
218             You can make new bug reports, and view existing ones, through the
219             web interface at L<http://rt.cpan.org/Public/Dist/Display.html?Name=Reflex>.
220              
221             =head1 AUTHOR
222              
223             Rocco Caputo <rcaputo@cpan.org>
224              
225             =head1 COPYRIGHT AND LICENSE
226              
227             This software is copyright (c) 2017 by Rocco Caputo.
228              
229             This is free software; you can redistribute it and/or modify it under
230             the same terms as the Perl 5 programming language system itself.
231              
232             =head1 AVAILABILITY
233              
234             The latest version of this module is available from the Comprehensive Perl
235             Archive Network (CPAN). Visit L<http://www.perl.com/CPAN/> to find a CPAN
236             site near you, or see L<https://metacpan.org/module/Reflex/>.
237              
238             =head1 DISCLAIMER OF WARRANTY
239              
240             BECAUSE THIS SOFTWARE IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
241             FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT
242             WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER
243             PARTIES PROVIDE THE SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND,
244             EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
245             IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
246             PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
247             SOFTWARE IS WITH YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME
248             THE COST OF ALL NECESSARY SERVICING, REPAIR, OR CORRECTION.
249              
250             IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
251             WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
252             REDISTRIBUTE THE SOFTWARE AS PERMITTED BY THE ABOVE LICENCE, BE LIABLE
253             TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL, OR
254             CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
255             SOFTWARE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
256             RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
257             FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
258             SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
259             DAMAGES.
260              
261             =cut