Skip to content

Instantly share code, notes, and snippets.

@igrigorik
Forked from tmm1/gist:61014
Created April 13, 2010 23:43
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 igrigorik/365249 to your computer and use it in GitHub Desktop.
Save igrigorik/365249 to your computer and use it in GitHub Desktop.
class FiberedMutex
#
# Creates a new FiberedMutex
#
def initialize
@waiting = []
@locked = false
end
#
# Returns +true+ if this lock is currently held by some fiber.
#
def locked?
@locked
end
#
# Obtains a lock, runs the block, and releases the lock when the block
# completes.
#
def synchronize
lock
begin
yield
ensure
unlock
end
end
#
# Attempts to grab the lock and waits if it isn't available.
#
def lock
while @locked
raise FiberError, "deadlock; #{self.class} already locked for #{@locked.inspect}" if @locked == Fiber.current
@waiting.push Fiber.current
Fiber.yield
end
@locked = Fiber.current
self
end
#
# Releases the lock. Returns +nil+ if ref wasn't locked.
#
def unlock
return unless @locked
@locked = false
if f = @waiting.shift
if defined? EM and EM.reactor_running?
EM.next_tick{ f.resume }
else
f.resume
end
end
self
end
end
if __FILE__ == $0
require 'fiber'
require 'neverblock'
require 'eventmachine'
def sleep n
f = Fiber.current
EM.add_timer(n){ f.resume }
Fiber.yield
end
pool = NB::Pool::FiberPool.new(5)
mutex = FiberedMutex.new
EM.run{
15.times do
pool.spawn{
mutex.synchronize{
# mutex.synchronize{
puts 'hi'; sleep 1; puts 'bye'
# }
}
}
end
}
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment