File Coverage

blib/lib/ProgressMonitor/SubTask.pm
Criterion Covered Total %
statement 58 72 80.5
branch 6 14 42.8
condition 2 8 25.0
subroutine 14 19 73.6
pod 5 8 62.5
total 85 121 70.2


line stmt bran cond sub pod time code
1             package ProgressMonitor::SubTask;
2            
3 10     10   195 use warnings;
  10         20  
  10         292  
4 10     10   52 use strict;
  10         15  
  10         615  
5            
6             require ProgressMonitor::AbstractStatefulMonitor if 0;
7            
8             # Attributes:
9             # scale
10             # keeps track of the amount we need to scale ticks when reporting to parent
11             # sentToParent
12             # keeps track of the tick amount reported to parent
13             #
14             use classes
15 10         61 extends => 'ProgressMonitor::AbstractStatefulMonitor',
16             new => 'new',
17             attrs_pr => ['scale', 'sentToParent',],
18 10     10   49 ;
  10         17  
19            
20             sub new
21             {
22 1     1   18 my $class = shift;
23 1         1 my $cfg = shift;
24            
25             # call the protected super ctor
26             #
27 1         103 my $self = $class->_new($cfg, $CLASS);
28            
29             # init our instance vars
30             #
31 1         4 $self->{$ATTR_scale} = 0;
32 1         3 $self->{$ATTR_sentToParent} = 0;
33            
34 1         15 return $self;
35             }
36            
37             sub begin
38             {
39 1     1 1 7 my $self = shift;
40 1         2 my $totalTicks = shift;
41            
42             # call the super class to keep track of state
43             #
44 1         6 $self->SUPER::begin($totalTicks);
45            
46             # initialize us
47             # store the scale we should use (keep in mind we might get 'unknown' or a wacky number)
48             #
49 1 50 33     14 $self->{$ATTR_scale} = (!defined($totalTicks) || $totalTicks <= 0) ? 0 : $self->_get_cfg->get_parentTicks / $totalTicks;
50 1         7 $self->{$ATTR_sentToParent} = 0;
51            
52 1         2 return;
53             }
54            
55             sub end
56             {
57 1     1 1 8 my $self = shift;
58            
59             # call the super class to keep track of state
60             #
61 1         12 $self->SUPER::end;
62            
63             # if we still have ticks not 'tocked', make sure to do that before closing shop
64             #
65 1         3 my $cfg = $self->_get_cfg;
66 1         3 my $remains = $cfg->get_parentTicks - $self->{$ATTR_sentToParent};
67 1 50       13 $cfg->get_parent->tick($remains) if ($remains > $self->{$ATTR_scale});
68            
69 1         3 return;
70             }
71            
72             sub isCanceled
73             {
74 0     0 1 0 my $self = shift;
75            
76             # propagate this to the parent
77             #
78 0         0 return $self->_get_cfg->get_parent->isCanceled(@_);
79             }
80            
81             sub setCanceled
82             {
83 0     0 1 0 my $self = shift;
84            
85             # propagate this to the parent
86             #
87 0         0 return $self->_get_cfg->get_parent->setCanceled(@_);
88             }
89            
90             sub setErrorMessage
91             {
92 0     0 0 0 my $self = shift;
93            
94             # propagate this to the parent
95             #
96 0         0 return $self->_get_cfg->get_parent->setErrorMessage(@_);
97             }
98            
99             sub tick
100             {
101 10     10 1 30 my $self = shift;
102 10         11 my $ticks = shift;
103            
104             # call the super class to keep track of state
105             #
106 10         29 $self->SUPER::tick($ticks);
107            
108             # use the scale to calculate the actual ticks to be handled by the parent
109             #
110 10 50       22 my $realTicks = $ticks ? $self->{$ATTR_scale} * $ticks : 0;
111 10         23 $self->_get_cfg->get_parent->tick($realTicks);
112 10         22 $self->{$ATTR_sentToParent} += $realTicks;
113            
114 10         19 return;
115             }
116            
117             sub render
118 13     13 0 21 {
119             # noop
120             # just trap any calls by the super class - rendering is done by the parent
121             # when it gets 'tick' calls from us
122             #
123             }
124            
125             sub subMonitor
126             {
127 0     0 0 0 my $self = shift;
128 0   0     0 my $subCfg = shift || {};
129            
130 0         0 $subCfg->{parent} = $self;
131 0         0 return ProgressMonitor::SubTask->new($subCfg);
132             }
133            
134             sub _set_message
135             {
136 0     0   0 my $self = shift;
137 0         0 my $msg = shift;
138            
139             # propagate this to the parent if we're set that way
140             #
141 0         0 my $cfg = $self->_get_cfg;
142 0 0       0 $cfg->get_parent->setMessage($msg) if $cfg->get_passMessageToParent;
143             }
144            
145             ###
146            
147             package ProgressMonitor::SubTaskConfiguration;
148            
149 10     10   9015 use strict;
  10         17  
  10         365  
150 10     10   89 use warnings;
  10         15  
  10         325  
151            
152 10     10   49 use Scalar::Util qw(blessed);
  10         20  
  10         832  
153            
154             # The configuration class - ensure to extend in the parallel hierarchy as the main class
155             #
156             # Attributes:
157             # parent
158             # The parent monitor we wrap
159             # parentTicks
160             # The number of ticks we should use out of the parent, scaled by the ticks we
161             # ourself is told to handle
162             # passMessageToParent
163             # Set to true if 'setMessage' calls should be passed to parent
164             #
165             use classes
166 10         55 extends => 'ProgressMonitor::AbstractStatefulMonitorConfiguration',
167             attrs => ['parent', 'parentTicks', 'passMessageToParent'],
168 10     10   49 ;
  10         22  
169            
170             sub defaultAttributeValues
171             {
172 1     1   2 my $self = shift;
173            
174 1         2 return {%{$self->SUPER::defaultAttributeValues()}, passMessageToParent => 0, parentTicks => 1};
  1         8  
175             }
176            
177             sub checkAttributeValues
178             {
179 1     1   2 my $self = shift;
180            
181 1         7 $self->SUPER::checkAttributeValues();
182            
183             # ensure the parent has the right interface
184             #
185 1         2 my $parentPkg = "ProgressMonitor";
186 1         4 my $parent = $self->get_parent;
187 1 50       6 X::Usage->throw("parent must be supplied") unless $parent;
188 1 50 33     23 X::Usage->throw("parent is not derived from $parentPkg") unless (blessed($parent) && $parent->isa($parentPkg));
189 1 50       6 X::Usage->throw("must assign a parent tick value >= 0") if $self->get_parentTicks < 0;
190            
191 1         6 return;
192             }
193            
194             ############################
195            
196             =head1 NAME
197            
198             ProgressMonitor::SubTask - a monitor implementation that wraps another monitor
199             in order to propagate the correct number of ticks to the parent.
200            
201             =head1 SYNOPSIS
202            
203             ...
204             # call someTask and give it a monitor to print on stdout
205             #
206             someTask(ProgressMonitor::Stringify::ToStream->new({fields => [ ... ]}));
207            
208             sub someTask
209             {
210             my $monitor = shift;
211            
212             monitor->prepare;
213             # we gather we have 3215 things to do, but only 215 of them are done by us
214             # the others will be accomplished by anotherTask
215             #
216             monitor->begin(3215);
217             for (1..215)
218             {
219             ...do part of the work...
220             monitor->tick(1);
221             }
222             # farm out 3000 units of work to anotherTask
223             # regardless how many units it will use for begin(), the net result is that our monitor will
224             # work its way to 3000 ticks
225             #
226             anotherTask(ProgressMonitor::SubTask->new({parent => monitor, parentTicks => 3000});
227             monitor->end;
228             }
229            
230             sub anotherTask
231             {
232             my $monitor = shift;
233            
234             monitor->prepare;
235             # we're unaware of what kind of monitor we've gotten, nor do we care.
236             # In this sample it'll be a SubTask, so it will scale our 189 units into the 3000
237             #
238             monitor->begin(189);
239             for (1..189)
240             {
241             ...do part of the work...
242             monitor->tick(1);
243             }
244             monitor->end;
245             }
246            
247             =head1 DESCRIPTION
248            
249             This is a special implementation of the ProgressMonitor interface. It takes another
250             monitor as its parent, and a number of ticks it can use of the number allotted to
251             the parent. It will scale its own ticks to the parent.
252            
253             Inherits from AbstractStatefulMonitor.
254            
255             =head1 METHODS
256            
257             =over 2
258            
259             =item new( $hashRef )
260            
261             Configuration data:
262            
263             =over 2
264            
265             =item parent
266            
267             The parent monitor.
268            
269             =item parentTicks (default => 1)
270            
271             The number of ticks to use from the parent.
272            
273             =item passMessageToParent (default => 0)
274            
275             Describes whether setMessage calls should be forwarded to the parent.
276            
277             =back
278            
279             =back
280            
281             =head1 AUTHOR
282            
283             Kenneth Olwing, C<< >>
284            
285             =head1 BUGS
286            
287             I wouldn't be surprised! If you can come up with a minimal test that shows the
288             problem I might be able to take a look. Even better, send me a patch.
289            
290             Please report any bugs or feature requests to
291             C, or through the web interface at
292             L.
293             I will be notified, and then you'll automatically be notified of progress on
294             your bug as I make changes.
295            
296             =head1 SUPPORT
297            
298             You can find general documentation for this module with the perldoc command:
299            
300             perldoc ProgressMonitor
301            
302             =head1 ACKNOWLEDGEMENTS
303            
304             Thanks to my family. I'm deeply grateful for you!
305            
306             =head1 COPYRIGHT & LICENSE
307            
308             Copyright 2006,2007 Kenneth Olwing, all rights reserved.
309            
310             This program is free software; you can redistribute it and/or modify it
311             under the same terms as Perl itself.
312            
313             =cut
314            
315             1; # End of ProgressMonitor::SubTask