2009-06-18 58 views
2

比方說,我有一個線程:IO :: Select線程安全的select()包裝器?如何解決?

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 
        ); 
     } 

}  

由於直到上描述的一個(當然,「把手」)組檢測到活動我都沒有提供超時select()並無限期阻塞,如果另一個會發生什麼線程修改集合的內容(例如爲輪詢添加一個新的套接字)?

它是否相對於Perl POSIX線程實現以線程安全的方式實現?

如果沒有,我想我可以將阻塞的select()調用放在一個有自己的作用域的塊中,並鎖定這些集合,或者更乾淨地鎖定整個包數據。從另一個線程喚醒select()到最後返回的最佳方式是什麼,以便可以操縱這些集合的內容?線程特定的信號?信號?建議歡迎。

非常感謝!

編輯:那麼,線程特定的「信號」就出來了。如此處所述(http://perldoc.perl.org/threads.html):「相應地,向線程發送信號不會中斷該線程當前正在進行的操作:信號將在當前操作完成後纔會執行,例如,如果線程卡住一個I/O呼叫,發送一個信號不會導致I/O呼叫被中斷,從而使信號立即起作用。「

這仍然讓我想知道如何處理在線程中喚醒select()的問題,如果我想讓它無限期地阻塞而不是在固定超時後返回。

回答

2

默認情況下,perl線程不共享任何數據,所以如果一個線程改變它的設置,它不會影響另一個線程。所以是的,它是線程安全的,但它可能不會做你想做的事情。

如果你真的想喚醒另一個阻塞select的線程或進程,一個簡單的解決方案就是向它的讀隊列添加一個管道。然後可以通過向該管道寫入一個字節來喚醒它。

+0

嘿,這不是一個壞主意! – 2009-06-18 11:22:50