File Coverage

blib/lib/Loop/Flow/Object.pm
Criterion Covered Total %
statement 12 66 18.1
branch 0 26 0.0
condition 0 18 0.0
subroutine 4 9 44.4
pod 3 5 60.0
total 19 124 15.3


line stmt bran cond sub pod time code
1             package Loop::Flow::Object;
2              
3 1     1   243980 use 5.006;
  1         4  
  1         49  
4 1     1   7 use strict;
  1         3  
  1         43  
5 1     1   6 use warnings;
  1         6  
  1         42  
6              
7 1     1   1075 use POSIX ':sys_wait_h'; # для waitpid -1, WNOHANG;
  1         8375  
  1         9  
8              
9             =encoding utf8
10              
11             =head1 ПРИВЕТСТВИЕ SALUTE
12              
13             Доброго всем! Доброго здоровья! Доброго духа!
14              
15             Hello all! Nice health! Good thinks!
16              
17             =head1 NAME
18              
19             Loop::Flow::Object - запуск цикла для объекта с контролем и переключением ветвления (fork), выполнение кода в указанных методах объекта.
20              
21             Loop::Flow::Object - looping code of one object with forking on/off. Simple switch and count of forks.
22              
23             Executing code, control count and exit from loop by the object methods.
24              
25              
26             =head1 VERSION
27              
28             Version 0.03
29              
30             =cut
31              
32             our $VERSION = '0.03';
33              
34              
35             =head1 SYNOPSIS
36              
37             package Some::My::Module;
38            
39             sub new {
40             my $class = shift;
41             ...
42            
43             }
44             sub one {# main code in loop
45             my $self = shift;
46             my @data = @_;
47             ...
48             }
49            
50             sub data {# data for main code in loop
51             my $self = shift;
52             my $count = shift;
53             ...
54             }
55            
56             sub end {# end hook
57             my $self = shift;
58             ....
59             }
60            
61             package main;
62            
63             use Loop::Flow::Object;
64             use Some::My::Module;
65            
66             my $obj = Some::My::Module->new(...);
67            
68             my $loop = Loop::Flow::Object->new(max_count=>..., forks=>..., debug=>...);
69             $loop->start($obj, main=>'one', data=>'data', end=>'end',);
70             ...
71              
72              
73              
74             =head1 EXPORT
75              
76             None.
77              
78             =head1 METHODS
79              
80             =cut
81              
82             =head2 new(max_count=>..., forks=>..., debug=>...)
83              
84             Options:
85              
86             =over 4
87              
88             =item * B => (optional)
89              
90             infinitely looping if max_count => 0 || undef (default)
91              
92             =item * B => (optional)
93              
94             Limit of forks
95            
96             No forking, sequentially if forks => 0 || undef (default)
97              
98              
99              
100             =item * B => 0|1 (optional)
101              
102             0 - no print msg (default)
103              
104             =back
105             =cut
106              
107             sub new {
108 0     0 1   my $class = shift;
109 0           my $self = {
110             max_count=>undef,
111             forks => undef,
112             debug => undef,
113             @_,
114             };
115 0           bless $self, $class;
116 0           return $self;
117             }
118              
119             =head2 start($obj, main=>'', data=>'', end=>'',)
120              
121             Looping/forking for $obj which have methods:
122              
123             =over 4
124              
125             =item * B
=> string '' - main code which execute in loop (as child process if forks) (mandatory)
126              
127             =item * B => string '' - hook which get/return data for ''
128              
129             Returning list of data will pass to the main method.
130              
131             B. If you define this method and it's return B - WILL STOPS THE LOOPING, but will wait for childs if any.
132              
133             =item * B => string '' - hook which execute when end the '' of one loop (child process exit if forks)
134              
135             =cut
136              
137             sub start {
138 0     0 1   my $self = shift;
139 0           my $obj = shift;
140 0           my %meths = (@_);
141 0           my %stack = ();# для $self->{forks} = undef останется пустой
142 0           my $count = 0;
143             #~ while ( %stack != 0 || !$self->{max_count} || $count < $self->{max_count} ) {# ПОЕХАЛИ
144 0   0       until ( scalar keys %stack == 0 && $self->{max_count} && $count == $self->{max_count} ) {# ПОЕХАЛИ (с)
      0        
145             #~ print "START: ", (map {"[$_], "} (%stack != 0, !$self->{max_count}, $count < $self->{max_count})),"\n",;
146 0 0 0       if ((!$self->{max_count} || $count < $self->{max_count}) && (!$self->{forks} || scalar keys %stack < $self->{forks})) {
      0        
      0        
147 0           my @data = $self->data($obj, $meths{data}, $count);# данные, отправляемые в основной метод
148 0 0         last unless @data;
149 0           my $pid = $self->start_main($obj, $meths{main}, @data,);
150 0 0         $stack{$pid}++ if $pid;
151 0           $count++;
152             }
153            
154 0 0 0       if ($self->{forks} && (my @pids = $self->check_child()) ) {
155 0           delete @stack{ @pids };
156             }
157            
158             }
159            
160 0           while (scalar keys %stack) {
161 0           my @pids = $self->check_child();
162 0           delete @stack{ @pids };
163             }
164             }
165              
166             sub data {
167 0     0 1   my $self = shift;
168 0           my $obj = shift;
169 0           my $meth_str = shift;
170 0           my $count = shift;
171            
172 0 0         if ($meth_str) {
173 0           my $meth = $obj->can($meth_str);
174 0 0         die "Не найден метод [$meth_str] объекта/модуля [$obj]" unless $meth;
175 0           return $obj->$meth(@_);
176             } else {
177 0           return $count;
178             }
179             }
180              
181             sub start_main {# может не форк
182 0     0 0   my $self = shift;
183 0           my $obj = shift;
184 0           my $meth_str = shift;
185            
186 0           my $meth = $obj->can($meth_str);
187 0 0         die "Не найден метод [$meth_str] объекта/модуля [$obj]" unless $meth;
188              
189 0 0         my $pid = $self->{forks} ? fork() : 0;#
190 0 0         if( $pid ) {# parent
    0          
191             #~ print "{$$} PARENT: running child pid={$pid}\n" if $self->{debug};
192 0           return $pid;
193             } elsif ($pid == 0) {# child or sequential
194             #~ print "make_child: ", Dumper(\@_),
195 0           $obj->$meth(@_);
196            
197 0 0         if ($self->{forks}) {
198 0 0         print "{$$} CHILD: iam done!\n" if $self->{debug};
199 0           exit 0;
200             } else {
201 0           return undef;
202             }
203             } else {
204 0           die "couldnt fork: $!\n";
205             }
206              
207             }
208              
209             sub check_child {# просто проверить и вернуть иды завершенных процессов для delete from %stack
210 0     0 0   my $self = shift;
211 0           my $pid;
212 0           my @pids = ();
213 0           while (1) {#$pid > 0do
214 0           $pid = waitpid(-1, WNOHANG);
215 0 0         if ($pid > 0) {
  0            
216 0           print "Parent: done child pid=$pid \$?=[$?];\n";
217 0           push(@pids, $pid);
218             } else {last;}
219             }
220 0           return @pids;
221             }
222              
223              
224             =head1 AUTHOR
225              
226             Mikhail Che, C<< >>
227              
228             =head1 BUGS
229              
230             Please report any bugs or feature requests to C, or through
231             the web interface at L. I will be notified, and then you'll
232             automatically be notified of progress on your bug as I make changes.
233              
234              
235              
236              
237             =head1 SUPPORT
238              
239             You can find documentation for this module with the perldoc command.
240              
241             perldoc Loop::Flow::Object
242              
243              
244             You can also look for information at:
245              
246             =over 4
247              
248             =item * RT: CPAN's request tracker (report bugs here)
249              
250             L
251              
252             =item * AnnoCPAN: Annotated CPAN documentation
253              
254             L
255              
256             =item * CPAN Ratings
257              
258             L
259              
260             =item * Search CPAN
261              
262             L
263              
264             =back
265              
266              
267             =head1 ACKNOWLEDGEMENTS
268              
269              
270             =head1 LICENSE AND COPYRIGHT
271              
272             Copyright 2012 Mikhail Che.
273              
274             This program is free software; you can redistribute it and/or modify it
275             under the terms of either: the GNU General Public License as published
276             by the Free Software Foundation; or the Artistic License.
277              
278             See http://dev.perl.org/licenses/ for more information.
279              
280              
281             =cut
282              
283             1; # End of Loop::Flow::Object