1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
module Every @interval, @stopped = 0.0, true @numwords = {"one"=>1, "two"=>2, "three"=>3, "four"=>4, "five"=>5, "six"=>6, "seven"=>7, "eight"=>8, "nine"=>9, "ten"=>10, "eleven"=>11, "twelve"=>12, "thirteen"=>13, "fourteen"=>14, "fifteen"=>15, "sixteen"=>16, "seventeen"=>17, "eighteen"=>18, "nineteen"=>19, "twenty"=>20, "thirty"=>30, "forty"=>40, "fifty"=>50} protected #todo: figure out a better repeat_every function and make accessable only to the Every module def time_block start_time = Time.now yield if block_given? return Time.now - start_time end def repeat_every(seconds) while !@stopped do sleep( seconds - time_block { yield if block_given? } ) # again ignoring time > seconds end end public def break @stopped, @interval = true, 0.01 end def method_missing(meth, *args, &block) meth = meth.to_s.downcase if meth == "millisecond" @stopped, @interval = false, 0.01 repeat_every(@interval) { block.call(self) if block } elsif meth == "second" @stopped, @interval = false, 1 repeat_every(@interval) { block.call(self) if block } elsif meth == "minute" @stopped, @interval = false, 60 repeat_every(@interval) { block.call(self) if block } elsif meth == "hour" @stopped, @interval = false, 3600 repeat_every(@interval) { block.call(self) if block } elsif meth == "milliseconds" @stopped, @interval = false, @interval / 60 repeat_every(@interval) { block.call(self) if block } @stopped, @interval = true, 0 elsif meth == ("seconds" || "minutes" || "hours") @stopped = false repeat_every(@interval) { block.call(self) if block } @stopped, @interval = true, 0 elsif meth == "stopped?" @stopped elsif meth == "interval" @interval elsif @numwords[meth] @interval += @numwords[meth] self else @stopped, @interval = true, 0 raise("\n Method missin': \"#{meth}\"\n You prolly fucked up... srsly wtf?\n") end end module_function :method_missing, :break, :time_block, :repeat_every end
Refactorings
No refactoring yet !
elliottcable
June 15, 2008, June 15, 2008 06:17, permalink
Make sure to read here about the threadsafety and strict clocking I worked in: http://pastie.org/215285
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
# Used to repeat a block at a given interval, in seconds. # Repeat::Every 30 do # puts "I will be printed every thirty seconds" # end # Can be told to not abide slow iterations, and continue on according to # schedule regardless of the state of block-execute iterations: # Repeat::Every 4 do # sleep 5; puts "I completed after the next block was initiated" # end # Finally, some convenience methods are proffered for working with the seconds: # Repeat::Every 2.hours do; end # Repeat::Every 3.days do; end # Repeat::Every 140.milliseconds do; end module Repeat StretchMarks = { # In seconds :millisecond => 0.001, :centisecond => 0.01, :second => 1.0, :minute => 59.83617, :hour => 3590.1702, :day => 86_164.09, :week => 603_148.63 } class <<self def Every period, opts = {}, &action begin while true act = Thread.new &action hold = Thread.new { sleep period } # Strict timekeeping: Takes :strict => tru in the opts, which # causes it to ignore slow blocks. Otherwise, it will continue to # wait for slow blocks to evaluate before initiating the next block, # even if they exceed the allowed iteration time. unless opts[:strict] [act, hold].map {|t| t.join } else act.run hold.join end end rescue Interrupt puts "\n" # Cleanly exit the loop. end end end module Every class <<self # Unfortunately, we can't do a metaprogrammy bit of magic here, due to the # fact that blocks in 1.8 can't take other blocks as arguments. Hence, you # have to do some lambda magic like this to use the singualar syntax: # Repeat::Every.minute(lambda do # puts 'whee' # end) ::Repeat::StretchMarks.each do |stretch, period| define_method stretch do |proc| ::Repeat::Every 1.send(stretch.to_s + 's'), &proc end end end end class ::Fixnum ::Repeat::StretchMarks.each do |stretch, period| define_method(stretch.to_s + 's') do period * self end end end end
Loop a block of code every set interval:
Every.twenty.milliseconds { #stuff }
Every.second { #stuff }
Every.two.minutes { #stuff }
Every.twenty.four.hours { #stuff }
You get the idea..