2014-02-20 110 views
1

比方說,我有一個計劃中包含一個循環:重新啓動循環與信號

#!/usr/bin/env ruby 

puts $$ 

def do_work 
    puts Time.now 
end 

Signal.trap("HUP") do 
    do_work 
end 

loop do 
    sleep 60 
    do_work 
end 

它「做工作」每60秒。有時我不想等整整60秒,所以我立即將HUP信號捕獲到do_work。這很好,除了一件事:我想在處理信號後重置60秒時鐘。現在它的設置方式,如果睡眠是45秒,我發送程序SIGHUP,它會do_work,然後15秒後,它會再次do_work

我該如何修改這個函數來處理上述約束?

回答

1

聲明:我使用信號INT(由ctrl + C觸發)測試我的代碼,因爲我在Windows上沒有HUP。 http://en.wikipedia.org/wiki/Unix_signal#POSIX_signals使我相信HUP應該也能正常工作,但我不能100%確定。

爲您列出的示例代碼,你可以從循環移動sleep 60do_work方法內:

def do_work 
    puts Time.now 
    sleep 60 
end 

Signal.trap("HUP") do 
    do_work 
end 

loop do 
    do_work 
end 

不過,也有可能是更好的方式來封裝邏輯,使之可重複使用。以下是我想出了:

class Worker 
    attr_accessor :interval 
    attr_reader :times_worked 

    def initialize(interval, signal) 
    @signal = signal 
    @interval = interval 
    @times_worked = 0 
    end 

    def set_task(&block) 
    @work_to_do = block 
    Signal.trap(signal) { do_work } 
    start 
    end 

    def stop 
    @stop = true 
    end 

    def start 
    @stop = false 
    loop do 
     break if @stop 
     do_work 
    end 
    end 

    def do_work 
    @work_to_do.call 
    @times_worked += 1 # just an example of something you could put here 
    sleep @interval 
    end 
end 

worker = Worker.new(5, "HUP") 
worker.set_task { puts Time.now } 
+0

雖然它看起來像它的工作原理是一個可怕的解決方案。 'HUP'會中斷當前正在運行的'do_work'(在'sleep'中間不需要)並啓動另一個'do_work'。此外,它不能在「陷阱」區塊內第二次中斷。做陷阱的任何事情首先是一個壞主意。 –

+0

@VictorMoroz優秀點 –

+0

我承認,我只是把它們扔在了一起,實際上我從未使用過'Signal'類。也許我應該對此坦率一些。我會說,我確實很有趣,使這個代碼=) –

1

可能的解決辦法:

q1, q2 = (0..1).map { Queue.new } 

Thread.new do 
    loop do 
    time, seq = q1.pop 
    delta = time - Time.now 
    sleep delta if delta > 0 
    q2.push seq 
    end 
end 

Signal.trap("HUP") do 
    Thread.new do 
    q2.push nil 
    end 
end 

seq = 0 
q2.push seq 
loop do 
    # Drop expired sequences 
    while (event_seq = q2.pop; event_seq && event_seq != seq) 
    end 

    # If HUP expire current sequence 
    seq += 1 unless event_seq 

    # Do work here 
    p Time.now 

    q1.push [Time.now + 60, seq] 
end 
相關問題