NAME
Padre::Task - Padre Background Task API
SYNOPSIS
Create a subclass of Padre::Task which implements your background task:
package Padre::Task::Foo;
use base 'Padre::Task';
# This is run in the main thread before being handed
# off to a worker (background) thread. The Wx GUI can be
# polled for information here.
# If you don't need it, just inherit the default no-op.
sub prepare {
my $self = shift;
if ( condition_for_not_running_the_task ) {
return "BREAK";
}
return 1;
}
# This is run in a worker thread and make take a long-ish
# time to finish. It must not touch the GUI, except through
# Wx events. TODO: explain how this works
sub run {
my $self = shift;
# Do something that takes a long time!
return 1;
}
# This is run in the main thread after the task is done.
# It can update the GUI and do cleanup.
# You don't have to implement this if you don't need it.
sub finish {
my $self = shift;
my $mainwindow = shift;
# cleanup!
return 1;
}
1;
From your code, you can then use this new background task class as follows. (new
and schedule
are inherited.)
require Padre::Task::Foo;
my $task = Padre::Task::Foo->new(some => 'data');
$task->schedule(); # hand off to the task manager
As a special case, any (arbitrarily nested and complex) data structure you put into your object under the magic main_thread_only
hash slot will not be passed to the worker thread but become available again when finish
is called in the main thread. You can use this to pass references to GUI objects and similar things to the finish event handler since these must not be accessed from worker threads.
DESCRIPTION
This is the base class of all background operations in Padre. The SYNOPSIS explains the basic usage, but in a nutshell, you create a subclass, implement your own custom run
method, create a new instance, and call schedule
on it to run it in a worker thread. When the scheduler has a free worker thread for your task, the following steps happen:
- The scheduler calls
prepare
on your object. - If your prepare method returns the string 'break', all further processing is stopped immediately.
- The scheduler serializes your object with
Storable
. - Your object is handed to the worker thread.
- The thread deserializes the task object and calls
run()
on it. - After
run()
is done, the thread serializes the object again and hands it back to the main thread. - In the main thread, the scheduler calls
finish
on your object with the Padre main window object as argument for cleanup.
During all this time, the state of your task object is retained! So anything you store in the task object while in the worker thread is still there when finish
runs in the main thread. (Confer the CAVEATS section below!)
INSTANCE METHODS
schedule
Padre::Task
implements the scheduling logic for your subclass. Simply call the schedule
method to have your task processed by the task manager.
Calling this multiple times will submit multiple jobs.
new
Padre::Task
provides a basic constructor for you to inherit. It simply stores all provided data in the internal hash reference.
run
This is the method that'll be called in the worker thread. You must implement this in your subclass.
You must not interact with the Wx GUI directly from the worker thread. You may use Wx thread events only. TODO: Experiment with this and document it.
prepare
In case you need to set up things in the main thread, you can implement a prepare
method which will be called right before serialization for transfer to the assigned worker thread.
If prepare
returns the string break
(case insensitive), all further processing of the task will be stopped and neither run
nor finish
will be called. Any other return values are generally ignored.
You do not have to implement this method in the subclass.
finish
Quite likely, you need to actually use the results of your background task somehow. Since you cannot directly communicate with the Wx GUI from the worker thread, this method is called from the main thread after the task object has been transferred back to the main thread.
The first and only argument to finish
is the Padre main window object.
You do not have to implement this method in the subclass.
post_event
This method allows you to easily post a Wx event to the main thread. First argument must be the event ID, second argument the data you want to pass to the event handler.
For a complete example, please check the code of Padre::Task::Example::WxEvent
.
You can set up a new event ID in your Padre::Task subclass like this:
our $FUN_EVENT_TYPE = : shared = Wx::NewEventType();
Then you have to setup the event handler (for example in the prepare()
method. This should happen in the main thread!
(TODO: Check the effect of declaring the same handler multiple times)
Wx::Event::EVT_COMMAND(
Padre->ide->wx->main_window,
-1,
$FUN_EVENT,
\&update_gui_with_fun
);
sub update_gui_with_fun {
my ($main, $event) = @_; @_=(); # hack to avoid "Scalars leaked"
my $data = $event->GetData();
}
After that, you can dispatch events of type $FUN_EVENT_TYPE
by simply running:
$self->post_event($FUN_EVENT_TYPE, $data);
NOTES AND CAVEATS
Since the task objects are transferred to the worker threads via Storable::freeze()
/ Storable::thaw()
, you cannot put any data into the objects that cannot be serialized by Storable
. To the best of my knowledge, that includes filehandles and code references.
SEE ALSO
The management of worker threads is implemented in the Padre::TaskManager class.
The transfer of the objects to and from the worker threads is implemented with Storable.
AUTHOR
Steffen Mueller smueller@cpan.org
COPYRIGHT AND LICENSE
Copyright 2008 Gabor Szabo.
This program is free software; you can redistribute it and/or modify it under the same terms as Perl 5 itself.