Skip to content

Instantly share code, notes, and snippets.

@panaggio
Created July 24, 2010 20:01
Show Gist options
  • Save panaggio/488926 to your computer and use it in GitHub Desktop.
Save panaggio/488926 to your computer and use it in GitHub Desktop.
class Semaphore
#
# Creates a new Semaphore
#
def initialize(initvalue = 0)
@counter = @max = initvalue
@waiting = []
@mutex = Mutex.new
end
#
# Attempts to enter and waits if the semaphore is already full
#
def wait
@mutex.lock
if (@counter -= 1) < 0
@waiting.push(Thread.current)
Thread.stop
end
ensure
@mutex.unlock
end
alias down wait
#
# Leaves and let another thread in, if there's any waiting
#
def signal
@mutex.lock
begin
#if (@counter = [@counter+1,@max].min) <= 0
if (@counter += 1) <= 0
t = @waiting.shift
t.wakeup if t
end
rescue ThreadError
retry
end
ensure
@mutex.unlock
end
alias up signal
end
sem.rb:5:in `block in <main>'
sleep
/tmp/ruby/lib/ruby/1.9.1/thread.rb:50:in `wait'
sem.rb:6:in `block in <main>'
sleep
/tmp/ruby/lib/ruby/1.9.1/thread.rb:62:in `signal'
sem.rb:5:in `block in <main>'
sleep
/tmp/ruby/lib/ruby/1.9.1/thread.rb:50:in `wait'
sem.rb:6:in `block in <main>'
require "thread"
s = Semaphore.new(1)
t1 = Thread.new { s.down; Thread.stop; s.up }
t2 = Thread.new { s.down; puts "It works" }
puts t1.status
puts t1.backtrace
puts t2.status
puts t2.backtrace
t1.run
puts t1.status
puts t1.backtrace
puts t2.status
puts t2.backtrace
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment