concurrent-ruby 0.6.0.pre.1 → 0.6.0.pre.2

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 (142) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +16 -0
  3. data/lib/concurrent.rb +9 -29
  4. data/lib/concurrent/{actor.rb → actor/actor.rb} +3 -3
  5. data/lib/concurrent/actor/actor_context.rb +77 -0
  6. data/lib/concurrent/actor/actor_ref.rb +67 -0
  7. data/lib/concurrent/{postable.rb → actor/postable.rb} +1 -1
  8. data/lib/concurrent/actor/simple_actor_ref.rb +94 -0
  9. data/lib/concurrent/actors.rb +5 -0
  10. data/lib/concurrent/agent.rb +81 -47
  11. data/lib/concurrent/async.rb +35 -35
  12. data/lib/concurrent/atomic/atomic_boolean.rb +157 -0
  13. data/lib/concurrent/atomic/atomic_fixnum.rb +170 -0
  14. data/lib/concurrent/{condition.rb → atomic/condition.rb} +0 -0
  15. data/lib/concurrent/{copy_on_notify_observer_set.rb → atomic/copy_on_notify_observer_set.rb} +48 -13
  16. data/lib/concurrent/{copy_on_write_observer_set.rb → atomic/copy_on_write_observer_set.rb} +41 -20
  17. data/lib/concurrent/atomic/count_down_latch.rb +116 -0
  18. data/lib/concurrent/atomic/cyclic_barrier.rb +106 -0
  19. data/lib/concurrent/atomic/event.rb +103 -0
  20. data/lib/concurrent/{thread_local_var.rb → atomic/thread_local_var.rb} +0 -0
  21. data/lib/concurrent/atomics.rb +9 -0
  22. data/lib/concurrent/channel/buffered_channel.rb +6 -4
  23. data/lib/concurrent/channel/channel.rb +30 -2
  24. data/lib/concurrent/channel/unbuffered_channel.rb +2 -2
  25. data/lib/concurrent/channel/waitable_list.rb +3 -1
  26. data/lib/concurrent/channels.rb +5 -0
  27. data/lib/concurrent/{channel → collection}/blocking_ring_buffer.rb +16 -5
  28. data/lib/concurrent/collection/priority_queue.rb +305 -0
  29. data/lib/concurrent/{channel → collection}/ring_buffer.rb +6 -1
  30. data/lib/concurrent/collections.rb +3 -0
  31. data/lib/concurrent/configuration.rb +68 -19
  32. data/lib/concurrent/dataflow.rb +9 -9
  33. data/lib/concurrent/delay.rb +21 -13
  34. data/lib/concurrent/dereferenceable.rb +40 -33
  35. data/lib/concurrent/exchanger.rb +3 -0
  36. data/lib/concurrent/{cached_thread_pool.rb → executor/cached_thread_pool.rb} +8 -9
  37. data/lib/concurrent/executor/executor.rb +222 -0
  38. data/lib/concurrent/{fixed_thread_pool.rb → executor/fixed_thread_pool.rb} +6 -7
  39. data/lib/concurrent/{immediate_executor.rb → executor/immediate_executor.rb} +5 -5
  40. data/lib/concurrent/executor/java_cached_thread_pool.rb +31 -0
  41. data/lib/concurrent/{java_fixed_thread_pool.rb → executor/java_fixed_thread_pool.rb} +7 -11
  42. data/lib/concurrent/executor/java_single_thread_executor.rb +21 -0
  43. data/lib/concurrent/{java_thread_pool_executor.rb → executor/java_thread_pool_executor.rb} +66 -77
  44. data/lib/concurrent/executor/one_by_one.rb +65 -0
  45. data/lib/concurrent/{per_thread_executor.rb → executor/per_thread_executor.rb} +4 -4
  46. data/lib/concurrent/executor/ruby_cached_thread_pool.rb +29 -0
  47. data/lib/concurrent/{ruby_fixed_thread_pool.rb → executor/ruby_fixed_thread_pool.rb} +5 -4
  48. data/lib/concurrent/executor/ruby_single_thread_executor.rb +72 -0
  49. data/lib/concurrent/executor/ruby_thread_pool_executor.rb +282 -0
  50. data/lib/concurrent/{ruby_thread_pool_worker.rb → executor/ruby_thread_pool_worker.rb} +6 -6
  51. data/lib/concurrent/{safe_task_executor.rb → executor/safe_task_executor.rb} +20 -13
  52. data/lib/concurrent/executor/single_thread_executor.rb +35 -0
  53. data/lib/concurrent/executor/thread_pool_executor.rb +68 -0
  54. data/lib/concurrent/executor/timer_set.rb +138 -0
  55. data/lib/concurrent/executors.rb +9 -0
  56. data/lib/concurrent/future.rb +39 -40
  57. data/lib/concurrent/ivar.rb +22 -15
  58. data/lib/concurrent/mvar.rb +2 -1
  59. data/lib/concurrent/obligation.rb +9 -3
  60. data/lib/concurrent/observable.rb +33 -0
  61. data/lib/concurrent/options_parser.rb +46 -0
  62. data/lib/concurrent/promise.rb +23 -24
  63. data/lib/concurrent/scheduled_task.rb +21 -45
  64. data/lib/concurrent/timer_task.rb +204 -126
  65. data/lib/concurrent/tvar.rb +1 -1
  66. data/lib/concurrent/utilities.rb +3 -36
  67. data/lib/concurrent/{processor_count.rb → utility/processor_count.rb} +1 -1
  68. data/lib/concurrent/utility/timeout.rb +36 -0
  69. data/lib/concurrent/utility/timer.rb +21 -0
  70. data/lib/concurrent/version.rb +1 -1
  71. data/lib/concurrent_ruby_ext.bundle +0 -0
  72. data/spec/concurrent/{actor_context_spec.rb → actor/actor_context_spec.rb} +0 -8
  73. data/spec/concurrent/{actor_ref_shared.rb → actor/actor_ref_shared.rb} +9 -59
  74. data/spec/concurrent/{actor_spec.rb → actor/actor_spec.rb} +43 -41
  75. data/spec/concurrent/{postable_shared.rb → actor/postable_shared.rb} +0 -0
  76. data/spec/concurrent/actor/simple_actor_ref_spec.rb +135 -0
  77. data/spec/concurrent/agent_spec.rb +160 -71
  78. data/spec/concurrent/atomic/atomic_boolean_spec.rb +172 -0
  79. data/spec/concurrent/atomic/atomic_fixnum_spec.rb +186 -0
  80. data/spec/concurrent/{condition_spec.rb → atomic/condition_spec.rb} +2 -2
  81. data/spec/concurrent/{copy_on_notify_observer_set_spec.rb → atomic/copy_on_notify_observer_set_spec.rb} +0 -0
  82. data/spec/concurrent/{copy_on_write_observer_set_spec.rb → atomic/copy_on_write_observer_set_spec.rb} +0 -0
  83. data/spec/concurrent/atomic/count_down_latch_spec.rb +151 -0
  84. data/spec/concurrent/atomic/cyclic_barrier_spec.rb +248 -0
  85. data/spec/concurrent/{event_spec.rb → atomic/event_spec.rb} +18 -3
  86. data/spec/concurrent/{observer_set_shared.rb → atomic/observer_set_shared.rb} +15 -6
  87. data/spec/concurrent/{thread_local_var_spec.rb → atomic/thread_local_var_spec.rb} +0 -0
  88. data/spec/concurrent/channel/buffered_channel_spec.rb +1 -1
  89. data/spec/concurrent/channel/channel_spec.rb +6 -4
  90. data/spec/concurrent/channel/probe_spec.rb +37 -9
  91. data/spec/concurrent/channel/unbuffered_channel_spec.rb +2 -2
  92. data/spec/concurrent/{channel → collection}/blocking_ring_buffer_spec.rb +0 -0
  93. data/spec/concurrent/collection/priority_queue_spec.rb +317 -0
  94. data/spec/concurrent/{channel → collection}/ring_buffer_spec.rb +0 -0
  95. data/spec/concurrent/configuration_spec.rb +4 -70
  96. data/spec/concurrent/dereferenceable_shared.rb +5 -4
  97. data/spec/concurrent/exchanger_spec.rb +10 -5
  98. data/spec/concurrent/{cached_thread_pool_shared.rb → executor/cached_thread_pool_shared.rb} +15 -37
  99. data/spec/concurrent/{fixed_thread_pool_shared.rb → executor/fixed_thread_pool_shared.rb} +0 -0
  100. data/spec/concurrent/{global_thread_pool_shared.rb → executor/global_thread_pool_shared.rb} +10 -8
  101. data/spec/concurrent/{immediate_executor_spec.rb → executor/immediate_executor_spec.rb} +0 -0
  102. data/spec/concurrent/{java_cached_thread_pool_spec.rb → executor/java_cached_thread_pool_spec.rb} +1 -21
  103. data/spec/concurrent/{java_fixed_thread_pool_spec.rb → executor/java_fixed_thread_pool_spec.rb} +0 -0
  104. data/spec/concurrent/executor/java_single_thread_executor_spec.rb +21 -0
  105. data/spec/concurrent/{java_thread_pool_executor_spec.rb → executor/java_thread_pool_executor_spec.rb} +0 -0
  106. data/spec/concurrent/{per_thread_executor_spec.rb → executor/per_thread_executor_spec.rb} +0 -4
  107. data/spec/concurrent/{ruby_cached_thread_pool_spec.rb → executor/ruby_cached_thread_pool_spec.rb} +1 -1
  108. data/spec/concurrent/{ruby_fixed_thread_pool_spec.rb → executor/ruby_fixed_thread_pool_spec.rb} +0 -0
  109. data/spec/concurrent/executor/ruby_single_thread_executor_spec.rb +18 -0
  110. data/spec/concurrent/{ruby_thread_pool_executor_spec.rb → executor/ruby_thread_pool_executor_spec.rb} +12 -24
  111. data/spec/concurrent/executor/safe_task_executor_spec.rb +103 -0
  112. data/spec/concurrent/{thread_pool_class_cast_spec.rb → executor/thread_pool_class_cast_spec.rb} +12 -0
  113. data/spec/concurrent/{thread_pool_executor_shared.rb → executor/thread_pool_executor_shared.rb} +0 -0
  114. data/spec/concurrent/{thread_pool_shared.rb → executor/thread_pool_shared.rb} +84 -119
  115. data/spec/concurrent/executor/timer_set_spec.rb +183 -0
  116. data/spec/concurrent/future_spec.rb +12 -0
  117. data/spec/concurrent/ivar_spec.rb +11 -1
  118. data/spec/concurrent/observable_shared.rb +173 -0
  119. data/spec/concurrent/observable_spec.rb +51 -0
  120. data/spec/concurrent/options_parser_spec.rb +71 -0
  121. data/spec/concurrent/runnable_shared.rb +6 -0
  122. data/spec/concurrent/scheduled_task_spec.rb +60 -40
  123. data/spec/concurrent/timer_task_spec.rb +130 -144
  124. data/spec/concurrent/{processor_count_spec.rb → utility/processor_count_spec.rb} +0 -0
  125. data/spec/concurrent/{utilities_spec.rb → utility/timeout_spec.rb} +0 -0
  126. data/spec/concurrent/utility/timer_spec.rb +52 -0
  127. metadata +147 -108
  128. data/lib/concurrent/actor_context.rb +0 -31
  129. data/lib/concurrent/actor_ref.rb +0 -39
  130. data/lib/concurrent/atomic.rb +0 -121
  131. data/lib/concurrent/channel/probe.rb +0 -19
  132. data/lib/concurrent/count_down_latch.rb +0 -60
  133. data/lib/concurrent/event.rb +0 -80
  134. data/lib/concurrent/java_cached_thread_pool.rb +0 -45
  135. data/lib/concurrent/ruby_cached_thread_pool.rb +0 -37
  136. data/lib/concurrent/ruby_thread_pool_executor.rb +0 -268
  137. data/lib/concurrent/simple_actor_ref.rb +0 -124
  138. data/lib/concurrent/thread_pool_executor.rb +0 -30
  139. data/spec/concurrent/atomic_spec.rb +0 -201
  140. data/spec/concurrent/count_down_latch_spec.rb +0 -125
  141. data/spec/concurrent/safe_task_executor_spec.rb +0 -58
  142. data/spec/concurrent/simple_actor_ref_spec.rb +0 -219
@@ -2,7 +2,7 @@ require 'thread'
2
2
  require 'concurrent/configuration'
3
3
  require 'concurrent/ivar'
4
4
  require 'concurrent/future'
5
- require 'concurrent/thread_pool_executor'
5
+ require 'concurrent/executor/thread_pool_executor'
6
6
 
7
7
  module Concurrent
8
8
 
@@ -17,20 +17,20 @@ module Concurrent
17
17
  # Stateful, mutable objects must be managed carefully when used asynchronously.
18
18
  # But Ruby is an object-oriented language so designing with objects and classes
19
19
  # plays to Ruby's strengths and is often more natural to many Ruby programmers.
20
- # The +Async+ module is a way to mix simple yet powerful asynchronous capabilities
20
+ # The `Async` module is a way to mix simple yet powerful asynchronous capabilities
21
21
  # into any plain old Ruby object or class. These capabilities provide a reasonable
22
22
  # level of thread safe guarantees when used correctly.
23
23
  #
24
24
  # When this module is mixed into a class or object it provides to new methods:
25
- # +async+ and +await+. These methods are thread safe with respect to the enclosing
25
+ # `async` and `await`. These methods are thread safe with respect to the enclosing
26
26
  # object. The former method allows methods to be called asynchronously by posting
27
27
  # to the global thread pool. The latter allows a method to be called synchronously
28
28
  # on the current thread but does so safely with respect to any pending asynchronous
29
- # method calls. Both methods return an +Obligation+ which can be inspected for
30
- # the result of the method call. Calling a method with +async+ will return a
31
- # +:pending+ +Obligation+ whereas +await+ will return a +:complete+ +Obligation+.
29
+ # method calls. Both methods return an `Obligation` which can be inspected for
30
+ # the result of the method call. Calling a method with `async` will return a
31
+ # `:pending` `Obligation` whereas `await` will return a `:complete` `Obligation`.
32
32
  #
33
- # Very loosely based on the +async+ and +await+ keywords in C#.
33
+ # Very loosely based on the `async` and `await` keywords in C#.
34
34
  #
35
35
  # @example Defining an asynchronous class
36
36
  # class Echo
@@ -64,9 +64,9 @@ module Concurrent
64
64
  # @note Thread safe guarantees can only be made when asynchronous method calls
65
65
  # are not mixed with synchronous method calls. Use only synchronous calls
66
66
  # when the object is used exclusively on a single thread. Use only
67
- # +async+ and +await+ when the object is shared between threads. Once you
68
- # call a method using +async+, you should no longer call any methods
69
- # directly on the object. Use +async+ and +await+ exclusively from then on.
67
+ # `async` and `await` when the object is shared between threads. Once you
68
+ # call a method using `async`, you should no longer call any methods
69
+ # directly on the object. Use `async` and `await` exclusively from then on.
70
70
  # With careful programming it is possible to switch back and forth but it's
71
71
  # also very easy to create race conditions and break your application.
72
72
  # Basically, it's "async all the way down."
@@ -83,14 +83,14 @@ module Concurrent
83
83
  # @param [Symbol] method the method to check the object for
84
84
  # @param [Array] args zero or more arguments for the arity check
85
85
  #
86
- # @raise [NameError] the object does not respond to +method+ method
87
- # @raise [ArgumentError] the given +args+ do not match the arity of +method+
86
+ # @raise [NameError] the object does not respond to `method` method
87
+ # @raise [ArgumentError] the given `args` do not match the arity of `method`
88
88
  #
89
89
  # @note This check is imperfect because of the way Ruby reports the arity of
90
90
  # methods with a variable number of arguments. It is possible to determine
91
91
  # if too few arguments are given but impossible to determine if too many
92
92
  # arguments are given. This check may also fail to recognize dynamic behavior
93
- # of the object, such as methods simulated with +method_missing+.
93
+ # of the object, such as methods simulated with `method_missing`.
94
94
  #
95
95
  # @see http://www.ruby-doc.org/core-2.1.1/Method.html#method-i-arity Method#arity
96
96
  # @see http://ruby-doc.org/core-2.1.0/Object.html#method-i-respond_to-3F Object#respond_to?
@@ -112,8 +112,8 @@ module Concurrent
112
112
  # @!visibility private
113
113
  class AwaitDelegator # :nodoc:
114
114
 
115
- # Create a new delegator object wrapping the given +delegate+ and
116
- # protecting it with the given +mutex+.
115
+ # Create a new delegator object wrapping the given `delegate` and
116
+ # protecting it with the given `mutex`.
117
117
  #
118
118
  # @param [Object] delegate the object to wrap and delegate method calls to
119
119
  # @param [Mutex] mutex the mutex lock to use when delegating method calls
@@ -124,15 +124,15 @@ module Concurrent
124
124
 
125
125
  # Delegates method calls to the wrapped object. For performance,
126
126
  # dynamically defines the given method on the delegator so that
127
- # all future calls to +method+ will not be directed here.
127
+ # all future calls to `method` will not be directed here.
128
128
  #
129
129
  # @param [Symbol] method the method being called
130
130
  # @param [Array] args zero or more arguments to the method
131
131
  #
132
132
  # @return [IVar] the result of the method call
133
133
  #
134
- # @raise [NameError] the object does not respond to +method+ method
135
- # @raise [ArgumentError] the given +args+ do not match the arity of +method+
134
+ # @raise [NameError] the object does not respond to `method` method
135
+ # @raise [ArgumentError] the given `args` do not match the arity of `method`
136
136
  def method_missing(method, *args, &block)
137
137
  super unless @delegate.respond_to?(method)
138
138
  Async::validate_argc(@delegate, method, *args)
@@ -166,8 +166,8 @@ module Concurrent
166
166
  # @!visibility private
167
167
  class AsyncDelegator # :nodoc:
168
168
 
169
- # Create a new delegator object wrapping the given +delegate+ and
170
- # protecting it with the given +mutex+.
169
+ # Create a new delegator object wrapping the given `delegate` and
170
+ # protecting it with the given `mutex`.
171
171
  #
172
172
  # @param [Object] delegate the object to wrap and delegate method calls to
173
173
  # @param [Mutex] mutex the mutex lock to use when delegating method calls
@@ -179,15 +179,15 @@ module Concurrent
179
179
 
180
180
  # Delegates method calls to the wrapped object. For performance,
181
181
  # dynamically defines the given method on the delegator so that
182
- # all future calls to +method+ will not be directed here.
182
+ # all future calls to `method` will not be directed here.
183
183
  #
184
184
  # @param [Symbol] method the method being called
185
185
  # @param [Array] args zero or more arguments to the method
186
186
  #
187
187
  # @return [IVar] the result of the method call
188
188
  #
189
- # @raise [NameError] the object does not respond to +method+ method
190
- # @raise [ArgumentError] the given +args+ do not match the arity of +method+
189
+ # @raise [NameError] the object does not respond to `method` method
190
+ # @raise [ArgumentError] the given `args` do not match the arity of `method`
191
191
  def method_missing(method, *args, &block)
192
192
  super unless @delegate.respond_to?(method)
193
193
  Async::validate_argc(@delegate, method, *args)
@@ -214,20 +214,20 @@ module Concurrent
214
214
 
215
215
  # Causes the chained method call to be performed asynchronously on the
216
216
  # global thread pool. The method called by this method will return a
217
- # +Future+ object in the +:pending+ state and the method call will have
217
+ # `Future` object in the `:pending` state and the method call will have
218
218
  # been scheduled on the global thread pool. The final disposition of the
219
- # method call can be obtained by inspecting the returned +Future+.
219
+ # method call can be obtained by inspecting the returned `Future`.
220
220
  #
221
221
  # Before scheduling the method on the global thread pool a best-effort
222
222
  # attempt will be made to validate that the method exists on the object
223
223
  # and that the given arguments match the arity of the requested function.
224
224
  # Due to the dynamic nature of Ruby and limitations of its reflection
225
225
  # library, some edge cases will be missed. For more information see
226
- # the documentation for the +validate_argc+ method.
226
+ # the documentation for the `validate_argc` method.
227
227
  #
228
228
  # @note The method call is guaranteed to be thread safe with respect to
229
229
  # all other method calls against the same object that are called with
230
- # either +async+ or +await+. The mutable nature of Ruby references
230
+ # either `async` or `await`. The mutable nature of Ruby references
231
231
  # (and object orientation in general) prevent any other thread safety
232
232
  # guarantees. Do NOT mix non-protected method calls with protected
233
233
  # method call. Use ONLY protected method calls when sharing the object
@@ -235,8 +235,8 @@ module Concurrent
235
235
  #
236
236
  # @return [Concurrent::Future] the pending result of the asynchronous operation
237
237
  #
238
- # @raise [NameError] the object does not respond to +method+ method
239
- # @raise [ArgumentError] the given +args+ do not match the arity of +method+
238
+ # @raise [NameError] the object does not respond to `method` method
239
+ # @raise [ArgumentError] the given `args` do not match the arity of `method`
240
240
  #
241
241
  # @see Concurrent::Future
242
242
  def async
@@ -246,20 +246,20 @@ module Concurrent
246
246
 
247
247
  # Causes the chained method call to be performed synchronously on the
248
248
  # current thread. The method called by this method will return an
249
- # +IVar+ object in either the +:fulfilled+ or +rejected+ state and the
249
+ # `IVar` object in either the `:fulfilled` or `rejected` state and the
250
250
  # method call will have completed. The final disposition of the
251
- # method call can be obtained by inspecting the returned +IVar+.
251
+ # method call can be obtained by inspecting the returned `IVar`.
252
252
  #
253
253
  # Before scheduling the method on the global thread pool a best-effort
254
254
  # attempt will be made to validate that the method exists on the object
255
255
  # and that the given arguments match the arity of the requested function.
256
256
  # Due to the dynamic nature of Ruby and limitations of its reflection
257
257
  # library, some edge cases will be missed. For more information see
258
- # the documentation for the +validate_argc+ method.
258
+ # the documentation for the `validate_argc` method.
259
259
  #
260
260
  # @note The method call is guaranteed to be thread safe with respect to
261
261
  # all other method calls against the same object that are called with
262
- # either +async+ or +await+. The mutable nature of Ruby references
262
+ # either `async` or `await`. The mutable nature of Ruby references
263
263
  # (and object orientation in general) prevent any other thread safety
264
264
  # guarantees. Do NOT mix non-protected method calls with protected
265
265
  # method call. Use ONLY protected method calls when sharing the object
@@ -267,8 +267,8 @@ module Concurrent
267
267
  #
268
268
  # @return [Concurrent::IVar] the completed result of the synchronous operation
269
269
  #
270
- # @raise [NameError] the object does not respond to +method+ method
271
- # @raise [ArgumentError] the given +args+ do not match the arity of +method+
270
+ # @raise [NameError] the object does not respond to `method` method
271
+ # @raise [ArgumentError] the given `args` do not match the arity of `method`
272
272
  #
273
273
  # @see Concurrent::IVar
274
274
  def await
@@ -0,0 +1,157 @@
1
+ module Concurrent
2
+
3
+ # @!macro [attach] atomic_boolean
4
+ #
5
+ # A boolean value that can be updated atomically. Reads and writes to an atomic
6
+ # boolean and thread-safe and guaranteed to succeed. Reads and writes may block
7
+ # briefly but no explicit locking is required.
8
+ #
9
+ # @since 0.6.0
10
+ # @see http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/atomic/AtomicBoolean.html java.util.concurrent.atomic.AtomicBoolean
11
+ class MutexAtomicBoolean
12
+
13
+ # @!macro [attach] atomic_boolean_method_initialize
14
+ #
15
+ # Creates a new `AtomicBoolean` with the given initial value.
16
+ #
17
+ # @param [Boolean] init the initial value
18
+ def initialize(initial = false)
19
+ @value = !!initial
20
+ @mutex = Mutex.new
21
+ end
22
+
23
+ # @!macro [attach] atomic_boolean_method_value
24
+ #
25
+ # Retrieves the current `Boolean` value.
26
+ #
27
+ # @return [Boolean] the current value
28
+ def value
29
+ @mutex.lock
30
+ result = @value
31
+ @mutex.unlock
32
+ result
33
+ end
34
+
35
+ # @!macro [attach] atomic_boolean_method_value_eq
36
+ #
37
+ # Explicitly sets the value.
38
+ #
39
+ # @param [Boolean] value the new value to be set
40
+ #
41
+ # @return [Boolean] the current value
42
+ def value=(value)
43
+ @mutex.lock
44
+ @value = !!value
45
+ result = @value
46
+ @mutex.unlock
47
+ result
48
+ end
49
+
50
+ # @!macro [attach] atomic_boolean_method_is_true
51
+ #
52
+ # Is the current value `true`?
53
+ #
54
+ # @return [Boolean] true if the current value is `true`, else false
55
+ def true?
56
+ @mutex.lock
57
+ result = @value
58
+ @mutex.unlock
59
+ result
60
+ end
61
+
62
+ # @!macro [attach] atomic_boolean_method_is_false
63
+ #
64
+ # Is the current value `true`?false
65
+ #
66
+ # @return [Boolean] true if the current value is `false`, else false
67
+ def false?
68
+ @mutex.lock
69
+ result = !@value
70
+ @mutex.unlock
71
+ result
72
+ end
73
+
74
+ # @!macro [attach] atomic_boolean_method_make_true
75
+ #
76
+ # Explicitly sets the value to true.
77
+ #
78
+ # @return [Boolean] true is value has changed, otherwise false
79
+ def make_true
80
+ @mutex.lock
81
+ old = @value
82
+ @value = true
83
+ @mutex.unlock
84
+
85
+ !old
86
+ end
87
+
88
+ # @!macro [attach] atomic_boolean_method_make_false
89
+ #
90
+ # Explicitly sets the value to false.
91
+ #
92
+ # @return [Boolean] true is value has changed, otherwise false
93
+ def make_false
94
+ @mutex.lock
95
+ old = @value
96
+ @value = false
97
+ @mutex.unlock
98
+
99
+ old
100
+ end
101
+ end
102
+
103
+ if RUBY_PLATFORM == 'java'
104
+
105
+ # @!macro atomic_boolean
106
+ class JavaAtomicBoolean
107
+
108
+ # @!macro atomic_boolean_method_initialize
109
+ #
110
+ def initialize(initial = false)
111
+ @atomic = java.util.concurrent.atomic.AtomicBoolean.new(!!initial)
112
+ end
113
+
114
+ # @!macro atomic_boolean_method_value
115
+ #
116
+ def value
117
+ @atomic.get
118
+ end
119
+
120
+ # @!macro atomic_boolean_method_value_eq
121
+ #
122
+ def value=(value)
123
+ @atomic.set(!!value)
124
+ end
125
+
126
+ # @!macro [attach] atomic_boolean_method_is_true
127
+ def true?
128
+ @atomic.get
129
+ end
130
+
131
+ # @!macro [attach] atomic_boolean_method_is_false
132
+ def false?
133
+ !@atomic.get
134
+ end
135
+
136
+ # @!macro atomic_boolean_method_make_true
137
+ def make_true
138
+ @atomic.compareAndSet(false, true)
139
+ end
140
+
141
+ # @!macro atomic_boolean_method_make_false
142
+ def make_false
143
+ @atomic.compareAndSet(true, false)
144
+ end
145
+ end
146
+
147
+ # @!macro atomic_boolean
148
+ class AtomicBoolean < JavaAtomicBoolean
149
+ end
150
+
151
+ else
152
+
153
+ # @!macro atomic_boolean
154
+ class AtomicBoolean < MutexAtomicBoolean
155
+ end
156
+ end
157
+ end
@@ -0,0 +1,170 @@
1
+ module Concurrent
2
+
3
+ # @!macro [attach] atomic_fixnum
4
+ #
5
+ # A numeric value that can be updated atomically. Reads and writes to an atomic
6
+ # fixnum and thread-safe and guaranteed to succeed. Reads and writes may block
7
+ # briefly but no explicit locking is required.
8
+ #
9
+ # @since 0.5.0
10
+ # @see http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/atomic/AtomicLong.html java.util.concurrent.atomic.AtomicLong
11
+ class MutexAtomicFixnum
12
+
13
+ # @!macro [attach] atomic_fixnum_method_initialize
14
+ #
15
+ # Creates a new `AtomicFixnum` with the given initial value.
16
+ #
17
+ # @param [Fixnum] init the initial value
18
+ # @raise [ArgumentError] if the initial value is not a `Fixnum`
19
+ def initialize(init = 0)
20
+ raise ArgumentError.new('initial value must be a Fixnum') unless init.is_a?(Fixnum)
21
+ @value = init
22
+ @mutex = Mutex.new
23
+ end
24
+
25
+ # @!macro [attach] atomic_fixnum_method_value
26
+ #
27
+ # Retrieves the current `Fixnum` value.
28
+ #
29
+ # @return [Fixnum] the current value
30
+ def value
31
+ @mutex.lock
32
+ result = @value
33
+ @mutex.unlock
34
+
35
+ result
36
+ end
37
+
38
+ # @!macro [attach] atomic_fixnum_method_value_eq
39
+ #
40
+ # Explicitly sets the value.
41
+ #
42
+ # @param [Fixnum] value the new value to be set
43
+ #
44
+ # @return [Fixnum] the current value
45
+ #
46
+ # @raise [ArgumentError] if the new value is not a `Fixnum`
47
+ def value=(value)
48
+ raise ArgumentError.new('value must be a Fixnum') unless value.is_a?(Fixnum)
49
+ @mutex.lock
50
+ result = @value = value
51
+ @mutex.unlock
52
+
53
+ result
54
+ end
55
+
56
+ # @!macro [attach] atomic_fixnum_method_increment
57
+ #
58
+ # Increases the current value by 1.
59
+ #
60
+ # @return [Fixnum] the current value after incrementation
61
+ def increment
62
+ @mutex.lock
63
+ @value += 1
64
+ result = @value
65
+ @mutex.unlock
66
+
67
+ result
68
+ end
69
+
70
+ alias_method :up, :increment
71
+
72
+ # @!macro [attach] atomic_fixnum_method_decrement
73
+ #
74
+ # Decreases the current value by 1.
75
+ #
76
+ # @return [Fixnum] the current value after decrementation
77
+ def decrement
78
+ @mutex.lock
79
+ @value -= 1
80
+ result = @value
81
+ @mutex.unlock
82
+
83
+ result
84
+ end
85
+
86
+ alias_method :down, :decrement
87
+
88
+ # @!macro [attach] atomic_fixnum_method_compare_and_set
89
+ #
90
+ # Atomically sets the value to the given updated value if the current
91
+ # value == the expected value.
92
+ #
93
+ # @param [Fixnum] expect the expected value
94
+ # @param [Fixnum] update the new value
95
+ #
96
+ # @return [Boolean] true if the value was updated else false
97
+ def compare_and_set(expect, update)
98
+
99
+ @mutex.lock
100
+ if @value == expect
101
+ @value = update
102
+ result = true
103
+ else
104
+ result = false
105
+ end
106
+ @mutex.unlock
107
+
108
+ result
109
+ end
110
+ end
111
+
112
+ if RUBY_PLATFORM == 'java'
113
+
114
+ # @!macro atomic_fixnum
115
+ class JavaAtomicFixnum
116
+
117
+ # @!macro atomic_fixnum_method_initialize
118
+ #
119
+ def initialize(init = 0)
120
+ raise ArgumentError.new('initial value must be a Fixnum') unless init.is_a?(Fixnum)
121
+ @atomic = java.util.concurrent.atomic.AtomicLong.new(init)
122
+ end
123
+
124
+ # @!macro atomic_fixnum_method_value
125
+ #
126
+ def value
127
+ @atomic.get
128
+ end
129
+
130
+ # @!macro atomic_fixnum_method_value_eq
131
+ #
132
+ def value=(value)
133
+ raise ArgumentError.new('value must be a Fixnum') unless value.is_a?(Fixnum)
134
+ @atomic.set(value)
135
+ end
136
+
137
+ # @!macro atomic_fixnum_method_increment
138
+ #
139
+ def increment
140
+ @atomic.increment_and_get
141
+ end
142
+
143
+ alias_method :up, :increment
144
+
145
+ # @!macro atomic_fixnum_method_decrement
146
+ #
147
+ def decrement
148
+ @atomic.decrement_and_get
149
+ end
150
+
151
+ alias_method :down, :decrement
152
+
153
+ # @!macro atomic_fixnum_method_compare_and_set
154
+ #
155
+ def compare_and_set(expect, update)
156
+ @atomic.compare_and_set(expect, update)
157
+ end
158
+ end
159
+
160
+ # @!macro atomic_fixnum
161
+ class AtomicFixnum < JavaAtomicFixnum
162
+ end
163
+
164
+ else
165
+
166
+ # @!macro atomic_fixnum
167
+ class AtomicFixnum < MutexAtomicFixnum
168
+ end
169
+ end
170
+ end