1Padre::Task(3) User Contributed Perl Documentation Padre::Task(3)
2
3
4
6 Padre::Task - Padre Task API 2.0
7
9 # Fire a task that will communicate back to an owner object
10 My::Task->new(
11 owner => $padre_role_task_object,
12 on_message => 'owner_message_method',
13 on_finish => 'owner_finish_method',
14 my_param1 => 123,
15 my_param2 => 'abc',
16 )->schedule;
17
18
19
20 package My::Task;
21
22 sub new {
23 my $class = shift;
24 my $self = $class->SUPER::new(@_);
25
26 # Check params and validate the task
27
28 return $self;
29 }
30
31 sub prepare {
32 my $self = shift;
33
34 # Run after scheduling immediately before serialised to a worker
35
36 return 0 if $self->my_last_second_abort_check;
37 return 1; # Continue and run
38 }
39
40 sub run {
41 my $self = shift;
42
43 # Called in child, do the work here
44
45 return 1;
46 }
47
48 sub finish {
49 my $self = shift;
50
51 # Called in parent after successful completion
52
53 return 1;
54 }
55
56 1;
57
59 The Padre Task API implements support for background and parallel
60 execution of code in the Padre IDE, and is based on the CPAN Process
61 API.
62
63 A Task Class is a class that completely encapsulates a single unit of
64 work, describing not only the work to be done, but also how the unit of
65 work is created, how is serialised for transport, and any
66 initialisation or cleanup work needs to be done.
67
68 A Task is a single self-contained unit of work, and is implemented as a
69 single instance of a particular Task Class.
70
71 The lifecycle of a Task object
72 From the perspective of a task author, the execution of a task will
73 occur in four distinct phases.
74
75 1. Construction
76
77 The creation of a task is always done completely independantly of its
78 execution. Typically this is done via the "new" method, or something
79 that calls it.
80
81 This separate construction step allows validation of parameters in
82 advance, as well as allowing bulk task pre-generation and advanced task
83 management functionality such as prioritisation, queueing, throttling
84 and load-balancing of tasks.
85
86 2. Preparation
87
88 Once a task has been constructed, an arbitrarily long time may pass
89 before the code is actually run (if it is ever run at all).
90
91 If the actual execution of the task will result in certain work being
92 done in the parent thread, this work cannot be done in the constructor.
93 And once created as an object, no futher task code will be called until
94 the task is ready for execution.
95
96 To give the author a chance to allow for any problems that may occur as
97 a result of this delay, the Task API provides a preparation phase for
98 the task via the "prepare" method.
99
100 This preparation code is run in the parent thread once the task has
101 been prioritised, has a worker allocated to it, and has been
102 encapsulated in its Padre::TaskHandle, but before the object is
103 serialised for transport into the thread.
104
105 A task can use this preparation phase to detach from non-serialisable
106 resources in the object such as database handles, to copy any
107 interesting parent state late rather than early, or decide on a last-
108 second self-abort.
109
110 Once the preparation phase is completed the task will be serialised,
111 transported into assigned worker thread and then executed immediately.
112
113 Because it will execute in the parent thead, the rest of the Padre
114 instance is available for use if needed, but the preparation code
115 should run quickly and must not block.
116
117 3. Execution
118
119 The main phase of the task is where the CPU-intensive or blocking code
120 can be safely run. It is run inside a worker thread in the background,
121 without impacting on the performance of the parent thread.
122
123 However, the task execution phase must be entirely self-contained.
124
125 The worker threads not only do not have access to the Padre IDE
126 variable structure, but most Padre classes (including heavily used
127 modules such as Padre::Current) will not be loaded at all in the worker
128 thread.
129
130 Any output that needs to be transported back to the parent should be
131 stored in the object somewhere. When the cleanup phase is run, these
132 values will be available automatically in the parent.
133
134 4. Cleanup
135
136 When the execution phase of the task is completed, the task object will
137 be serialised for transport back up to the parent thread.
138
139 On arrival, the instance of the task in the parent will be gutted and
140 its contents replaced with the contents of the version arriving from
141 the child thread.
142
143 Once this is complete, the task object will fire a "finish" handler
144 allowing it to take action in the parent thread based on the work done
145 in the child.
146
147 This can include having the task contact any "owner" object that had
148 commissioned the task in the first place.
149
151 new
152 My::Task->new(
153 owner => $padre_role_task_object,
154 on_message => 'owner_message_method',
155 on_finish => 'owner_finish_method',
156 my_param1 => 123,
157 my_param2 => 'abc',
158 );
159
160 The "new" method creates a new "task", a self-contained object that
161 represents a unit of work to be done in the background (although not
162 required to be done in the background).
163
164 In addition to defining a set of method for you to provide as the task
165 implementer, the base class also provides implements a "task ownership"
166 system in the base class that you may use for nearly no cost in terms
167 of code.
168
169 This task owner system will consume three paramters.
170
171 The optional "owner" parameter should be an object that inherits from
172 the role Padre::Role::Task. Message and finish events for this task
173 will be forwarded on to handlers on the owner, if they are defined.
174
175 The optional "on_message" parameter should be the name of a method that
176 can be called on the owner object, to be called when a message arrives
177 from the child object during its execution.
178
179 The required (if "owner" was provided) "on_finish" parameter should be
180 the name of a method that can be called on the owner object, to be
181 called when the task has completed and returns to the parent from the
182 child object.
183
184 When implementing your own task, you should always call the
185 "SUPER::new" method first, to ensure that integration with the task
186 owner system is done.
187
188 You can then check any other parameters, capture additional information
189 from the IDE, and validate that the task is correctly requested and
190 should go ahead.
191
192 The creation of a task object does NOT imply that it will be executed,
193 merely that the require for work to be done is validly formed. A task
194 object may never execute, or may only execute significantly later than
195 it was created.
196
197 Anything that the task needs to do once it is certain that the task
198 will be run should be done in the "prepare" method (see below).
199
200 Returns a new task object if the request is valid, or throws an
201 exception if the request is invalid.
202
203 owner
204 The "owner" method returns the owner object for the task, if one was
205 defined and the owner still exists and considers the answer for the
206 task to be relevant.
207
208 Returns "undef" if the task was not created with an owner.
209
210 Returns "undef" if the owner object has been destroyed since a task was
211 made.
212
213 Returns "undef" if the owner has abandoned this task since it was made.
214
215 on_message
216 The "on_message" accessor returns the name of the owner's message
217 handler method, if one was defined.
218
219 on_finish
220 The "on_finish" accessor returns the name of the owner's finish handler
221 method, if one was defined.
222
223 as_string
224 The "as_string" method is used to serialise the task into a string for
225 transmission between the parent and the child (in both directions).
226
227 By default your task will be serialised using Storable's "nfreeze"
228 method, which is suitable for transmission between threads or processes
229 running the same instance of Perl with the same module search path.
230
231 This should be sufficient in most situations.
232
233 from_string
234 The "from_string" method is used to deserialise the task from a string
235 after transmission between the parent and the child (in both
236 directions).
237
238 By default your task will be deserialised using Storable's "thaw"
239 method, which is suitable for transmission between threads or processes
240 running the same instance of Perl with the same module search path.
241
242 This should be sufficient in most situations.
243
244 schedule
245 $task->schedule;
246
247 The "schedule" method is used to trigger the sending of the task to a
248 worker for processing at whatever time the Task Manager deems it
249 appropriate.
250
251 This could be immediately, with the task sent before the call returns,
252 or it may be delayed indefinately or never run at all.
253
254 Returns true if the task was dispatched immediately.
255
256 Returns false if the task was queued for later dispatch.
257
258 prepare
259 The optional "prepare" method will be called by the task manager on
260 your task object while still in the parent thread, immediately before
261 being serialised to pass to the worker thread.
262
263 This method should be used to compensate for the potential time
264 difference between when "new" is oridinally called and when the task
265 will actually be run.
266
267 For example, a GUI element may indicate the need to run a background
268 task on the visible document but does not care that it is the literally
269 "current" document at the time the task was spawned.
270
271 By capturing the contents of the current document during "prepare"
272 rather than "new" the task object is able to apply the task to the most
273 up to date information at the time we are able to do the work, rather
274 than at the time we know we need to do the work.
275
276 The "prepare" method can take a relatively heavy parameter such as a
277 reference to a Wx element, and flatten it to the widget ID or contents
278 of the widget instead.
279
280 The "prepare" method also gives your task object a chance to determine
281 whether or not it is still necesary. In some situations the delay
282 between "new" and "prepare" may be long enough that the task is no
283 longer relevant, and so by the use of "prepare" you can indicate
284 execution should be aborted.
285
286 Returns true if the task is stil valid, and so the task should be
287 executed.
288
289 Returns false if the task is no longer valid, and the task should be
290 aborted.
291
292 run
293 The "run" method is called on the object in the worker thread
294 immediately after deserialisation. It is where the actual computations
295 and work for the task occurs.
296
297 In many situations the implementation of run is simple and procedural,
298 doing work based on input parameters stored on the object, blocking if
299 necesary, and storing the results of the computation on the object for
300 transmission back to the parent thread.
301
302 In more complex scenarios, you may wish to do a series of tasks or a
303 recursive set of tasks in a loop with a check on the "cancel" method
304 periodically to allow the aborting of the task if requested by the
305 parent.
306
307 In even more advanced situations, you may embed and launch an entire
308 event loop such as POE or AnyEvent inside the "run" method so that long
309 running or complex functionality can be run in the background.
310
311 Once inside of "run" your task is in complete control and the task
312 manager cannot interupt the execution of your code short of killing the
313 thread entirely. The standard "cancel" method to check for a request
314 from the parent to abort your task is cooperative and entirely
315 voluntary.
316
317 Returns true if the computation was completed successfully.
318
319 Returns false if the computation was not completed successfully, and so
320 the parent should not run any post-task logic.
321
322 finish
323 The "finish" method is called on the object in the parent thread once
324 it has been passed back up to the parent, if "run" completed
325 successfully.
326
327 It is responsible for cleaning up the task and taking any actions based
328 on the result of the computation.
329
330 If your task is fire-and-forget or void and you don't care about when
331 the task completes, you do not need to implement this method.
332
333 The default implementation of "finish" implements redirection to the
334 "on_finish" handler of the task owner object, if one has been defined.
335
336 cancel
337 sub run {
338 my $self = shift;
339
340 # Abort a long task if we are no longer wanted
341 foreach my $thing ( @{$self->{lots_of_stuff}} ) {
342 return if $self->cancel;
343
344 # Do something expensive
345 }
346
347 return 1;
348 }
349
350 The "cancel" method can be used in the worker thread by your task
351 during the execution of "run".
352
354 Padre, Process
355
357 Copyright 2008-2011 The Padre development team as listed in Padre.pm.
358
359 This program is free software; you can redistribute it and/or modify it
360 under the same terms as Perl 5 itself.
361
362 The full text of the license can be found in the LICENSE file included
363 with this module.
364
365
366
367perl v5.32.0 2020-07-28 Padre::Task(3)