Class: Async::Semaphore

Inherits:
Object
  • Object
show all
Defined in:
lib/async/semaphore.rb

Overview

A synchronization primitive, which limits access to a given resource.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(limit = 1, parent: nil) ⇒ Semaphore

Returns a new instance of Semaphore.



14
15
16
17
18
19
20
# File 'lib/async/semaphore.rb', line 14

def initialize(limit = 1, parent: nil)
	@count = 0
	@limit = limit
	@waiting = List.new
	
	@parent = parent
end

Instance Attribute Details

#countObject (readonly)

The current number of tasks that have acquired the semaphore.



23
24
25
# File 'lib/async/semaphore.rb', line 23

def count
  @count
end

#limitObject

The maximum number of tasks that can acquire the semaphore.



26
27
28
# File 'lib/async/semaphore.rb', line 26

def limit
  @limit
end

#waitingObject (readonly)

The tasks waiting on this semaphore.



29
30
31
# File 'lib/async/semaphore.rb', line 29

def waiting
  @waiting
end

Instance Method Details

#acquireObject

Acquire the semaphore, block if we are at the limit. If no block is provided, you must call release manually.



79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/async/semaphore.rb', line 79

def acquire
	wait
	
	@count += 1
	
	return unless block_given?
	
	begin
		return yield
	ensure
		self.release
	end
end

#async(*arguments, parent: (@parent or Task.current), **options) ⇒ Object

Run an async task. Will wait until the semaphore is ready until spawning and running the task.



61
62
63
64
65
66
67
68
69
70
71
72
73
# File 'lib/async/semaphore.rb', line 61

def async(*arguments, parent: (@parent or Task.current), **options)
	wait
	
	parent.async(**options) do |task|
		@count += 1
		
		begin
			yield task, *arguments
		ensure
			self.release
		end
	end
end

#blocking?Boolean

Whether trying to acquire this semaphore would block.

Returns:

  • (Boolean)


56
57
58
# File 'lib/async/semaphore.rb', line 56

def blocking?
	@count >= @limit
end

#empty?Boolean

Is the semaphore currently acquired?

Returns:

  • (Boolean)


51
52
53
# File 'lib/async/semaphore.rb', line 51

def empty?
	@count.zero?
end

#releaseObject

Release the semaphore. Must match up with a corresponding call to ‘acquire`. Will release waiting fibers in FIFO order.



94
95
96
97
98
99
100
# File 'lib/async/semaphore.rb', line 94

def release
	@count -= 1
	
	while (@limit - @count) > 0 and node = @waiting.first
		node.resume
	end
end