2009-06-18 5 views
2

Sagen wir, ich habe einen thread:Ist der select() Wrapper in IO :: Wählen Sie thread-safe? Wie arbeitest du?

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

}  

Da ich keine Zeitüberschreitung zu select() zur Verfügung gestellt haben und blockiert es auf unbestimmte Zeit bis zur Aktivität auf einem der Deskriptor erfaßt wird (gut, „Griff“) setzt, was, wenn eine andere geschieht thread ändert den Inhalt der Sets (fügt zB einen neuen Socket für das Polling hinzu)?

Wird es threadsicher im Verhältnis zur Implementierung von Perl POSIX-Threads implementiert?

Wenn nicht, nehme ich an, ich kann den blockierenden select() Aufruf in einen Block mit seinem eigenen Bereich stecken und die Sätze oder, sauberer, die gesamten Paketdaten sperren. Was ist der beste Weg, select() aufzuwecken, um von einem anderen Thread zurückzukehren, so dass der Inhalt der Sätze manipuliert werden kann? Fadenspezifisches Signal? Semaphor? Vorschläge willkommen.

Vielen Dank!

Edit: Nun, Thread-spezifische "Signal" ist out. Wie hier erklärt (http://perldoc.perl.org/threads.html): "Entsprechend unterbricht das Senden eines Signals an einen Thread die Operation, an der der Thread gerade arbeitet, nicht: Das Signal wird bearbeitet, nachdem die aktuelle Operation abgeschlossen ist. Zum Beispiel, wenn der Thread festsitzt Ein E/A-Anruf, der ein Signal sendet, führt nicht dazu, dass der E/A-Anruf unterbrochen wird, so dass das Signal sofort ausgelöst wird. "

Das lässt mich immer noch fragen, wie ich das Problem von select() in einem Thread aufwachen sollte, wenn ich möchte, dass es auf unbestimmte Zeit blockiert, anstatt nach einer festen Zeitüberschreitung zurückzukehren.

Antwort

2

Standardmäßig teilen Perl-Threads keine Daten. Wenn also ein Thread seine Sets ändert, wirkt sich dies nicht auf das andere aus. Also ja, es ist Thread-sicher, aber es tut wahrscheinlich nicht, was Sie wollen, dass es tut.

Wenn Sie wirklich einen anderen Thread oder Prozess, der bei einer Auswahl blockiert, aufwecken möchten, ist es eine einfache Lösung, eine Pipe zu seiner Lesewarteschlange hinzuzufügen. Sie können es dann aufwecken, indem Sie ein Byte an diese Pipe schreiben.

+0

Hey, das ist keine schlechte Idee! –