Author image Graciliano Monteiro Passos

NAME

Thread::Isolate - Create Threads that can be called externally and use them to isolate modules from the main thread.

DESCRIPTION

This module has the main purpose to isolate loaded modules from the main thread.

The idea is to create the Thread::Isolate object and call methods, evaluate codes and use modules inside it, with synchronized and unsynchronized calls.

Also you can have multiple Thread::Isolate objects, with different states of the Perl interpreter (different loaded modules in each thread).

To save memory Thread::Isolate holds a cleaner version of the Perl interpreter when it's loaded, than it uses this Mother Thread to create all the other Thread::Isolate objects.

USAGE

Synchronized calls:

  ## Load it soon as possible to save memory:
  use Thread::Isolate ;
  
  my $thi = Thread::Isolate->new() ;

  $thi->eval(' 2**10 ') ;
  
  ...
  
  $thi->eval(q`
    sub TEST {
      my ( $var ) = @_ ;
      return $var ** 10 ;
    }
  `) ;
  
  print $thi->call('TEST' , 2) ;

  ...
  
  $thi->use('Data::Dumper') ;
  
  print $thi->call('Data::Dumper::Dumper' , [123 , 456 , 789]) ;
  

Here's an example of an unsynchronized call (detached):

  my $job = $thi->eval_detached(q`
    for(1..5) {
      print "in> $_\n" ;
      sleep(1);
    }
    return 2**3 ;
  `);
  
  $job->wait_to_start ;

  while( $job->is_running ) {
    print "." ;
  }
  
  print $job->returned ;

Creating a copy of an already existent Thread::Isolate:

  my $thi = Thread::Isolate->new() ;
  
  ## Creates a thread inside/from $thi and return it:
  $thi2 = $thi->new_internal ;

The code above can be used to make different copies of different states of the Perl Interpreter.

Thread::Isolate METHODS

new (%OPTIONS)

Create a new Thread::Isolate object.

From version 0.02 each new Thread::Isolate object will be a copy of a Mother Thread that holds a cleaner state of the Perl interpreter.

OPTIONS:

no_mother_thread

Do not use default Mother Thread as generator of the new thread. This will create a thread usign the current Perl thread. (Normal behavior of Perl threads).

mother_thread

A thread to be used as the generator of the new Thread::Isolate object.

new_internal

Create a new Thread::Isolate inside the current Thread::Isolate object.

This can be used to copy/clone threads from external calls.

new_from_id (ID)

Returns an already created Thread::Isolate object using the ID.

self

Returns the current Thread::Isolate object (similar to Perl threads->self call).

id

Return the ID of the thread. Same that is returned by $thread->id.

Thread ID is based in the Thread::Isolate creation of instances.

tid

Return the TID of the thread. Same that is returned by $thread->tid.

TID is based in the OS and Perl thread implementation.

clone

Return a cloned object. (This won't create a new Perl thread, is just a clone of the object reference).

copy

Create a copy of the thread. (Same as new_internal(). Will create a new Perl thread).

use (MODULE , ARGS)

call 'use MODULE qw(ARGS)' inside the thread,

eval (CODE , ARGS)

Evaluate a CODE and paste ARGS inside the thread.

eval_detached (CODE , ARGS)

Evaluate detached (unsynchronous) a CODE and paste ARGS inside the thread.

Returns a Thread::Isolate::Job object.

err

Return the error ($@) value of the last eval.

pack_eval (CODE , ARGS)

Evaluate the CODE in the same package of the caller:

  use Class::HPLOO ;
  
  class Foo::Bar::Baz {
    use Thread::Isolate ;
    
    my $th_isolate = Thread::Isolate->new() ;
    
    $th_isolate->pack_eval(q`
      sub isolated_function {...}
    `);
    
    ## or:
    
    $th_isolate->eval(q`
      package Foo::Bar::Baz ;
      sub isolated_function {...}
    `);
  }

pack_eval_detached (CODE , ARGS)

Same as pack_eval() but detached.

call (FUNCTION , ARGS)

call FUNCTION inside the thread.

call_detached (FUNCTION , ARGS)

call detached (unsynchronous) FUNCTION inside the thread.

Returns a Thread::Isolate::Job object.

pack_call (FUNCTION , ARGS)

Call function in the same package of the caller. So, if you call function X from package Foo, the result will be the same to call call('Foo::X'). The idea is to use that in classes that uses some "shared" code in a Thread::Isolate:

  use Class::HPLOO ;
  
  class Foo::Bar::Baz {
    use Thread::Isolate ;
    
    my $th_isolate = Thread::Isolate->new() ;
    
    $th_isolate->eval(q`
      package Foo::Bar::Baz ;
      
      open (LOG,"foo.log") ;
      
      sub write_lines {
        print LOG @_ ;
      }
    `) ;
    
    sub log {
      my ( $msg ) = @_ ;
      $th_isolate->pack_call('write_lines' , "LOG> $msg\n") ;
      ## or:
      $th_isolate->call('Foo::Bar::Baz::write_lines' , "LOG> $msg\n") ;
    }
  
  }

The code above uses a Thread::Isolate to share a HANDLE (IO) to write lines into a log file.

pack_call_detached (FUNCTION , ARGS)

Same as pack_call() but detached.

shutdown

Shutdown the thread. See also kill().

kill

Kill the thread. The difference of shutdown() and kill is that kill will interrupt the current job executation.

exists

Return TRUE if the thread exists.

is_running_any_job

Return TRUE if the thread is running some job.

get_attr( KEY )

Get the value of an internal attribute of the thread.

set_attr( KEY )

Set the value of an internal attribute of the thread and return it.

get_global( KEY )

Get the value of a global attribute (shared by all the threads).

set_global( KEY )

Set the value of a global attribute (shared by all the threads) and return it.

Thread::Isolate::Job METHODS

When a deteched method is called a job is returned. Here are the methods to use the job object:

id

Return the ID of the job.

tid

Return the TID of the thread. Same that is returned by $thread->tid.

TID is based in the OS and Perl thread implementation.

th_id

Return the ID of the thread. Same that is returned by $thread->id.

Thread ID is based in the Thread::Isolate creation of instances.

dump

Dump the job informations (similar to Data::Dumper).

type

Return the type of the job.

args

Return the arguments of the job.

detach

Detach the job (will not wait to finish the job).

is_detached

Return TRUE if the job is detached.

is_started

Return TRUE if the job was started.

is_running

Return TRUE if the job is running.

is_finished

Return TRUE if the job was finished.

time

Return the start time of the job.

wait_to_start

Wait until the job starts. (Ensure that the job was started).

wait

Wait until the job is finished. (Ensure that the job was fully executed).

Returns the arguments returneds by the job.

wait_to_finish

Same as wait().

Wait until the job is finished. (Ensure that the job was fully executed).

Returns the arguments returneds by the job.

returned

Returns the arguments returneds by the job. It will wait the job to finish too.

Pasting Data Between Threads

When the methods call() and eval() (and derivations) are called all the sent data is freezed (by Storable::freeze()) and in the target thread they are thawed (by Storable::thaw()). But Storable can't freeze GLOB and CODE, so Thread::Isolate make a work around to be possible to send this kind of references.

For GLOB/IO Thread::Isolate paste it as fileno(), and for CODE a dum sub is paste for now.

Mapping a Thread Package to Another Thread

With Thread::Isolate::Map is possible to Map the package symbols of one thread to another, and use this package from many threads without need to load it many times.

See Thread::Isolate::Map POD for more.

SEE ALSO

Thread::Isolate::Map, Thread::Isolate::Pool.

Thread::Tie::Thread, threads::shared.

Safe::World.

AUTHOR

Graciliano M. P. <gmpassos@cpan.org>

I will appreciate any type of feedback (include your opinions and/or suggestions). ;-P

This module was inspirated on Thread::Tie::Thread by Elizabeth Mattijsen, <liz at dijkmat.nl>, the mistress of threads. ;-P

COPYRIGHT

This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.