Skip to content

Instantly share code, notes, and snippets.

@rklemme
Created November 14, 2011 08:16
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 rklemme/1363513 to your computer and use it in GitHub Desktop.
Save rklemme/1363513 to your computer and use it in GitHub Desktop.
Simple semaphore implementation
require 'monitor'
# Simple semaphore implementation using Monitor and ConditionVariable
class Semaphore
def initialize(initial_value = 0)
@val = initial_value
@lock = Monitor.new
@available = ConditionVariable.new
end
def wait(take = 1)
take = permit_check(take)
@lock.synchronize do
while @val - take < 0
@available.wait(@lock)
end
@val -= take
end
end
def signal(put = 1)
put = permit_check(put)
@lock.synchronize do
@val += put
@available.broadcast
end
end
def synchronize(permits = 1)
permits = permit_check(permits)
wait(permits)
begin
yield
ensure
signal(permits)
end
end
private
# Check the permits and throw if illegal. Otherwise return the value.
def permit_check(permits)
x = permits.to_int
raise ArgumentError, "Illegal no. of permits: #{x.inspect}" if x <= 0
x
end
end
# test
if __FILE__ == $0
c = 0
sem = Semaphore.new 1
4.times.map do |i|
Thread.new i do |ii|
3.times { sem.synchronize { c += 1; printf "%2d: %3d\n", ii, c } }
end
end.each(&:join)
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment