~ubuntu-branches/ubuntu/precise/padre/precise

« back to all changes in this revision

Viewing changes to lib/Padre/Task.pm

  • Committer: Bazaar Package Importer
  • Author(s): Damyan Ivanov
  • Date: 2010-05-08 09:17:22 UTC
  • mfrom: (1.2.1 upstream) (10.1.1 sid)
  • Revision ID: james.westby@ubuntu.com-20100508091722-y6008jtk0ap6znyn
Tags: 0.60.ds1-3
rules: run tests with HOME=$fake_home to avoud failing when $HOME points
to a non-existent location. Closes: #579289

Show diffs side-by-side

added added

removed removed

Lines of Context:
12
12
task:
13
13
 
14
14
  package Padre::Task::Foo;
15
 
  
 
15
 
16
16
  use base 'Padre::Task';
17
 
  
 
17
 
18
18
  # This is run in the main thread before being handed
19
19
  # off to a worker (background) thread. The Wx GUI can be
20
20
  # polled for information here.
24
24
          if ( condition_for_not_running_the_task ) {
25
25
                  return "BREAK";
26
26
          }
27
 
          
 
27
 
28
28
          return 1;
29
29
  }
30
30
 
31
31
  # This is run in a worker thread and may take a long-ish
32
32
  # time to finish. It must not touch the GUI, except through
33
 
  # Wx events. TODO: explain how this works
 
33
  # Wx events. TO DO: explain how this works
34
34
  sub run {
35
35
          my $self = shift;
36
36
          # Do something that takes a long time!
48
48
          # cleanup!
49
49
          return 1;
50
50
  }
51
 
  
 
51
 
52
52
  1;
53
53
 
54
54
From your code, you can then use this new background task class as
66
66
to GUI objects and similar things to the finish event handler
67
67
since these must not be accessed from worker threads.
68
68
 
 
69
However, you should be cautious when keeping references to GUI
 
70
elements in your tasks, in case the GUI wants to destroy them
 
71
before your task returns.
 
72
 
 
73
Instead, it is better if your C<finish> method knows how to
 
74
relocate the GUI element from scratch (and can safely handle
 
75
the situation when the GUI element is gone, or has changed enough
 
76
to make the task response irrelevent).
 
77
 
69
78
=head1 DESCRIPTION
70
79
 
71
 
This is the base class of all background operations in Padre. The SYNOPSIS
72
 
explains the basic usage, but in a nutshell, you create a subclass, implement
73
 
your own custom C<run> method, create a new instance, and call C<schedule>
74
 
on it to run it in a worker thread. When the scheduler has a free worker
75
 
thread for your task, the following steps happen:
 
80
This is the base class of all background operations in Padre.
 
81
The SYNOPSIS explains the basic usage, but in a nutshell, you create a
 
82
subclass, implement your own custom C<run> method, create a new instance,
 
83
and call C<schedule> on it to run it in a worker thread. When the scheduler
 
84
has a free worker thread for your task, the following steps happen:
76
85
 
77
86
=over 2
78
87
 
113
122
use Scalar::Util ();
114
123
use Params::Util '_INSTANCE';
115
124
 
116
 
our $VERSION = '0.50';
117
 
 
118
 
# TODO: Why are there require?
 
125
our $VERSION = '0.60';
 
126
 
 
127
# set up the stdout/stderr printing events => initialized during run time
 
128
our $STDOUT_EVENT : shared;
 
129
our $STDERR_EVENT : shared;
 
130
 
 
131
# TO DO: Why are these require?
119
132
require Padre;
120
133
require Padre::Wx;
 
134
require Wx;
121
135
 
122
136
BEGIN {
123
137
 
127
141
        }
128
142
}
129
143
 
130
 
use Class::XSAccessor constructor => 'new';
131
 
 
132
 
# set up the stdout/stderr printing events
133
 
our $STDOUT_EVENT : shared = Wx::NewEventType();
134
 
our $STDERR_EVENT : shared = Wx::NewEventType();
135
 
 
136
144
=pod
137
145
 
138
146
=head2 new
141
149
inherit. It simply stores all provided data in the internal
142
150
hash reference.
143
151
 
 
152
=cut
 
153
 
 
154
sub new {
 
155
        my $class = shift;
 
156
        my $self = bless {@_} => $class;
 
157
        if ( not defined $STDOUT_EVENT ) {
 
158
                $STDOUT_EVENT = Wx::NewEventType();
 
159
                $STDERR_EVENT = Wx::NewEventType();
 
160
        }
 
161
        return $self;
 
162
}
 
163
 
144
164
=head2 schedule
145
165
 
146
166
C<Padre::Task> implements the scheduling logic for your
152
172
=cut
153
173
 
154
174
SCOPE: {
155
 
        my $events_initialized = 0;
 
175
        my $event_hooks_initialized = 0;
156
176
 
157
177
        sub schedule {
158
178
                my $self = shift;
159
 
                if ( !$events_initialized ) {
160
 
                        my $main = Padre->ide->wx->main;
 
179
                if ( not $event_hooks_initialized ) {
 
180
                        $event_hooks_initialized = 1;
 
181
                        my $main = Padre->ide->wx;
161
182
                        Wx::Event::EVT_COMMAND(
162
183
                                $main,
163
184
                                -1,
170
191
                                $STDERR_EVENT,
171
192
                                \&_on_stderr,
172
193
                        );
173
 
                        $events_initialized = 1;
174
194
                }
175
195
                Padre->ide->task_manager->schedule($self);
176
196
        }
180
200
 
181
201
=head2 run
182
202
 
183
 
This is the method that'll be called in the worker thread.
 
203
This is the method that will be called in the worker thread.
184
204
You must implement this in your subclass.
185
205
 
186
206
You must not interact with the Wx GUI directly from the
187
207
worker thread. You may use Wx thread events only.
188
 
TODO: Experiment with this and document it.
 
208
TO DO: Experiment with this and document it.
189
209
 
190
210
=cut
191
211
 
214
234
=cut
215
235
 
216
236
sub prepare {
217
 
        my $self = shift;
218
237
        return 1;
219
238
}
220
239
 
236
255
=cut
237
256
 
238
257
sub finish {
239
 
        my $self = shift;
240
258
        return 1;
241
259
}
242
260
 
304
322
                my $userclass = $padretask->{_process_class};
305
323
                delete $padretask->{_process_class};
306
324
 
307
 
                no strict 'refs'; ## no critic
 
325
                no strict 'refs';
308
326
                my $ref = \%{"${userclass}::"};
309
327
                use strict 'refs';
310
328
                my $loaded = exists $ref->{"ISA"};
311
 
                unless ( $loaded or eval("require $userclass;") ) { ## no critic
 
329
                unless ( $loaded or eval("require $userclass;") ) {
312
330
                        require Carp;
313
331
                        if ($@) {
314
332
                                Carp::croak("Failed to load Padre::Task subclass '$userclass': $@");
414
432
 
415
433
# The main-thread stdout hook
416
434
sub _on_stdout {
417
 
        my ( $main, $event ) = @_;
 
435
        my ( $wx, $event ) = @_;
418
436
        @_ = (); # hack to avoid "Scalars leaked"
419
 
        my $out = $main->output();
 
437
        my $main = $wx->main;
 
438
        my $out  = $main->output();
420
439
        $main->show_output(1);
421
440
        $out->style_neutral();
422
441
        $out->AppendText( $event->GetData );
425
444
 
426
445
# The main-thread stderr hook
427
446
sub _on_stderr {
428
 
        my ( $main, $event ) = @_;
 
447
        my ( $wx, $event ) = @_;
429
448
        @_ = (); # hack to avoid "Scalars leaked"
430
 
        my $out = $main->output();
 
449
        my $main = $wx->main;
 
450
        my $out  = $main->output();
431
451
        $main->show_output(1);
432
452
        $out->style_bad();
433
453
        $out->AppendText( $event->GetData );
441
461
 
442
462
  $task->task_print("Hi this is immediately sent to the Padre output window\n");
443
463
 
444
 
Sends an event to the main Padre thread and dispays a
 
464
Sends an event to the main Padre thread and displays a
445
465
message in the Padre output window.
446
466
 
447
467
=cut
458
478
 
459
479
  $task->task_warn("Hi this is immediately sent to the Padre output window\n");
460
480
 
461
 
Sends an event to the main Padre thread and dispays a
 
481
Sends an event to the main Padre thread and displays a
462
482
message in the Padre output window with style C<bad>.
463
483
 
464
484
=cut
483
503
You can set up a new event ID in your Padre::Task subclass
484
504
like this:
485
505
 
486
 
  our $FUN_EVENT_TYPE =  : shared = Wx::NewEventType();
 
506
  our $FUN_EVENT_TYPE : shared;
 
507
  BEGIN { $FUN_EVENT_TYPE = Wx::NewEventType(); }
487
508
 
488
509
Then you have to setup the event handler (for example in the
489
510
C<prepare()> method. This should happen in the main thread!
497
518
      $FUN_EVENT,
498
519
      \&update_gui_with_fun
499
520
  );
500
 
  
 
521
 
501
522
  sub update_gui_with_fun {
502
523
      my ($main, $event) = @_; @_=(); # hack to avoid "Scalars leaked"
503
524
      my $data = $event->GetData();
504
525
  }
505
 
  
 
526
 
506
527
After that, you can dispatch events of type C<$FUN_EVENT_TYPE>
507
528
by simply running:
508
529
 
520
541
                unless ( defined $data and length($data) );
521
542
 
522
543
        Wx::PostEvent(
523
 
                $Padre::TaskManager::_main,
 
544
                Padre->ide->wx,
524
545
                Wx::PlThreadEvent->new( -1, $eventid, $data ),
525
546
        );
526
547
        return ();
535
556
Since the task objects are transferred to the worker threads via
536
557
C<Storable::freeze()> / C<Storable::thaw()>, you cannot put any data
537
558
into the objects that cannot be serialized by C<Storable>. I<To the best
538
 
of my knowledge>, that includes filehandles and code references.
 
559
of my knowledge>, that includes file handles and code references.
539
560
 
540
561
=head1 SEE ALSO
541
562
 
551
572
 
552
573
=head1 COPYRIGHT AND LICENSE
553
574
 
554
 
Copyright 2008-2009 The Padre development team as listed in Padre.pm.
 
575
Copyright 2008-2010 The Padre development team as listed in Padre.pm.
555
576
 
556
577
This program is free software; you can redistribute it and/or
557
578
modify it under the same terms as Perl 5 itself.
558
579
 
559
580
=cut
560
581
 
561
 
# Copyright 2008-2009 The Padre development team as listed in Padre.pm.
 
582
# Copyright 2008-2010 The Padre development team as listed in Padre.pm.
562
583
# LICENSE
563
584
# This program is free software; you can redistribute it and/or
564
585
# modify it under the same terms as Perl 5 itself.