~ubuntu-branches/ubuntu/saucy/padre/saucy-proposed

« back to all changes in this revision

Viewing changes to .pc/pod-spelling.patch/lib/Padre/Role/Task.pm

  • Committer: Package Import Robot
  • Author(s): Dominique Dumont, gregor herrmann, Dominique Dumont
  • Date: 2012-01-04 12:04:20 UTC
  • mfrom: (1.3.3)
  • Revision ID: package-import@ubuntu.com-20120104120420-i5oybqwf91m1d3il
Tags: 0.92.ds1-1
[ gregor herrmann ]
* Remove debian/source/local-options; abort-on-upstream-changes
  and unapply-patches are default in dpkg-source since 1.16.1.
* Swap order of alternative (build) dependencies after the perl
  5.14 transition.

[ Dominique Dumont ]
* Imported Upstream version 0.92.ds1
* removed fix-spelling patch (applied upstream)
* lintian-override: use wildcard to avoid listing a gazillion files
* updated size of some 'not-real-man-page' entries
* rules: remove dekstop cruft (replaced by a file provided in debian
  directory)
* control: removed Breaks statement. Add /me to uploaders. Updated
  dependencies
* rules: make sure that non-DFSG file (i.e. the cute butterfly, sigh)
  is not distributed

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
package Padre::Role::Task;
2
 
 
3
 
=pod
4
 
 
5
 
=head1 NAME
6
 
 
7
 
Padre::Role::Task - A role for objects that commission tasks
8
 
 
9
 
=head1 DESCRIPTION
10
 
 
11
 
This is a role that should be inherited from by objects in Padre's
12
 
permanent model that want to commision tasks to be run and have the
13
 
results fed back to them, if the answer is still relevant.
14
 
 
15
 
=head2 Task Revisions
16
 
 
17
 
Objects in Padre that commission tasks to run in the background can continue
18
 
processing and changing state during the queue'ing and/or execution of their
19
 
background tasks.
20
 
 
21
 
If the object state changes in such a way as to make the results of a background
22
 
task irrelevant, a mechanism is needed to ensure these background tasks are
23
 
aborted where possible, or their results thrown away when not.
24
 
 
25
 
B<Padre::Role::Task> provides the concept of "task revisions" to support this
26
 
functionality.
27
 
 
28
 
A task revision is an incrementing number for each owner that remains the same
29
 
as long as the results from any arbitrary launched task remains relevant for
30
 
the current state of the object.
31
 
 
32
 
When an object transitions a state boundary it will increment it's revision,
33
 
whether there are any running tasks or not.
34
 
 
35
 
When a task has completed the task manager will look up the owner (if it has
36
 
one) and check to see if the current revision of the owner object is the same
37
 
as when the task was scheduled. If so the Task Manager will call the
38
 
C<on_finish> handler passing it the task. If not, the completed task will be
39
 
silently discarded.
40
 
 
41
 
=head2 Sending messages to your tasks
42
 
 
43
 
The L<Padre::Task> API supports bidirection communication between tasks and
44
 
their owners.
45
 
 
46
 
However, when you commission a task via C<task_request> the task object is not
47
 
returned, leaving you without access to the task and thus without a method by
48
 
which to send messages to the child.
49
 
 
50
 
This is intentional, as there is no guarentee that your task will be launched
51
 
immediately and so sending messages immediately may be unsafe. The task may
52
 
need to be delayed until a new background worker can be spawned, or for longer
53
 
if the maximum background worker limit has been reached.
54
 
 
55
 
The solution is provided by the C<on_message> handler, which is passed the
56
 
parent task object as its first paramater.
57
 
 
58
 
Tasks which expect to be sent messages from their owner should send the owner
59
 
a greeting message as soon as they have started. Not only does this let the
60
 
parent know that work has commenced on their task, but it provides the task
61
 
object to the owner once there is certainty that any parent messages can be
62
 
dispatched to the child successfully.
63
 
 
64
 
In the following example, we assume a long running "service" style task that
65
 
will need to be interacted with over time.
66
 
 
67
 
  sub service_start {
68
 
      my $self = shift;
69
 
  
70
 
      $self->task_reset;
71
 
      $self->task_request(
72
 
          task       => 'My::Service',
73
 
          on_message => 'my_message',
74
 
          on_finish  => 'my_finish',
75
 
      );
76
 
  }
77
 
  
78
 
  sub my_message {
79
 
      my $self = shift;
80
 
      my $task = shift;
81
 
  
82
 
      # In this example our task sends an empty message to indicate "started"
83
 
      unless ( @_ ) {
84
 
          $self->{my_service} = $task;
85
 
          return;
86
 
      }
87
 
  
88
 
      # Handle other messages...
89
 
  }
90
 
 
91
 
=head1 METHODS
92
 
 
93
 
=cut
94
 
 
95
 
use 5.008005;
96
 
use strict;
97
 
use warnings;
98
 
use Scalar::Util   ();
99
 
use Padre::Current ();
100
 
use Padre::Logger;
101
 
 
102
 
our $VERSION    = '0.90';
103
 
our $COMPATIBLE = '0.69';
104
 
 
105
 
# Use a shared sequence for object revisioning greatly
106
 
# simplifies the indexing process.
107
 
my $SEQUENCE = 0;
108
 
my %INDEX    = ();
109
 
 
110
 
 
111
 
 
112
 
 
113
 
 
114
 
######################################################################
115
 
# Main Methods
116
 
 
117
 
=pod
118
 
 
119
 
=head2 task_owner
120
 
 
121
 
  Padre::Role::Task->task_owner( 1234 );
122
 
 
123
 
The C<task_owner> static method is a convenience method which takes an owner
124
 
id and will look up the owner object.
125
 
 
126
 
Returns the object if it still exists and has not changed it's task revision.
127
 
 
128
 
Returns C<undef> of the owner object no longer exists, or has changed its task
129
 
revision since the original owner id was issued.
130
 
 
131
 
=cut
132
 
 
133
 
sub task_owner {
134
 
        TRACE( $_[0] ) if DEBUG;
135
 
        $INDEX{ $_[1] };
136
 
}
137
 
 
138
 
=pod
139
 
 
140
 
=head2 task_manager
141
 
 
142
 
The C<task_manager> method is a convenience for quick access to the Padre's
143
 
L<Padre::TaskManager> instance.
144
 
 
145
 
=cut
146
 
 
147
 
sub task_manager {
148
 
        TRACE( $_[0] ) if DEBUG;
149
 
        return $_[0]->can('current')
150
 
                ? $_[0]->current->ide->task_manager
151
 
                : Padre::Current->ide->task_manager;
152
 
}
153
 
 
154
 
=pod
155
 
 
156
 
=head2 task_revision
157
 
 
158
 
The C<task_revision> accessor returns the current task revision for an object.
159
 
 
160
 
=cut
161
 
 
162
 
sub task_revision {
163
 
        TRACE( $_[0] ) if DEBUG;
164
 
        my $self = shift;
165
 
 
166
 
        # Set a revision if this is the first time
167
 
        unless ( defined $self->{task_revision} ) {
168
 
                $self->{task_revision} = ++$SEQUENCE;
169
 
        }
170
 
 
171
 
        # Optimisation hack: Only populate the index when
172
 
        # the revision is queried from the view.
173
 
        unless ( exists $INDEX{ $self->{task_revision} } ) {
174
 
                $INDEX{ $self->{task_revision} } = $self;
175
 
                Scalar::Util::weaken( $INDEX{ $self->{task_revision} } );
176
 
        }
177
 
 
178
 
        TRACE("Owner revision is $self->{task_revision}") if DEBUG;
179
 
        return $self->{task_revision};
180
 
}
181
 
 
182
 
=pod
183
 
 
184
 
=head2 task_reset
185
 
 
186
 
The C<task_reset> method is called when the state of an owner object
187
 
significantly changes, and outstanding tasks should be deleted or ignored.
188
 
 
189
 
It will change the task revision of the owner and request the task manager to
190
 
send a standard C<cancel> message to any currently executing background tasks,
191
 
allowing them to terminate elegantly (if they handle 
192
 
 
193
 
=cut
194
 
 
195
 
sub task_reset {
196
 
        TRACE( $_[0] ) if DEBUG;
197
 
        my $self = shift;
198
 
        if ( $self->{task_revision} ) {
199
 
                delete $INDEX{ $self->{task_revision} };
200
 
                $self->task_manager->cancel( $self->{task_revision} );
201
 
        }
202
 
        $self->{task_revision} = ++$SEQUENCE;
203
 
}
204
 
 
205
 
=pod
206
 
 
207
 
=head2 task_request
208
 
 
209
 
  $self->task_request(
210
 
      task       => 'Padre::Task::SomeTask',
211
 
      on_message => 'message_handler_method',
212
 
      on_finish  => 'finish_handler_method',
213
 
      my_param1  => 123,
214
 
      my_param2  => 'abc',
215
 
  );
216
 
 
217
 
The C<task_request> method is used to spawn a new background task for the
218
 
owner, loading the class and registering for callback messages in the process.
219
 
 
220
 
The C<task> parameter indicates the class of the task to be executed, which
221
 
must inherit from L<Padre::Task>. The class itself will be automatically loaded
222
 
if required.
223
 
 
224
 
The optional C<on_message> parameter should be the name of a method
225
 
(which must exist if provided) that will receive owner-targetted messages from
226
 
the background process.
227
 
 
228
 
The method will be passed the task object (as it exists after the C<prepare>
229
 
phase in the parent thread) as its first parameter, followed by any values
230
 
passed by the background task.
231
 
 
232
 
If no C<on_message> parameter is provided the default method null
233
 
C<task_message> will be called.
234
 
 
235
 
The optional C<on_finish> parameter should be the name of a method
236
 
(which must exist if provided) that will receive the task object back from
237
 
the background worker once the task has completed, complete with any state
238
 
saved in the task during its background execution.
239
 
 
240
 
It is passed a single parameter, which is the L<Padre::Task> object.
241
 
 
242
 
If no C<on_finish> parameter is provided the default method null
243
 
C<task_finish> will be called.
244
 
 
245
 
Any other parameters are passed through the constructor method of the task.
246
 
 
247
 
=cut
248
 
 
249
 
sub task_request {
250
 
        TRACE( $_[0] ) if DEBUG;
251
 
        my $self  = shift;
252
 
        my %param = @_;
253
 
 
254
 
        # Check and load the task
255
 
        # Support a convenience shortcut where a false value
256
 
        # for task means don't run a task at all.
257
 
        my $name = delete $param{task} or return;
258
 
        my $driver = Params::Util::_DRIVER( $name, 'Padre::Task' );
259
 
        die "Invalid task class '$name'" unless $driver;
260
 
 
261
 
        # Create and start the task with ourself as the owner
262
 
        TRACE("Creating and scheduling task $driver") if DEBUG;
263
 
        $driver->new( owner => $self, %param )->schedule;
264
 
}
265
 
 
266
 
=pod
267
 
 
268
 
=head2 task_finish
269
 
 
270
 
The C<task_finish> method is the default handler method for completed tasks,
271
 
and will be called for any C<task_request> where no specific C<on_finish>
272
 
handler was provided.
273
 
 
274
 
If your object issues only one task, or if you would prefer a single common
275
 
finish handler for all your different tasks, you should override this method
276
 
instead of explicitly defining an C<on_finish> handler for every task.
277
 
 
278
 
The default implementation ensures that every task has an appropriate finish
279
 
handler by throwing an exception with a message indicating the owner and task
280
 
class for which no finish handler could be found.
281
 
 
282
 
=cut
283
 
 
284
 
sub task_finish {
285
 
        my $class = ref( $_[0] ) || $_[0];
286
 
        my $task  = ref( $_[1] ) || $_[1];
287
 
        die "Unhandled task_finish for $class (recieved $task)";
288
 
}
289
 
 
290
 
=pod
291
 
 
292
 
=head2 task_message
293
 
 
294
 
The C<task_message> method is the default handler method for completed tasks,
295
 
and will be called for any C<task_request> where no specific C<on_message>
296
 
handler was provided.
297
 
 
298
 
If your object issues only one task, or if you would prefer a single common
299
 
message handler for all your different tasks, you should override this method
300
 
instead of explicitly defining an C<on_finish> handler for every task.
301
 
 
302
 
If none of your tasks will send messages back to their owner, you do not need
303
 
to define this method.
304
 
 
305
 
The default implementation ensures that every task has an appropriate finish
306
 
handler by throwing an exception with a message indicating the owner and task
307
 
class for which no finish handler could be found.
308
 
 
309
 
=cut
310
 
 
311
 
sub task_message {
312
 
        my $class = ref( $_[0] ) || $_[0];
313
 
        my $task  = ref( $_[1] ) || $_[1];
314
 
        die "Unhandled task_message for $class (recieved $task message $_[2]->[0])";
315
 
}
316
 
 
317
 
1;
318
 
 
319
 
=pod
320
 
 
321
 
=head1 COPYRIGHT & LICENSE
322
 
 
323
 
Copyright 2008-2011 The Padre development team as listed in Padre.pm.
324
 
 
325
 
This program is free software; you can redistribute
326
 
it and/or modify it under the same terms as Perl itself.
327
 
 
328
 
The full text of the license can be found in the
329
 
LICENSE file included with this module.
330
 
 
331
 
=cut
332
 
 
333
 
# Copyright 2008-2011 The Padre development team as listed in Padre.pm.
334
 
# LICENSE
335
 
# This program is free software; you can redistribute it and/or
336
 
# modify it under the same terms as Perl 5 itself.