concurrent-ruby 0.9.2-java → 1.0.0-java

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (121) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +49 -1
  3. data/README.md +86 -120
  4. data/lib/concurrent.rb +14 -5
  5. data/lib/concurrent/agent.rb +587 -0
  6. data/lib/concurrent/array.rb +39 -0
  7. data/lib/concurrent/async.rb +296 -149
  8. data/lib/concurrent/atom.rb +135 -45
  9. data/lib/concurrent/atomic/abstract_thread_local_var.rb +38 -0
  10. data/lib/concurrent/atomic/atomic_boolean.rb +83 -118
  11. data/lib/concurrent/atomic/atomic_fixnum.rb +101 -163
  12. data/lib/concurrent/atomic/atomic_reference.rb +1 -8
  13. data/lib/concurrent/atomic/count_down_latch.rb +62 -103
  14. data/lib/concurrent/atomic/cyclic_barrier.rb +3 -1
  15. data/lib/concurrent/atomic/event.rb +1 -1
  16. data/lib/concurrent/atomic/java_count_down_latch.rb +39 -0
  17. data/lib/concurrent/atomic/java_thread_local_var.rb +50 -0
  18. data/lib/concurrent/atomic/mutex_atomic_boolean.rb +60 -0
  19. data/lib/concurrent/atomic/mutex_atomic_fixnum.rb +91 -0
  20. data/lib/concurrent/atomic/mutex_count_down_latch.rb +43 -0
  21. data/lib/concurrent/atomic/mutex_semaphore.rb +115 -0
  22. data/lib/concurrent/atomic/read_write_lock.rb +5 -4
  23. data/lib/concurrent/atomic/reentrant_read_write_lock.rb +3 -1
  24. data/lib/concurrent/atomic/ruby_thread_local_var.rb +172 -0
  25. data/lib/concurrent/atomic/semaphore.rb +84 -178
  26. data/lib/concurrent/atomic/thread_local_var.rb +65 -294
  27. data/lib/concurrent/atomic_reference/jruby+truffle.rb +1 -0
  28. data/lib/concurrent/atomic_reference/jruby.rb +1 -1
  29. data/lib/concurrent/atomic_reference/mutex_atomic.rb +14 -8
  30. data/lib/concurrent/atomic_reference/ruby.rb +1 -1
  31. data/lib/concurrent/atomics.rb +7 -37
  32. data/lib/concurrent/collection/copy_on_notify_observer_set.rb +7 -15
  33. data/lib/concurrent/collection/copy_on_write_observer_set.rb +7 -15
  34. data/lib/concurrent/collection/java_non_concurrent_priority_queue.rb +84 -0
  35. data/lib/concurrent/collection/map/atomic_reference_map_backend.rb +927 -0
  36. data/lib/concurrent/collection/map/mri_map_backend.rb +66 -0
  37. data/lib/concurrent/collection/map/non_concurrent_map_backend.rb +144 -0
  38. data/lib/concurrent/collection/map/synchronized_map_backend.rb +86 -0
  39. data/lib/concurrent/collection/non_concurrent_priority_queue.rb +143 -0
  40. data/lib/concurrent/collection/ruby_non_concurrent_priority_queue.rb +150 -0
  41. data/lib/concurrent/concern/dereferenceable.rb +9 -24
  42. data/lib/concurrent/concern/logging.rb +1 -1
  43. data/lib/concurrent/concern/obligation.rb +11 -20
  44. data/lib/concurrent/concern/observable.rb +38 -13
  45. data/lib/concurrent/configuration.rb +23 -152
  46. data/lib/concurrent/constants.rb +8 -0
  47. data/lib/concurrent/delay.rb +14 -12
  48. data/lib/concurrent/exchanger.rb +339 -41
  49. data/lib/concurrent/executor/abstract_executor_service.rb +134 -0
  50. data/lib/concurrent/executor/executor_service.rb +23 -359
  51. data/lib/concurrent/executor/immediate_executor.rb +3 -2
  52. data/lib/concurrent/executor/java_executor_service.rb +100 -0
  53. data/lib/concurrent/executor/java_single_thread_executor.rb +3 -3
  54. data/lib/concurrent/executor/java_thread_pool_executor.rb +3 -4
  55. data/lib/concurrent/executor/ruby_executor_service.rb +78 -0
  56. data/lib/concurrent/executor/ruby_single_thread_executor.rb +10 -66
  57. data/lib/concurrent/executor/ruby_thread_pool_executor.rb +25 -22
  58. data/lib/concurrent/executor/safe_task_executor.rb +6 -7
  59. data/lib/concurrent/executor/serial_executor_service.rb +34 -0
  60. data/lib/concurrent/executor/serialized_execution.rb +10 -33
  61. data/lib/concurrent/executor/serialized_execution_delegator.rb +28 -0
  62. data/lib/concurrent/executor/simple_executor_service.rb +1 -10
  63. data/lib/concurrent/executor/single_thread_executor.rb +20 -10
  64. data/lib/concurrent/executor/timer_set.rb +8 -10
  65. data/lib/concurrent/executors.rb +12 -2
  66. data/lib/concurrent/future.rb +6 -4
  67. data/lib/concurrent/hash.rb +35 -0
  68. data/lib/concurrent/immutable_struct.rb +5 -1
  69. data/lib/concurrent/ivar.rb +12 -16
  70. data/lib/concurrent/lazy_register.rb +11 -8
  71. data/lib/concurrent/map.rb +180 -0
  72. data/lib/concurrent/maybe.rb +6 -3
  73. data/lib/concurrent/mutable_struct.rb +7 -6
  74. data/lib/concurrent/mvar.rb +26 -2
  75. data/lib/concurrent/{executor/executor.rb → options.rb} +5 -29
  76. data/lib/concurrent/promise.rb +7 -5
  77. data/lib/concurrent/scheduled_task.rb +13 -71
  78. data/lib/concurrent/settable_struct.rb +5 -4
  79. data/lib/concurrent/synchronization.rb +15 -3
  80. data/lib/concurrent/synchronization/abstract_lockable_object.rb +98 -0
  81. data/lib/concurrent/synchronization/abstract_object.rb +7 -146
  82. data/lib/concurrent/synchronization/abstract_struct.rb +2 -3
  83. data/lib/concurrent/synchronization/condition.rb +6 -4
  84. data/lib/concurrent/synchronization/jruby_lockable_object.rb +13 -0
  85. data/lib/concurrent/synchronization/jruby_object.rb +44 -0
  86. data/lib/concurrent/synchronization/lock.rb +3 -2
  87. data/lib/concurrent/synchronization/lockable_object.rb +72 -0
  88. data/lib/concurrent/synchronization/mri_lockable_object.rb +71 -0
  89. data/lib/concurrent/synchronization/mri_object.rb +43 -0
  90. data/lib/concurrent/synchronization/object.rb +140 -73
  91. data/lib/concurrent/synchronization/rbx_lockable_object.rb +65 -0
  92. data/lib/concurrent/synchronization/rbx_object.rb +30 -73
  93. data/lib/concurrent/synchronization/volatile.rb +34 -0
  94. data/lib/concurrent/thread_safe/synchronized_delegator.rb +50 -0
  95. data/lib/concurrent/thread_safe/util.rb +14 -0
  96. data/lib/concurrent/thread_safe/util/adder.rb +74 -0
  97. data/lib/concurrent/thread_safe/util/array_hash_rbx.rb +30 -0
  98. data/lib/concurrent/thread_safe/util/cheap_lockable.rb +118 -0
  99. data/lib/concurrent/thread_safe/util/power_of_two_tuple.rb +38 -0
  100. data/lib/concurrent/thread_safe/util/striped64.rb +241 -0
  101. data/lib/concurrent/thread_safe/util/volatile.rb +75 -0
  102. data/lib/concurrent/thread_safe/util/xor_shift_random.rb +50 -0
  103. data/lib/concurrent/timer_task.rb +3 -4
  104. data/lib/concurrent/tuple.rb +86 -0
  105. data/lib/concurrent/tvar.rb +5 -1
  106. data/lib/concurrent/utility/at_exit.rb +1 -1
  107. data/lib/concurrent/utility/engine.rb +4 -0
  108. data/lib/concurrent/utility/monotonic_time.rb +3 -4
  109. data/lib/concurrent/utility/native_extension_loader.rb +50 -30
  110. data/lib/concurrent/version.rb +2 -2
  111. data/lib/concurrent_ruby_ext.jar +0 -0
  112. metadata +47 -12
  113. data/lib/concurrent/atomic/condition.rb +0 -78
  114. data/lib/concurrent/collection/priority_queue.rb +0 -360
  115. data/lib/concurrent/synchronization/java_object.rb +0 -34
  116. data/lib/concurrent/synchronization/monitor_object.rb +0 -27
  117. data/lib/concurrent/synchronization/mutex_object.rb +0 -43
  118. data/lib/concurrent/utilities.rb +0 -5
  119. data/lib/concurrent/utility/timeout.rb +0 -39
  120. data/lib/concurrent/utility/timer.rb +0 -26
  121. data/lib/concurrent_ruby.rb +0 -2
@@ -99,13 +99,15 @@ module Concurrent
99
99
  # @!visibility private
100
100
  WRITE_LOCK_MASK = MAX_WRITERS
101
101
 
102
+ safe_initialization!
103
+
102
104
  # Create a new `ReentrantReadWriteLock` in the unlocked state.
103
105
  def initialize
106
+ super()
104
107
  @Counter = AtomicFixnum.new(0) # single integer which represents lock state
105
108
  @ReadQueue = Synchronization::Lock.new # used to queue waiting readers
106
109
  @WriteQueue = Synchronization::Lock.new # used to queue waiting writers
107
110
  @HeldCount = ThreadLocalVar.new(0) # indicates # of R & W locks held by this thread
108
- ensure_ivar_visibility!
109
111
  end
110
112
 
111
113
  # Execute a block operation within a read lock.
@@ -0,0 +1,172 @@
1
+ require 'thread'
2
+ require 'concurrent/atomic/abstract_thread_local_var'
3
+
4
+ module Concurrent
5
+
6
+ # @!visibility private
7
+ # @!macro internal_implementation_note
8
+ class RubyThreadLocalVar < AbstractThreadLocalVar
9
+
10
+ # Each thread has a (lazily initialized) array of thread-local variable values
11
+ # Each time a new thread-local var is created, we allocate an "index" for it
12
+ # For example, if the allocated index is 1, that means slot #1 in EVERY
13
+ # thread's thread-local array will be used for the value of that TLV
14
+ #
15
+ # The good thing about using a per-THREAD structure to hold values, rather
16
+ # than a per-TLV structure, is that no synchronization is needed when
17
+ # reading and writing those values (since the structure is only ever
18
+ # accessed by a single thread)
19
+ #
20
+ # Of course, when a TLV is GC'd, 1) we need to recover its index for use
21
+ # by other new TLVs (otherwise the thread-local arrays could get bigger
22
+ # and bigger with time), and 2) we need to null out all the references
23
+ # held in the now-unused slots (both to avoid blocking GC of those objects,
24
+ # and also to prevent "stale" values from being passed on to a new TLV
25
+ # when the index is reused)
26
+ # Because we need to null out freed slots, we need to keep references to
27
+ # ALL the thread-local arrays -- ARRAYS is for that
28
+ # But when a Thread is GC'd, we need to drop the reference to its thread-local
29
+ # array, so we don't leak memory
30
+
31
+ # @!visibility private
32
+ FREE = []
33
+ LOCK = Mutex.new
34
+ ARRAYS = {} # used as a hash set
35
+ @@next = 0
36
+ private_constant :FREE, :LOCK, :ARRAYS
37
+
38
+ # @!macro [attach] thread_local_var_method_initialize
39
+ #
40
+ # Creates a thread local variable.
41
+ #
42
+ # @param [Object] default the default value when otherwise unset
43
+ def initialize(default = nil)
44
+ @default = default
45
+ allocate_storage
46
+ end
47
+
48
+ # @!macro thread_local_var_method_get
49
+ def value
50
+ if array = get_threadlocal_array
51
+ value = array[@index]
52
+ if value.nil?
53
+ @default
54
+ elsif value.equal?(NULL)
55
+ nil
56
+ else
57
+ value
58
+ end
59
+ else
60
+ @default
61
+ end
62
+ end
63
+
64
+ # @!macro thread_local_var_method_set
65
+ def value=(value)
66
+ me = Thread.current
67
+ # We could keep the thread-local arrays in a hash, keyed by Thread
68
+ # But why? That would require locking
69
+ # Using Ruby's built-in thread-local storage is faster
70
+ unless array = get_threadlocal_array(me)
71
+ array = set_threadlocal_array([], me)
72
+ LOCK.synchronize { ARRAYS[array.object_id] = array }
73
+ ObjectSpace.define_finalizer(me, self.class.thread_finalizer(array))
74
+ end
75
+ array[@index] = (value.nil? ? NULL : value)
76
+ value
77
+ end
78
+
79
+ # @!macro thread_local_var_method_bind
80
+ def bind(value, &block)
81
+ if block_given?
82
+ old_value = self.value
83
+ begin
84
+ self.value = value
85
+ yield
86
+ ensure
87
+ self.value = old_value
88
+ end
89
+ end
90
+ end
91
+
92
+ protected
93
+
94
+ # @!visibility private
95
+ def allocate_storage
96
+ @index = LOCK.synchronize do
97
+ FREE.pop || begin
98
+ result = @@next
99
+ @@next += 1
100
+ result
101
+ end
102
+ end
103
+ ObjectSpace.define_finalizer(self, self.class.threadlocal_finalizer(@index))
104
+ end
105
+
106
+ # @!visibility private
107
+ def self.threadlocal_finalizer(index)
108
+ proc do
109
+ LOCK.synchronize do
110
+ FREE.push(index)
111
+ # The cost of GC'ing a TLV is linear in the number of threads using TLVs
112
+ # But that is natural! More threads means more storage is used per TLV
113
+ # So naturally more CPU time is required to free more storage
114
+ ARRAYS.each_value do |array|
115
+ array[index] = nil
116
+ end
117
+ end
118
+ end
119
+ end
120
+
121
+ # @!visibility private
122
+ def self.thread_finalizer(array)
123
+ proc do
124
+ LOCK.synchronize do
125
+ # The thread which used this thread-local array is now gone
126
+ # So don't hold onto a reference to the array (thus blocking GC)
127
+ ARRAYS.delete(array.object_id)
128
+ end
129
+ end
130
+ end
131
+
132
+ private
133
+
134
+ if Thread.instance_methods.include?(:thread_variable_get)
135
+
136
+ def get_threadlocal_array(thread = Thread.current)
137
+ thread.thread_variable_get(:__threadlocal_array__)
138
+ end
139
+
140
+ def set_threadlocal_array(array, thread = Thread.current)
141
+ thread.thread_variable_set(:__threadlocal_array__, array)
142
+ end
143
+
144
+ else
145
+
146
+ def get_threadlocal_array(thread = Thread.current)
147
+ thread[:__threadlocal_array__]
148
+ end
149
+
150
+ def set_threadlocal_array(array, thread = Thread.current)
151
+ thread[:__threadlocal_array__] = array
152
+ end
153
+ end
154
+
155
+ # This exists only for use in testing
156
+ # @!visibility private
157
+ def value_for(thread)
158
+ if array = get_threadlocal_array(thread)
159
+ value = array[@index]
160
+ if value.nil?
161
+ @default
162
+ elsif value.equal?(NULL)
163
+ nil
164
+ else
165
+ value
166
+ end
167
+ else
168
+ @default
169
+ end
170
+ end
171
+ end
172
+ end
@@ -1,207 +1,113 @@
1
+ require 'concurrent/atomic/mutex_semaphore'
1
2
  require 'concurrent/synchronization'
2
3
 
3
4
  module Concurrent
4
5
 
5
- # @!macro [attach] semaphore
6
+ ###################################################################
7
+
8
+ # @!macro [new] semaphore_method_initialize
6
9
  #
7
- # A counting semaphore. Conceptually, a semaphore maintains a set of
8
- # permits. Each {#acquire} blocks if necessary until a permit is
9
- # available, and then takes it. Each {#release} adds a permit, potentially
10
- # releasing a blocking acquirer.
11
- # However, no actual permit objects are used; the Semaphore just keeps a
12
- # count of the number available and acts accordingly.
10
+ # Create a new `Semaphore` with the initial `count`.
13
11
  #
14
- # @!visibility private
12
+ # @param [Fixnum] count the initial count
15
13
  #
16
- # @!macro internal_implementation_note
17
- class MutexSemaphore < Synchronization::Object
18
-
19
- # @!macro [attach] semaphore_method_initialize
20
- #
21
- # Create a new `Semaphore` with the initial `count`.
22
- #
23
- # @param [Fixnum] count the initial count
24
- #
25
- # @raise [ArgumentError] if `count` is not an integer or is less than zero
26
- def initialize(count)
27
- unless count.is_a?(Fixnum) && count >= 0
28
- fail ArgumentError, 'count must be an non-negative integer'
29
- end
30
- super()
31
- synchronize { ns_initialize count }
32
- end
33
-
34
- # @!macro [attach] semaphore_method_acquire
35
- #
36
- # Acquires the given number of permits from this semaphore,
37
- # blocking until all are available.
38
- #
39
- # @param [Fixnum] permits Number of permits to acquire
40
- #
41
- # @raise [ArgumentError] if `permits` is not an integer or is less than
42
- # one
43
- #
44
- # @return [Nil]
45
- def acquire(permits = 1)
46
- unless permits.is_a?(Fixnum) && permits > 0
47
- fail ArgumentError, 'permits must be an integer greater than zero'
48
- end
49
- synchronize do
50
- try_acquire_timed(permits, nil)
51
- nil
52
- end
53
- end
54
-
55
- # @!macro [attach] semaphore_method_available_permits
56
- #
57
- # Returns the current number of permits available in this semaphore.
58
- #
59
- # @return [Integer]
60
- def available_permits
61
- synchronize { @free }
62
- end
63
-
64
- # @!macro [attach] semaphore_method_drain_permits
65
- #
66
- # Acquires and returns all permits that are immediately available.
67
- #
68
- # @return [Integer]
69
- def drain_permits
70
- synchronize do
71
- @free.tap { |_| @free = 0 }
72
- end
73
- end
14
+ # @raise [ArgumentError] if `count` is not an integer or is less than zero
74
15
 
75
- # @!macro [attach] semaphore_method_try_acquire
76
- #
77
- # Acquires the given number of permits from this semaphore,
78
- # only if all are available at the time of invocation or within
79
- # `timeout` interval
80
- #
81
- # @param [Fixnum] permits the number of permits to acquire
82
- #
83
- # @param [Fixnum] timeout the number of seconds to wait for the counter
84
- # or `nil` to return immediately
85
- #
86
- # @raise [ArgumentError] if `permits` is not an integer or is less than
87
- # one
88
- #
89
- # @return [Boolean] `false` if no permits are available, `true` when
90
- # acquired a permit
91
- def try_acquire(permits = 1, timeout = nil)
92
- unless permits.is_a?(Fixnum) && permits > 0
93
- fail ArgumentError, 'permits must be an integer greater than zero'
94
- end
95
- synchronize do
96
- if timeout.nil?
97
- try_acquire_now(permits)
98
- else
99
- try_acquire_timed(permits, timeout)
100
- end
101
- end
102
- end
16
+ # @!macro [new] semaphore_method_acquire
17
+ #
18
+ # Acquires the given number of permits from this semaphore,
19
+ # blocking until all are available.
20
+ #
21
+ # @param [Fixnum] permits Number of permits to acquire
22
+ #
23
+ # @raise [ArgumentError] if `permits` is not an integer or is less than
24
+ # one
25
+ #
26
+ # @return [nil]
103
27
 
104
- # @!macro [attach] semaphore_method_release
105
- #
106
- # Releases the given number of permits, returning them to the semaphore.
107
- #
108
- # @param [Fixnum] permits Number of permits to return to the semaphore.
109
- #
110
- # @raise [ArgumentError] if `permits` is not a number or is less than one
111
- #
112
- # @return [Nil]
113
- def release(permits = 1)
114
- unless permits.is_a?(Fixnum) && permits > 0
115
- fail ArgumentError, 'permits must be an integer greater than zero'
116
- end
117
- synchronize do
118
- @free += permits
119
- permits.times { ns_signal }
120
- end
121
- nil
122
- end
28
+ # @!macro [new] semaphore_method_available_permits
29
+ #
30
+ # Returns the current number of permits available in this semaphore.
31
+ #
32
+ # @return [Integer]
123
33
 
124
- # @!macro [attach] semaphore_method_reduce_permits
125
- #
126
- # @api private
127
- #
128
- # Shrinks the number of available permits by the indicated reduction.
129
- #
130
- # @param [Fixnum] reduction Number of permits to remove.
131
- #
132
- # @raise [ArgumentError] if `reduction` is not an integer or is negative
133
- #
134
- # @raise [ArgumentError] if `@free` - `@reduction` is less than zero
135
- #
136
- # @return [Nil]
137
- def reduce_permits(reduction)
138
- unless reduction.is_a?(Fixnum) && reduction >= 0
139
- fail ArgumentError, 'reduction must be an non-negative integer'
140
- end
141
- synchronize { @free -= reduction }
142
- nil
143
- end
34
+ # @!macro [new] semaphore_method_drain_permits
35
+ #
36
+ # Acquires and returns all permits that are immediately available.
37
+ #
38
+ # @return [Integer]
144
39
 
145
- protected
40
+ # @!macro [new] semaphore_method_try_acquire
41
+ #
42
+ # Acquires the given number of permits from this semaphore,
43
+ # only if all are available at the time of invocation or within
44
+ # `timeout` interval
45
+ #
46
+ # @param [Fixnum] permits the number of permits to acquire
47
+ #
48
+ # @param [Fixnum] timeout the number of seconds to wait for the counter
49
+ # or `nil` to return immediately
50
+ #
51
+ # @raise [ArgumentError] if `permits` is not an integer or is less than
52
+ # one
53
+ #
54
+ # @return [Boolean] `false` if no permits are available, `true` when
55
+ # acquired a permit
146
56
 
147
- # @!visibility private
148
- def ns_initialize(count)
149
- @free = count
150
- end
57
+ # @!macro [new] semaphore_method_release
58
+ #
59
+ # Releases the given number of permits, returning them to the semaphore.
60
+ #
61
+ # @param [Fixnum] permits Number of permits to return to the semaphore.
62
+ #
63
+ # @raise [ArgumentError] if `permits` is not a number or is less than one
64
+ #
65
+ # @return [nil]
151
66
 
152
- private
67
+ ###################################################################
153
68
 
154
- # @!visibility private
155
- def try_acquire_now(permits)
156
- if @free >= permits
157
- @free -= permits
158
- true
159
- else
160
- false
161
- end
162
- end
69
+ # @!macro [new] semaphore_public_api
70
+ #
71
+ # @!method initialize(count)
72
+ # @!macro semaphore_method_initialize
73
+ #
74
+ # @!method acquire(permits = 1)
75
+ # @!macro semaphore_method_acquire
76
+ #
77
+ # @!method available_permits
78
+ # @!macro semaphore_method_available_permits
79
+ #
80
+ # @!method drain_permits
81
+ # @!macro semaphore_method_drain_permits
82
+ #
83
+ # @!method try_acquire(permits = 1, timeout = nil)
84
+ # @!macro semaphore_method_try_acquire
85
+ #
86
+ # @!method release(permits = 1)
87
+ # @!macro semaphore_method_release
163
88
 
164
- # @!visibility private
165
- def try_acquire_timed(permits, timeout)
166
- ns_wait_until(timeout) { try_acquire_now(permits) }
167
- end
168
- end
89
+ ###################################################################
169
90
 
170
91
  # @!visibility private
171
92
  # @!macro internal_implementation_note
172
93
  SemaphoreImplementation = case
173
- when Concurrent.on_jruby?
94
+ when defined?(JavaSemaphore)
174
95
  JavaSemaphore
175
96
  else
176
97
  MutexSemaphore
177
98
  end
178
99
  private_constant :SemaphoreImplementation
179
100
 
180
- # @!macro semaphore
101
+ # @!macro [attach] semaphore
181
102
  #
182
- # @see Concurrent::MutexSemaphore
103
+ # A counting semaphore. Conceptually, a semaphore maintains a set of
104
+ # permits. Each {#acquire} blocks if necessary until a permit is
105
+ # available, and then takes it. Each {#release} adds a permit, potentially
106
+ # releasing a blocking acquirer.
107
+ # However, no actual permit objects are used; the Semaphore just keeps a
108
+ # count of the number available and acts accordingly.
109
+ #
110
+ # @!macro semaphore_public_api
183
111
  class Semaphore < SemaphoreImplementation
184
-
185
- # @!method initialize(count)
186
- # @!macro semaphore_method_initialize
187
-
188
- # @!method acquire(permits = 1)
189
- # @!macro semaphore_method_acquire
190
-
191
- # @!method available_permits
192
- # @!macro semaphore_method_available_permits
193
-
194
- # @!method drain_permits
195
- # @!macro semaphore_method_drain_permits
196
-
197
- # @!method try_acquire(permits = 1, timeout = nil)
198
- # @!macro semaphore_method_try_acquire
199
-
200
- # @!method release(permits = 1)
201
- # @!macro semaphore_method_release
202
-
203
- # @!method reduce_permits(reduction)
204
- # @!macro semaphore_method_reduce_permits
205
-
206
112
  end
207
113
  end