Class: Async::Semaphore
- Inherits:
- 
      Object
      
        - Object
- Async::Semaphore
 
- Defined in:
- lib/async/semaphore.rb
Overview
A semaphore is used to control access to a common resource in a concurrent system. A useful way to think of a semaphore as used in the real-world systems is as a record of how many units of a particular resource are available, coupled with operations to adjust that record safely (i.e. to avoid race conditions) as units are required or become free, and, if necessary, wait until a unit of the resource becomes available.
Instance Attribute Summary collapse
- 
  
    
      #count  ⇒ Object 
    
    
  
  
  
  
    
      readonly
    
    
  
  
  
  
  
  
    The current number of tasks that have acquired the semaphore. 
- 
  
    
      #limit  ⇒ Object 
    
    
  
  
  
  
    
      readonly
    
    
  
  
  
  
  
  
    The maximum number of tasks that can acquire the semaphore. 
- 
  
    
      #waiting  ⇒ Object 
    
    
  
  
  
  
    
      readonly
    
    
  
  
  
  
  
  
    The tasks waiting on this semaphore. 
Instance Method Summary collapse
- 
  
    
      #acquire { ... } ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    Acquire the semaphore, block if we are at the limit. 
- 
  
    
      #async(*arguments, parent: (@parent or Task.current), **options)  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    Run an async task. 
- 
  
    
      #blocking?  ⇒ Boolean 
    
    
  
  
  
  
  
  
  
  
  
    Whether trying to acquire this semaphore would block. 
- 
  
    
      #empty?  ⇒ Boolean 
    
    
  
  
  
  
  
  
  
  
  
    Is the semaphore currently acquired?. 
- 
  
    
      #initialize(limit = 1, parent: nil)  ⇒ Semaphore 
    
    
  
  
  
    constructor
  
  
  
  
  
  
  
    A new instance of Semaphore. 
- 
  
    
      #release  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    Release the semaphore. 
Constructor Details
#initialize(limit = 1, parent: nil) ⇒ Semaphore
Returns a new instance of Semaphore.
| 26 27 28 29 30 31 32 | # File 'lib/async/semaphore.rb', line 26 def initialize(limit = 1, parent: nil) @count = 0 @limit = limit @waiting = [] @parent = parent end | 
Instance Attribute Details
#count ⇒ Object (readonly)
The current number of tasks that have acquired the semaphore.
| 35 36 37 | # File 'lib/async/semaphore.rb', line 35 def count @count end | 
#limit ⇒ Object (readonly)
The maximum number of tasks that can acquire the semaphore.
| 38 39 40 | # File 'lib/async/semaphore.rb', line 38 def limit @limit end | 
#waiting ⇒ Object (readonly)
The tasks waiting on this semaphore.
| 41 42 43 | # File 'lib/async/semaphore.rb', line 41 def waiting @waiting end | 
Instance Method Details
#acquire { ... } ⇒ Object
Acquire the semaphore, block if we are at the limit. If no block is provided, you must call release manually.
| 72 73 74 75 76 77 78 79 80 81 82 83 84 | # File 'lib/async/semaphore.rb', line 72 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.
| 54 55 56 57 58 59 60 61 62 63 64 65 66 | # File 'lib/async/semaphore.rb', line 54 def async(*arguments, parent: (@parent or Task.current), **) wait parent.async(**) do |task| @count += 1 begin yield task, *arguments ensure self.release end end end | 
#blocking? ⇒ Boolean
Whether trying to acquire this semaphore would block.
| 49 50 51 | # File 'lib/async/semaphore.rb', line 49 def blocking? @count >= @limit end | 
#empty? ⇒ Boolean
Is the semaphore currently acquired?
| 44 45 46 | # File 'lib/async/semaphore.rb', line 44 def empty? @count.zero? end | 
#release ⇒ Object
Release the semaphore. Must match up with a corresponding call to ‘acquire`. Will release waiting fibers in FIFO order.
| 87 88 89 90 91 92 93 94 95 | # File 'lib/async/semaphore.rb', line 87 def release @count -= 1 while (@limit - @count) > 0 and fiber = @waiting.shift if fiber.alive? fiber.resume end end end |