2015-06-15 9 views
5

पर थ्रेड पूल के पीछे विचार को रूपांतरित करें मुझे फाइबर \ coroutines और क्रिस्टल में कार्यान्वयन के पीछे विचार सीखने में कुछ कठिन समय है।क्रिस्टल फाइबर/स्पॉन

मुझे आशा है कि यह इस पूछने के लिए सही जगह है, मैं पूरी तरह से एक "यहाँ नहीं" जवाब :)

स्वीकार करेंगे यह रूबी में बहु सूत्रण से निपटने में मेरी हमेशा की तरह है:

threads = [] 
max_threads = 10 

loop do 
    begin 
    threads << Thread.new do 
     helper_method(1,2,3,4) 
    end 
    rescue Exception => e 
    puts "Error Starting thread" 
    end 

    begin 
    threads = threads.select { |t| t.alive? ? true : (t.join; false) } 
    while threads.size >= max_threads 
     puts 'Got Maximum threads' 
     sleep 1 
     threads = threads.select { |t| t.alive? ? true : (t.join; false) } 
    end 
    rescue Exception => e 
    puts e 
    end 
end 

इस तरह से मैं एक नया थ्रेड खोलता हूं, आमतौर पर आने वाले कनेक्शन या किसी अन्य चीज के, थ्रेड को सरणी में जोड़ें, और फिर जांचें कि मेरे पास और अधिक धागे नहीं हैं जो मैं चाहता था।

स्पॉन \ चैनल \ फाइबर आदि का उपयोग कर क्रिस्टल में समान कुछ लागू करने का एक अच्छा तरीका क्या होगा ..?

उत्तर

12

कुछ इस तरह: 10 फाइबर

require "socket" 

ch = Channel(TCPSocket).new 

10.times do 
    spawn do 
    loop do 
     socket = ch.receive 
     socket.puts "Hi!" 
     socket.close 
    end 
    end 
end 

server = TCPServer.new(1234) 
loop do 
    socket = server.accept 
    ch.send socket 
end 

इस कोड को पूर्व अंडे जाएगा अनुरोध भाग लेने के लिए। चैनल अनबफर किया गया है, इसलिए यदि कनेक्शन किसी भी फाइबर द्वारा नहीं लिया जा सकता है तो कनेक्शन कतार में नहीं होंगे।

+1

बिल्कुल जो मैं खोज रहा था, धन्यवाद! – Ba7a7chy

5

आप धागे के लिए काम करने के तरीके को दोहराने नहीं कर सकते हैं। spawn कोरआउट ऑब्जेक्ट नहीं लौटाता है, और join कोरआउट के लिए कोई रास्ता नहीं है।

फिर भी हम कोरआउट और पूल मैनेजर के बीच संवाद करने के लिए एक चैनल खोल सकते हैं। यह प्रबंधक अपने स्वयं के कोरआउटिन के भीतर चला सकता है या मुख्य कोरआउटिन हो सकता है - यह प्रक्रिया को बाहर निकलने से रोक देगा।

यहाँ एक काम कर उदाहरण है, एक worker(&block) विधि है कि एक coroutine अंडे जाएगा, और उसकी स्थिति (यह विफल रहा है या इसे समाप्त) वापस जाने के लिए एक चैनल खुला, और एक pool(&block) विधि कि इस तरह के कर्मचारियों की एक पूल रखने के लिए और पढ़ा जाएगा साथ परिणाम चैनलों से कोरआउट की स्थिति जानने के लिए, और नए लोगों को चमकते रहें।

def worker(&block) 
    result = UnbufferedChannel(Exception?).new 

    ::spawn do 
    begin 
     block.call 
    rescue ex 
     result.send(ex) 
    else 
     result.send(nil) 
    end 
    end 

    result 
end 

def pool(size, &block) 
    counter = 0 
    results = [] of UnbufferedChannel(Exception?) 

    loop do 
    while counter < size 
     counter += 1 
     puts "spawning worker" 
     results << worker(&block) 
    end 

    result = Channel.select(results) 
    counter -= 1 
    results.delete(result) 

    if ex = result.receive 
     puts "ERROR: #{ex.message}" 
    else 
     puts "worker terminated" 
    end 
    end 
end 

pool(5) do 
    loop { helper_method(1, 2, 3, 4) } 
end 
संबंधित मुद्दे