2016-08-31 10 views
6

Mam funkcję, która działa bardzo wolno. Potrzebuję danych wejściowych z tej funkcji w głównej części programu. Tak więc chciałbym zrobić coś podobnego do polecenia UNIX yes, które produkuje tyle danych wejściowych, ile jest przeczytanych, ale tylko trochę więcej niż jest potrzebne. W przeciwieństwie do yes nie chcę wartości od STDIN, ale chcę wartości w kolejce Perl.Gwinty Perla: jak zrobić producenta?

Innymi słowy: Ten problem nie dotyczy wybrania na uchwytach plików, ale w kolejkach obsługiwanych przez wątki.

Wyobrażam kod meta będzie wyglądał podobnie do tego:

my $DataQueue = Thread::Queue->new(); 

my @producers; 
my $no_of_threads = 10; 
for (1..$no_of_threads) { 
    push @producers, threads->create(\&producer); 
} 

for(<>) { 
    # This should block until there is a value to dequeue 
    # Maybe dequeue blocks by default - then this part is not a problem 
    my $val = $DataQueue->dequeue(); 
    do_something($_,$val); 
} 
# We are done: The producers are no longer needed 
kill @producers; 

sub producer { 
    while(1) { 
     # How do I wait until the queue length is smaller than number of threads? 
     wait_until(length of $DataQueue < $no_of_threads); 
     $DataQueue->enqueue(compute_slow_value()); 
    } 
} 

Ale czy istnieje bardziej elegancki sposób to zrobić? Nie jestem szczególnie pewien, jak wykonać część wait_until w efektywny sposób.

+2

Ten czuje się strasznie dużo jak w [ 'XY problem'] (http://meta.stackexchange.com/questions/66377/what-is-the -xy-problem). Dlaczego chcesz "doładować" kolejkę? Cały punkt kolejki polega na tym, że jest to partia pracy do dokończenia - umieszczasz ją w kolejce i pozostawiasz do uruchomienia. Ale zawsze możesz użyć '$ DataQueue -> oczekujących', aby zobaczyć, ile jest tam elementów. – Sobrique

+0

Problem polega na tym, że chcę odejść od procesów. To, co zostanie przekazane, to uchwyty dla procesów. Tarło trwa wiecznie, aby się rozgrzać, jeśli zostanie wykonane w tym samym wątku. Mam całkowitą rację, nie używając kolejki, dlatego pytam, czy jest na to bardziej elegancki sposób (na przykład bez kolejki). –

+1

Cóż, może to tylko ja, ale nadal nie podążam za tym, co próbujesz zrobić. Nie ma żadnego prawdziwego powodu, dla którego nie można po prostu rozpocząć wątku, aby wykonać swój proces "odrodzenia", i po prostu użyć semafora lub podobnego do wskazania gotowości. Ale tak naprawdę - kolejka, która jest pełna rzeczy, czekająca na "spawn", aby zakończyć uruchamianie, jest ... po prostu czymś, co czeka, aby odejść, gdy tylko będzie gotowe. – Sobrique

Odpowiedz

0

Coś jak to prawdopodobnie będzie działać:

my $DataQueue = Thread::Queue->new(); 

my @producers; 
my $no_of_threads = 10; 
for (1..$no_of_threads) { 
    push @producers, threads->create(\&producer); 
} 
$DataQueue->limit = 2 * $no_of_threads; 

for(<>) { 
    # This blocks until $DataQueue->pending > 0 
    my $val = $DataQueue->dequeue(); 
    do_something($_,$val); 
} 
# We are done: The producers are no longer needed 
kill @producers; 

sub producer { 
    while(1) { 
     # enqueue will block until $DataQueue->pending < $DataQueue->limit 
     $DataQueue->enqueue(compute_slow_value()); 
    } 
}