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

Sign up to get free protection for your applications and to get access to all the features.
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