#!/usr/bin/perl use warnings; use strict; use threads; use threads::shared; # Daten für die Threads my %threads=(); # für jeden thread gibt es drei Werte, # die über den thread hinaus gelesen werden können # end => thread hat sich beenden, oder soll sich beenden # txt_print => Puffer für den anzuzeigenden Text # txt_send => Puffer für den "eingebenden" Text #----------------------------------------------------------------------- # Daten Thread A share($threads{a}{end}); share($threads{a}{txt_print}); share($threads{a}{txt_send}); $threads{a}{end}=0; $threads{a}{txt_print}=''; $threads{a}{txt_send}=''; $threads{a}{name}='Thread_A'; $threads{a}{'shift'}=0; #----------------------------------------------------------------------- # Daten Thread B share($threads{b}{end}); share($threads{b}{txt_print}); share($threads{b}{txt_send}); $threads{b}{end}=0; $threads{b}{txt_print}=''; $threads{b}{txt_send}=''; $threads{b}{name}='Thread_B'; $threads{b}{'shift'}=35; #----------------------------------------------------------------------- # Thread a starten $threads{a}{thread}=threads->new(\&work,$threads{a}); # Thread b starten $threads{b}{thread}=threads->new(\&work,$threads{b}); # haupttread loop # hier werden die Nachrichten verteilt # solange arbeiten wie ein Thread noch läuft. while(1) { my $exit=0; my($n1,$n2)=qw(a b); communicate($threads{a},$threads{b}); communicate($threads{b},$threads{a}); last if($threads{a}{end} || $threads{b}{end}); # ein wenig warten sleep(1); } # Beenden erzwingen # und auf das Ende warten $threads{a}{end}=1; $threads{b}{end}=1; $threads{a}{thread}->join(); $threads{b}{thread}->join(); exit; ######################################################################## ######################################################################## # das ist der einzelne Thread sub work { my $data=shift; # mindestens 10 maxinal 20 Durchläufe my $count=int(rand(10))+10; while(1) { # zufälliger String von 10 Zeichen länge my $str=join('',map{chr(33+int(rand(93)))}(0..10)); # Text an den Puffer anhängen # beim überschreiben könnten Daten verloren gehen, # wenn der Puffer noch nicht geleert wurde $data->{txt_send}.="$str\n"; # es soll Text angezeigt werden if($data->{txt_print}) { # Text lesen und "Puffer" leeren # das sollte möglichst atomar sein, # sonst könnte ein anderer Thread da zwischen funken my $text=$data->{txt_print}; $data->{txt_print}=''; # Ausgabe # Text formatieren my $shift=' 'x$data->{'shift'}; $text=~s/\n$//s; $text=~s/(^|\n)/$1$shift$data->{name}: /gs; print "$text\n"; } # wenn counter abgelaufen # dann Signal zum beenden setzen $data->{end}=1 if($count-- <= 0); # beenden wenn das Signal kommt last if($data->{end}); # zufällig lang warten (0..1 Sekunde) select(undef,undef,undef,rand(1)); } } # Daten wischen den einzelnen Kind-Threads austauschen sub communicate { my ($from,$to)=@_; # wenn Text gesendet wurde # dann formatieren und an den anderen senden if($from->{txt_send}) { # EingabePuffer lesen und leeren my $text=$from->{txt_send}; $from->{txt_send}=''; # formatieren und in AusgabePuffer schreiben $text=~s/\n$//s; $text=~s/(^|\n)/$1$from->{name} => /gs; $to->{txt_print}.="$text\n"; } # beenden Nachricht senden wenn nötig if($from->{end} && !$from->{end_ok}) { $to->{txt_print}.="$from->{name} hat sich beendet!\n"; $from->{end_ok}=1; } }