2016-08-31 17 views
6

Çalıştırmak için çok yavaş olan bir işlev var. Programın ana bölümünde bu işlevin girişine ihtiyacım var. Bu yüzden, okunan kadar fazla girdi üreten, ancak ihtiyaç duyulandan biraz daha fazla olan yes UNIX komutuna benzer bir şey yapmak istiyorum. yes'dan farklı olarak STDIN değerlerini istemiyorum ancak değerleri bir Perl kuyruğunda istiyorum.Perl konuları: Nasıl yapımcı olunur?

Başka bir deyişle: Bu sorun, dosya tanıtıcıları seçmeyle ilgili değil, iş parçacığı tarafından tutulan sıralarda.

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

Ama bunu yapmanın daha zarif bir yolu yoktur:

Ben meta kodu bu benzer olacaktır hayal? Özellikle wait_until parçasının verimli bir şekilde nasıl yapıldığından emin değilim.

+2

Bu http://meta.stackexchange.com/questions/66377/what-is-the bir [ 'XY problem'] (gibi bir sürü kötü hissediyor -XY-sorunu). Neden sıraya girmek istiyorsun? Bir sıranın bütün noktası, tamamlanması gereken bir iş yığınlarıdır - sıraya alırsınız ve onu çalıştırmaya bırakın. Ancak, kaç öğe bulunduğunu görmek için her zaman '$ DataQueue -> pending 'yöntemini kullanabilirsiniz. – Sobrique

+0

Sorun şu ki, prepawn işlemleri yapmak istiyorum. Neler geçecek, süreçler için bir tutacak. Aynı iş parçacığında yapılırsa, yumurtlama sonsuza kadar ısınır. Bir kuyruğu kullanmama ile tamamıyla iyiyim, bu yüzden bunu yapmak için daha zarif bir yol var mı diye sorarım (örneğin bir sıra olmadan). –

+1

Eh, belki sadece ben varım, ama yapmaya çalıştığınız şeyi hala takip etmiyorum. “Önceden yumurtlama” işleminizi yapmak için bir iş parçacığı başlatmanızın gerçek bir sebebi yok ve sadece bir Semafor'u ya da hazırlığı belirtmek için benzer bir yöntem kullanın. Ama gerçekten - bir şeylerin dolduğu, 'yumurtlamanın' başlangıcını bitirmeyi beklediği bir sıra ... sadece hazır olduğu anda gitmeyi bekleyen bir şey. – Sobrique

cevap

0

Böyle bir şey muhtemelen çalışacaktır:

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()); 
    } 
} 
İlgili konular