Skip to content

Instantly share code, notes, and snippets.

@benolee
Forked from wycleffsean/fiber_sleep.rb
Created February 4, 2019 21:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save benolee/3bdeff5dcaa08de77dbe131a38965ca3 to your computer and use it in GitHub Desktop.
Save benolee/3bdeff5dcaa08de77dbe131a38965ca3 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