Class: RandomPort::Pool
- Inherits:
-
Object
- Object
- RandomPort::Pool
- Defined in:
- lib/random-port/pool.rb
Overview
Pool of TPC ports.
Use it like this:
RandomPort::Pool.new.acquire do |port|
# Use the TCP port. It will be returned back
# to the pool afterwards.
end
You can specify the maximum amount of ports to acquire, using limit
. If more acquiring requests will arrive, an exception will be raised.
The class is thread-safe, by default. You can configure it to be not-thread-safe, using optional sync
argument of the constructor, passing FALSE
.
- Author
-
Yegor Bugayenko ([email protected])
- Copyright
-
Copyright © 2018-2024 Yegor Bugayenko
- License
-
MIT
Defined Under Namespace
Classes: Timeout
Constant Summary collapse
- SINGLETON =
Application wide pool of ports
RandomPort::Pool.new
Instance Attribute Summary collapse
-
#limit ⇒ Object
readonly
Returns the value of attribute limit.
Instance Method Summary collapse
-
#acquire(total = 1, timeout: 4) ⇒ Object
Acquire a new random TCP port.
-
#count ⇒ Object
(also: #size)
How many ports acquired now?.
-
#empty? ⇒ Boolean
Is it empty?.
-
#initialize(sync: true, limit: 65_536) ⇒ Pool
constructor
Ctor.
-
#release(port) ⇒ Object
Return it/them back to the pool.
Constructor Details
#initialize(sync: true, limit: 65_536) ⇒ Pool
Ctor.
57 58 59 60 61 62 63 |
# File 'lib/random-port/pool.rb', line 57 def initialize(sync: true, limit: 65_536) @ports = [] @sync = sync @monitor = Monitor.new @limit = limit @next = 0 end |
Instance Attribute Details
#limit ⇒ Object (readonly)
Returns the value of attribute limit.
52 53 54 |
# File 'lib/random-port/pool.rb', line 52 def limit @limit end |
Instance Method Details
#acquire(total = 1, timeout: 4) ⇒ Object
Acquire a new random TCP port.
You can specify the number of ports to acquire. If it’s more than one, an array will be returned.
You can specify the amount of seconds to wait until a new port is available.
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 |
# File 'lib/random-port/pool.rb', line 86 def acquire(total = 1, timeout: 4) start = Time.now loop do if Time.now > start + timeout raise \ Timeout, "Can't find a place in the pool of #{@limit} ports " \ "for #{total} port(s), in #{format('%.02f', Time.now - start)}s" end opts = safe do next if @ports.count + total > @limit opts = Array.new(0, total) begin (0..(total - 1)).each do |i| opts[i] = take(i.zero? ? @next : opts[i - 1] + 1) end rescue Errno::EADDRINUSE, SocketError next end next if opts.any? { |p| @ports.include?(p) } d = total * (total - 1) / 2 next unless opts.inject(&:+) - (total * opts.min) == d @ports += opts opts end next if opts.nil? @next = opts.max + 1 @next = 0 if @next > 65_535 opts = opts[0] if total == 1 return opts unless block_given? begin return yield opts ensure release(opts) end end end |
#count ⇒ Object Also known as: size
How many ports acquired now?
69 70 71 |
# File 'lib/random-port/pool.rb', line 69 def count @ports.count end |
#empty? ⇒ Boolean
Is it empty?
75 76 77 |
# File 'lib/random-port/pool.rb', line 75 def empty? @ports.empty? end |
#release(port) ⇒ Object
Return it/them back to the pool.
125 126 127 128 129 130 131 132 133 |
# File 'lib/random-port/pool.rb', line 125 def release(port) safe do if port.is_a?(Array) port.each { |p| @ports.delete(p) } else @ports.delete(port) end end end |