views:

445

answers:

1

Let's say I have a thread:

sub     new {
        my      $class = shift;
        my      $self = ref $class || $class;

        bless { 'read_set'  => IO::Select->new,
                'write_set' => IO::Select->new,
                'error_set' => IO::Select->new }, $self;
}


sub     start {
        my      $self = shift;

        $self->{'thread'} = threads->create(\&worker_thr, $self);
        $self->{'thread'}->detach;
}

sub     worker_thr {
         my      $self = shift;

         while(1) {
                 my($read_active, $write_active, $error_active) = 
                    IO::Select->select(
                            $self->{'read_set'},
                            $self->{'write_set'},
                            $self->{'error_set'}, 
                            undef
                    );
         }

}

Since I have provided no timeout to select() and it blocks indefinitely until activity is detected on one of the descriptor (well, "handle") sets, what happens if another thread modifies the contents of the sets (e.g. adds a new socket for polling)?

Is it implemented in a thread-safe manner, relative to the Perl POSIX threads implementation?

If not, I suppose I can stick the blocking select() call in a block with its own scope and lock the sets or, more cleanly, the entire package data. What is the best way to wake select() up to return, from another thread so that the contents of the sets can be manipulated? Thread-specific signal? Semaphore? Suggestions welcome.

Thanks muchly!

Edit: Well, thread-specific "signal" is out. As explained here ( http://perldoc.perl.org/threads.html ): "Correspondingly, sending a signal to a thread does not disrupt the operation the thread is currently working on: The signal will be acted upon after the current operation has completed. For instance, if the thread is stuck on an I/O call, sending it a signal will not cause the I/O call to be interrupted such that the signal is acted up immediately."

That still leaves me wondering how I should handle the issue of waking select() up in a thread if I want it to block indefinitely instead of returning after a fixed timeout.

+2  A: 

By default, perl threads don't share any data, so if one thread changes its sets it will not affect the other. So yes, it is thread-safe, but it probably doesn't do what you want it to do.

If you really want to wake-up another thread or process that's blocking on a select, an easy solution is to add a pipe to it's read queue. You can then wake it up by writing a byte to that pipe.

Leon Timmermans
Hey, that's not a bad idea!
Alex Balashov