Skip to content

Instantly share code, notes, and snippets.

@wycleffsean
Last active February 4, 2019 21:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save wycleffsean/c4839c2729ba2fa767b423e953add709 to your computer and use it in GitHub Desktop.
Save wycleffsean/c4839c2729ba2fa767b423e953add709 to your computer and use it in GitHub Desktop.
Fiber Sleep
require 'fiber'
require 'concurrent' # gem install concurrent-ruby
Thread.abort_on_exception = true
class Async
def self.perform(&block)
instance = new
instance.instance_eval(&block)
until instance.dispatched.value.zero? do
unless instance.yields.empty?
fiber = instance.yields.pop
instance.dispatched.decrement
fiber.resume
end
end
end
attr_reader :dispatched, :yields
def initialize
@dispatched = Concurrent::AtomicFixnum.new
@yields = Queue.new
end
def job(&block)
fiber = Fiber.new do
Block.new(self).instance_eval &block
end.resume
end
class Block < Struct.new(:parent)
def sleepx(duration)
current = Fiber.current
parent.dispatched.increment
Thread.new do
sleep(duration)
parent.yields.push current
end
Fiber.yield
end
end
end
Async.perform do
job do
sleepx(5)
puts 'slept 5'
end
job do
sleepx(4)
puts 'slept 4'
end
job do
sleepx(2)
puts 'slept 2'
end
job do
sleepx(6)
puts 'slept 6'
end
job do
sleepx(3)
puts 'slept 3'
end
job do
sleepx(1)
puts 'slept 1'
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment