Skip to content

Commit cf131ae

Browse files
committed
Moved semaphore classes into own files.
1 parent 0df85fb commit cf131ae

File tree

2 files changed

+199
-178
lines changed

2 files changed

+199
-178
lines changed
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
require 'concurrent/synchronization'
2+
3+
module Concurrent
4+
5+
# @!macro semaphore
6+
# @!visibility private
7+
# @!macro internal_implementation_note
8+
class MutexSemaphore < Synchronization::Object
9+
10+
# @!macro semaphore_method_initialize
11+
def initialize(count)
12+
unless count.is_a?(Fixnum) && count >= 0
13+
fail ArgumentError, 'count must be an non-negative integer'
14+
end
15+
super()
16+
synchronize { ns_initialize count }
17+
end
18+
19+
# @!macro semaphore_method_acquire
20+
def acquire(permits = 1)
21+
unless permits.is_a?(Fixnum) && permits > 0
22+
fail ArgumentError, 'permits must be an integer greater than zero'
23+
end
24+
synchronize do
25+
try_acquire_timed(permits, nil)
26+
nil
27+
end
28+
end
29+
30+
# @!macro semaphore_method_available_permits
31+
def available_permits
32+
synchronize { @free }
33+
end
34+
35+
# @!macro semaphore_method_drain_permits
36+
#
37+
# Acquires and returns all permits that are immediately available.
38+
#
39+
# @return [Integer]
40+
def drain_permits
41+
synchronize do
42+
@free.tap { |_| @free = 0 }
43+
end
44+
end
45+
46+
# @!macro semaphore_method_try_acquire
47+
def try_acquire(permits = 1, timeout = nil)
48+
unless permits.is_a?(Fixnum) && permits > 0
49+
fail ArgumentError, 'permits must be an integer greater than zero'
50+
end
51+
synchronize do
52+
if timeout.nil?
53+
try_acquire_now(permits)
54+
else
55+
try_acquire_timed(permits, timeout)
56+
end
57+
end
58+
end
59+
60+
# @!macro semaphore_method_release
61+
def release(permits = 1)
62+
unless permits.is_a?(Fixnum) && permits > 0
63+
fail ArgumentError, 'permits must be an integer greater than zero'
64+
end
65+
synchronize do
66+
@free += permits
67+
permits.times { ns_signal }
68+
end
69+
nil
70+
end
71+
72+
# Shrinks the number of available permits by the indicated reduction.
73+
#
74+
# @param [Fixnum] reduction Number of permits to remove.
75+
#
76+
# @raise [ArgumentError] if `reduction` is not an integer or is negative
77+
#
78+
# @raise [ArgumentError] if `@free` - `@reduction` is less than zero
79+
#
80+
# @return [nil]
81+
#
82+
# @!visibility private
83+
def reduce_permits(reduction)
84+
unless reduction.is_a?(Fixnum) && reduction >= 0
85+
fail ArgumentError, 'reduction must be an non-negative integer'
86+
end
87+
synchronize { @free -= reduction }
88+
nil
89+
end
90+
91+
protected
92+
93+
# @!visibility private
94+
def ns_initialize(count)
95+
@free = count
96+
end
97+
98+
private
99+
100+
# @!visibility private
101+
def try_acquire_now(permits)
102+
if @free >= permits
103+
@free -= permits
104+
true
105+
else
106+
false
107+
end
108+
end
109+
110+
# @!visibility private
111+
def try_acquire_timed(permits, timeout)
112+
ns_wait_until(timeout) { try_acquire_now(permits) }
113+
end
114+
end
115+
end

0 commit comments

Comments
 (0)