Class: Ori::ReentrantSemaphore

Inherits:
Object
  • Object
show all
Includes:
Selectable
Defined in:
lib/ori/reentrant_semaphore.rb

Instance Method Summary collapse

Constructor Details

#initialize(num_tickets) ⇒ ReentrantSemaphore

Returns a new instance of ReentrantSemaphore.

Raises:

  • (ArgumentError)


7
8
9
10
11
12
13
# File 'lib/ori/reentrant_semaphore.rb', line 7

def initialize(num_tickets)
  raise ArgumentError, "Number of tickets must be positive" if num_tickets <= 0

  @tickets = num_tickets
  @available = num_tickets
  @owners = Hash.new(0) # Track fiber -> acquire count
end

Instance Method Details

#acquireObject



39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/ori/reentrant_semaphore.rb', line 39

def acquire
  current = Fiber.current

  # If this fiber already owns the semaphore, increment its count
  if @owners[current] > 0
    @owners[current] += 1
    return true
  end

  # Otherwise wait for an available ticket
  Fiber.yield(self) until available?
  @available -= 1
  @owners[current] = 1
  true
end

#available?Boolean

Returns:

  • (Boolean)


55
56
57
# File 'lib/ori/reentrant_semaphore.rb', line 55

def available?
  @available > 0 || @owners[Fiber.current] > 0
end

#awaitObject



63
64
65
66
# File 'lib/ori/reentrant_semaphore.rb', line 63

def await
  Fiber.yield until available?
  true
end

#countObject



59
60
61
# File 'lib/ori/reentrant_semaphore.rb', line 59

def count
  @available
end

#releaseObject



24
25
26
27
28
29
30
31
32
33
34
35
36
37
# File 'lib/ori/reentrant_semaphore.rb', line 24

def release
  current = Fiber.current

  if @owners[current] > 0
    @owners[current] -= 1
    if @owners[current] == 0
      @owners.delete(current)
      @available += 1
    end
    return true
  end

  raise "Cannot release semaphore - not owned by current fiber"
end

#syncObject



15
16
17
18
19
20
21
22
# File 'lib/ori/reentrant_semaphore.rb', line 15

def sync
  acquire
  begin
    yield
  ensure
    release
  end
end