concurrent-ruby 1.0.5 → 1.1.6

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 (161) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +115 -0
  3. data/Gemfile +42 -0
  4. data/{LICENSE.txt → LICENSE.md} +2 -0
  5. data/README.md +242 -105
  6. data/Rakefile +332 -0
  7. data/ext/concurrent-ruby/ConcurrentRubyService.java +17 -0
  8. data/ext/concurrent-ruby/com/concurrent_ruby/ext/AtomicReferenceLibrary.java +175 -0
  9. data/ext/concurrent-ruby/com/concurrent_ruby/ext/JRubyMapBackendLibrary.java +248 -0
  10. data/ext/concurrent-ruby/com/concurrent_ruby/ext/JavaAtomicBooleanLibrary.java +93 -0
  11. data/ext/concurrent-ruby/com/concurrent_ruby/ext/JavaAtomicFixnumLibrary.java +113 -0
  12. data/ext/concurrent-ruby/com/concurrent_ruby/ext/JavaSemaphoreLibrary.java +159 -0
  13. data/ext/concurrent-ruby/com/concurrent_ruby/ext/SynchronizationLibrary.java +307 -0
  14. data/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166e/ConcurrentHashMap.java +31 -0
  15. data/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166e/ConcurrentHashMapV8.java +3863 -0
  16. data/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166e/LongAdder.java +203 -0
  17. data/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166e/Striped64.java +342 -0
  18. data/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166e/nounsafe/ConcurrentHashMapV8.java +3800 -0
  19. data/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166e/nounsafe/LongAdder.java +204 -0
  20. data/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166e/nounsafe/Striped64.java +291 -0
  21. data/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166y/ThreadLocalRandom.java +199 -0
  22. data/lib/concurrent-ruby/concurrent-ruby.rb +1 -0
  23. data/lib/{concurrent.rb → concurrent-ruby/concurrent.rb} +24 -20
  24. data/lib/{concurrent → concurrent-ruby/concurrent}/agent.rb +7 -7
  25. data/lib/concurrent-ruby/concurrent/array.rb +66 -0
  26. data/lib/{concurrent → concurrent-ruby/concurrent}/async.rb +18 -4
  27. data/lib/{concurrent → concurrent-ruby/concurrent}/atom.rb +10 -10
  28. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/abstract_thread_local_var.rb +0 -0
  29. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/atomic_boolean.rb +26 -22
  30. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/atomic_fixnum.rb +27 -23
  31. data/lib/concurrent-ruby/concurrent/atomic/atomic_markable_reference.rb +164 -0
  32. data/lib/concurrent-ruby/concurrent/atomic/atomic_reference.rb +204 -0
  33. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/count_down_latch.rb +7 -7
  34. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/cyclic_barrier.rb +1 -1
  35. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/event.rb +1 -1
  36. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/java_count_down_latch.rb +9 -6
  37. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/java_thread_local_var.rb +0 -0
  38. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/mutex_atomic_boolean.rb +2 -0
  39. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/mutex_atomic_fixnum.rb +0 -0
  40. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/mutex_count_down_latch.rb +1 -0
  41. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/mutex_semaphore.rb +0 -0
  42. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/read_write_lock.rb +2 -1
  43. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/reentrant_read_write_lock.rb +3 -1
  44. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/ruby_thread_local_var.rb +43 -33
  45. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/semaphore.rb +8 -8
  46. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/thread_local_var.rb +8 -8
  47. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic_reference/mutex_atomic.rb +3 -8
  48. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic_reference/numeric_cas_wrapper.rb +1 -1
  49. data/lib/concurrent-ruby/concurrent/atomics.rb +10 -0
  50. data/lib/{concurrent → concurrent-ruby/concurrent}/collection/copy_on_notify_observer_set.rb +0 -0
  51. data/lib/{concurrent → concurrent-ruby/concurrent}/collection/copy_on_write_observer_set.rb +0 -0
  52. data/lib/{concurrent → concurrent-ruby/concurrent}/collection/java_non_concurrent_priority_queue.rb +0 -0
  53. data/lib/concurrent-ruby/concurrent/collection/lock_free_stack.rb +158 -0
  54. data/lib/{concurrent → concurrent-ruby/concurrent}/collection/map/atomic_reference_map_backend.rb +3 -3
  55. data/lib/{concurrent → concurrent-ruby/concurrent}/collection/map/mri_map_backend.rb +0 -0
  56. data/lib/{concurrent → concurrent-ruby/concurrent}/collection/map/non_concurrent_map_backend.rb +1 -2
  57. data/lib/{concurrent → concurrent-ruby/concurrent}/collection/map/synchronized_map_backend.rb +0 -0
  58. data/lib/{concurrent → concurrent-ruby/concurrent}/collection/non_concurrent_priority_queue.rb +30 -30
  59. data/lib/{concurrent → concurrent-ruby/concurrent}/collection/ruby_non_concurrent_priority_queue.rb +0 -0
  60. data/lib/{concurrent → concurrent-ruby/concurrent}/concern/deprecation.rb +0 -0
  61. data/lib/{concurrent → concurrent-ruby/concurrent}/concern/dereferenceable.rb +3 -3
  62. data/lib/{concurrent → concurrent-ruby/concurrent}/concern/logging.rb +6 -1
  63. data/lib/{concurrent → concurrent-ruby/concurrent}/concern/obligation.rb +0 -0
  64. data/lib/{concurrent → concurrent-ruby/concurrent}/concern/observable.rb +7 -7
  65. data/lib/concurrent-ruby/concurrent/concurrent_ruby.jar +0 -0
  66. data/lib/{concurrent → concurrent-ruby/concurrent}/configuration.rb +15 -15
  67. data/lib/{concurrent → concurrent-ruby/concurrent}/constants.rb +1 -1
  68. data/lib/{concurrent → concurrent-ruby/concurrent}/dataflow.rb +2 -1
  69. data/lib/{concurrent → concurrent-ruby/concurrent}/delay.rb +9 -7
  70. data/lib/{concurrent → concurrent-ruby/concurrent}/errors.rb +0 -0
  71. data/lib/{concurrent → concurrent-ruby/concurrent}/exchanger.rb +21 -25
  72. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/abstract_executor_service.rb +19 -25
  73. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/cached_thread_pool.rb +5 -5
  74. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/executor_service.rb +17 -17
  75. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/fixed_thread_pool.rb +27 -30
  76. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/immediate_executor.rb +0 -0
  77. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/indirect_immediate_executor.rb +0 -0
  78. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/java_executor_service.rb +19 -16
  79. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/java_single_thread_executor.rb +4 -3
  80. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/java_thread_pool_executor.rb +12 -8
  81. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/ruby_executor_service.rb +0 -2
  82. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/ruby_single_thread_executor.rb +0 -1
  83. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/ruby_thread_pool_executor.rb +9 -4
  84. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/safe_task_executor.rb +0 -0
  85. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/serial_executor_service.rb +0 -0
  86. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/serialized_execution.rb +0 -0
  87. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/serialized_execution_delegator.rb +0 -0
  88. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/simple_executor_service.rb +1 -1
  89. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/single_thread_executor.rb +3 -2
  90. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/thread_pool_executor.rb +6 -6
  91. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/timer_set.rb +14 -17
  92. data/lib/{concurrent → concurrent-ruby/concurrent}/executors.rb +0 -0
  93. data/lib/{concurrent → concurrent-ruby/concurrent}/future.rb +4 -1
  94. data/lib/concurrent-ruby/concurrent/hash.rb +59 -0
  95. data/lib/{concurrent → concurrent-ruby/concurrent}/immutable_struct.rb +8 -0
  96. data/lib/{concurrent → concurrent-ruby/concurrent}/ivar.rb +5 -6
  97. data/lib/concurrent-ruby/concurrent/map.rb +337 -0
  98. data/lib/{concurrent → concurrent-ruby/concurrent}/maybe.rb +1 -1
  99. data/lib/{concurrent → concurrent-ruby/concurrent}/mutable_struct.rb +25 -14
  100. data/lib/{concurrent → concurrent-ruby/concurrent}/mvar.rb +2 -2
  101. data/lib/{concurrent → concurrent-ruby/concurrent}/options.rb +0 -0
  102. data/lib/{concurrent → concurrent-ruby/concurrent}/promise.rb +53 -21
  103. data/lib/concurrent-ruby/concurrent/promises.rb +2167 -0
  104. data/lib/concurrent-ruby/concurrent/re_include.rb +58 -0
  105. data/lib/{concurrent → concurrent-ruby/concurrent}/scheduled_task.rb +0 -0
  106. data/lib/concurrent-ruby/concurrent/set.rb +66 -0
  107. data/lib/{concurrent → concurrent-ruby/concurrent}/settable_struct.rb +11 -0
  108. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization.rb +4 -5
  109. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/abstract_lockable_object.rb +5 -5
  110. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/abstract_object.rb +0 -0
  111. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/abstract_struct.rb +18 -4
  112. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/condition.rb +2 -0
  113. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/jruby_lockable_object.rb +0 -0
  114. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/jruby_object.rb +1 -0
  115. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/lock.rb +2 -0
  116. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/lockable_object.rb +6 -6
  117. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/mri_object.rb +1 -0
  118. data/lib/{concurrent/synchronization/mri_lockable_object.rb → concurrent-ruby/concurrent/synchronization/mutex_lockable_object.rb} +19 -14
  119. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/object.rb +53 -23
  120. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/rbx_lockable_object.rb +0 -0
  121. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/rbx_object.rb +1 -0
  122. data/lib/concurrent-ruby/concurrent/synchronization/truffleruby_object.rb +47 -0
  123. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/volatile.rb +11 -9
  124. data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/synchronized_delegator.rb +0 -0
  125. data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/util.rb +0 -0
  126. data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/util/adder.rb +0 -0
  127. data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/util/cheap_lockable.rb +0 -0
  128. data/lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb +63 -0
  129. data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/util/power_of_two_tuple.rb +0 -0
  130. data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/util/striped64.rb +9 -4
  131. data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/util/volatile.rb +0 -0
  132. data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/util/xor_shift_random.rb +0 -0
  133. data/lib/{concurrent → concurrent-ruby/concurrent}/timer_task.rb +5 -2
  134. data/lib/{concurrent → concurrent-ruby/concurrent}/tuple.rb +1 -1
  135. data/lib/{concurrent → concurrent-ruby/concurrent}/tvar.rb +2 -2
  136. data/lib/{concurrent → concurrent-ruby/concurrent}/utility/engine.rb +4 -4
  137. data/lib/{concurrent → concurrent-ruby/concurrent}/utility/monotonic_time.rb +3 -3
  138. data/lib/concurrent-ruby/concurrent/utility/native_extension_loader.rb +79 -0
  139. data/lib/{concurrent → concurrent-ruby/concurrent}/utility/native_integer.rb +0 -0
  140. data/lib/{concurrent → concurrent-ruby/concurrent}/utility/processor_counter.rb +5 -2
  141. data/lib/concurrent-ruby/concurrent/version.rb +3 -0
  142. metadata +146 -131
  143. data/lib/concurrent/array.rb +0 -39
  144. data/lib/concurrent/atomic/atomic_reference.rb +0 -51
  145. data/lib/concurrent/atomic_reference/concurrent_update_error.rb +0 -8
  146. data/lib/concurrent/atomic_reference/direct_update.rb +0 -81
  147. data/lib/concurrent/atomic_reference/jruby+truffle.rb +0 -2
  148. data/lib/concurrent/atomic_reference/jruby.rb +0 -16
  149. data/lib/concurrent/atomic_reference/rbx.rb +0 -22
  150. data/lib/concurrent/atomic_reference/ruby.rb +0 -32
  151. data/lib/concurrent/atomics.rb +0 -53
  152. data/lib/concurrent/edge.rb +0 -26
  153. data/lib/concurrent/hash.rb +0 -36
  154. data/lib/concurrent/lazy_register.rb +0 -81
  155. data/lib/concurrent/map.rb +0 -240
  156. data/lib/concurrent/synchronization/truffle_lockable_object.rb +0 -9
  157. data/lib/concurrent/synchronization/truffle_object.rb +0 -31
  158. data/lib/concurrent/thread_safe/util/array_hash_rbx.rb +0 -30
  159. data/lib/concurrent/utility/at_exit.rb +0 -97
  160. data/lib/concurrent/utility/native_extension_loader.rb +0 -73
  161. data/lib/concurrent/version.rb +0 -4
@@ -0,0 +1,199 @@
1
+ /*
2
+ * Written by Doug Lea with assistance from members of JCP JSR-166
3
+ * Expert Group and released to the public domain, as explained at
4
+ * http://creativecommons.org/publicdomain/zero/1.0/
5
+ */
6
+
7
+ // This is based on 1.16 version
8
+
9
+ package com.concurrent_ruby.ext.jsr166y;
10
+
11
+ import java.util.Random;
12
+
13
+ /**
14
+ * A random number generator isolated to the current thread. Like the
15
+ * global {@link java.util.Random} generator used by the {@link
16
+ * java.lang.Math} class, a {@code ThreadLocalRandom} is initialized
17
+ * with an internally generated seed that may not otherwise be
18
+ * modified. When applicable, use of {@code ThreadLocalRandom} rather
19
+ * than shared {@code Random} objects in concurrent programs will
20
+ * typically encounter much less overhead and contention. Use of
21
+ * {@code ThreadLocalRandom} is particularly appropriate when multiple
22
+ * tasks (for example, each a {@link ForkJoinTask}) use random numbers
23
+ * in parallel in thread pools.
24
+ *
25
+ * <p>Usages of this class should typically be of the form:
26
+ * {@code ThreadLocalRandom.current().nextX(...)} (where
27
+ * {@code X} is {@code Int}, {@code Long}, etc).
28
+ * When all usages are of this form, it is never possible to
29
+ * accidently share a {@code ThreadLocalRandom} across multiple threads.
30
+ *
31
+ * <p>This class also provides additional commonly used bounded random
32
+ * generation methods.
33
+ *
34
+ * @since 1.7
35
+ * @author Doug Lea
36
+ */
37
+ public class ThreadLocalRandom extends Random {
38
+ // same constants as Random, but must be redeclared because private
39
+ private static final long multiplier = 0x5DEECE66DL;
40
+ private static final long addend = 0xBL;
41
+ private static final long mask = (1L << 48) - 1;
42
+
43
+ /**
44
+ * The random seed. We can't use super.seed.
45
+ */
46
+ private long rnd;
47
+
48
+ /**
49
+ * Initialization flag to permit calls to setSeed to succeed only
50
+ * while executing the Random constructor. We can't allow others
51
+ * since it would cause setting seed in one part of a program to
52
+ * unintentionally impact other usages by the thread.
53
+ */
54
+ boolean initialized;
55
+
56
+ // Padding to help avoid memory contention among seed updates in
57
+ // different TLRs in the common case that they are located near
58
+ // each other.
59
+ private long pad0, pad1, pad2, pad3, pad4, pad5, pad6, pad7;
60
+
61
+ /**
62
+ * The actual ThreadLocal
63
+ */
64
+ private static final ThreadLocal<ThreadLocalRandom> localRandom =
65
+ new ThreadLocal<ThreadLocalRandom>() {
66
+ protected ThreadLocalRandom initialValue() {
67
+ return new ThreadLocalRandom();
68
+ }
69
+ };
70
+
71
+
72
+ /**
73
+ * Constructor called only by localRandom.initialValue.
74
+ */
75
+ ThreadLocalRandom() {
76
+ super();
77
+ initialized = true;
78
+ }
79
+
80
+ /**
81
+ * Returns the current thread's {@code ThreadLocalRandom}.
82
+ *
83
+ * @return the current thread's {@code ThreadLocalRandom}
84
+ */
85
+ public static ThreadLocalRandom current() {
86
+ return localRandom.get();
87
+ }
88
+
89
+ /**
90
+ * Throws {@code UnsupportedOperationException}. Setting seeds in
91
+ * this generator is not supported.
92
+ *
93
+ * @throws UnsupportedOperationException always
94
+ */
95
+ public void setSeed(long seed) {
96
+ if (initialized)
97
+ throw new UnsupportedOperationException();
98
+ rnd = (seed ^ multiplier) & mask;
99
+ }
100
+
101
+ protected int next(int bits) {
102
+ rnd = (rnd * multiplier + addend) & mask;
103
+ return (int) (rnd >>> (48-bits));
104
+ }
105
+
106
+ /**
107
+ * Returns a pseudorandom, uniformly distributed value between the
108
+ * given least value (inclusive) and bound (exclusive).
109
+ *
110
+ * @param least the least value returned
111
+ * @param bound the upper bound (exclusive)
112
+ * @throws IllegalArgumentException if least greater than or equal
113
+ * to bound
114
+ * @return the next value
115
+ */
116
+ public int nextInt(int least, int bound) {
117
+ if (least >= bound)
118
+ throw new IllegalArgumentException();
119
+ return nextInt(bound - least) + least;
120
+ }
121
+
122
+ /**
123
+ * Returns a pseudorandom, uniformly distributed value
124
+ * between 0 (inclusive) and the specified value (exclusive).
125
+ *
126
+ * @param n the bound on the random number to be returned. Must be
127
+ * positive.
128
+ * @return the next value
129
+ * @throws IllegalArgumentException if n is not positive
130
+ */
131
+ public long nextLong(long n) {
132
+ if (n <= 0)
133
+ throw new IllegalArgumentException("n must be positive");
134
+ // Divide n by two until small enough for nextInt. On each
135
+ // iteration (at most 31 of them but usually much less),
136
+ // randomly choose both whether to include high bit in result
137
+ // (offset) and whether to continue with the lower vs upper
138
+ // half (which makes a difference only if odd).
139
+ long offset = 0;
140
+ while (n >= Integer.MAX_VALUE) {
141
+ int bits = next(2);
142
+ long half = n >>> 1;
143
+ long nextn = ((bits & 2) == 0) ? half : n - half;
144
+ if ((bits & 1) == 0)
145
+ offset += n - nextn;
146
+ n = nextn;
147
+ }
148
+ return offset + nextInt((int) n);
149
+ }
150
+
151
+ /**
152
+ * Returns a pseudorandom, uniformly distributed value between the
153
+ * given least value (inclusive) and bound (exclusive).
154
+ *
155
+ * @param least the least value returned
156
+ * @param bound the upper bound (exclusive)
157
+ * @return the next value
158
+ * @throws IllegalArgumentException if least greater than or equal
159
+ * to bound
160
+ */
161
+ public long nextLong(long least, long bound) {
162
+ if (least >= bound)
163
+ throw new IllegalArgumentException();
164
+ return nextLong(bound - least) + least;
165
+ }
166
+
167
+ /**
168
+ * Returns a pseudorandom, uniformly distributed {@code double} value
169
+ * between 0 (inclusive) and the specified value (exclusive).
170
+ *
171
+ * @param n the bound on the random number to be returned. Must be
172
+ * positive.
173
+ * @return the next value
174
+ * @throws IllegalArgumentException if n is not positive
175
+ */
176
+ public double nextDouble(double n) {
177
+ if (n <= 0)
178
+ throw new IllegalArgumentException("n must be positive");
179
+ return nextDouble() * n;
180
+ }
181
+
182
+ /**
183
+ * Returns a pseudorandom, uniformly distributed value between the
184
+ * given least value (inclusive) and bound (exclusive).
185
+ *
186
+ * @param least the least value returned
187
+ * @param bound the upper bound (exclusive)
188
+ * @return the next value
189
+ * @throws IllegalArgumentException if least greater than or equal
190
+ * to bound
191
+ */
192
+ public double nextDouble(double least, double bound) {
193
+ if (least >= bound)
194
+ throw new IllegalArgumentException();
195
+ return nextDouble() * (bound - least) + least;
196
+ }
197
+
198
+ private static final long serialVersionUID = -5851777807851030925L;
199
+ }
@@ -0,0 +1 @@
1
+ require_relative "./concurrent"
@@ -7,11 +7,13 @@ require 'concurrent/atomics'
7
7
  require 'concurrent/executors'
8
8
  require 'concurrent/synchronization'
9
9
 
10
+ require 'concurrent/atomic/atomic_markable_reference'
10
11
  require 'concurrent/atomic/atomic_reference'
11
12
  require 'concurrent/agent'
12
13
  require 'concurrent/atom'
13
14
  require 'concurrent/array'
14
15
  require 'concurrent/hash'
16
+ require 'concurrent/set'
15
17
  require 'concurrent/map'
16
18
  require 'concurrent/tuple'
17
19
  require 'concurrent/async'
@@ -29,20 +31,21 @@ require 'concurrent/scheduled_task'
29
31
  require 'concurrent/settable_struct'
30
32
  require 'concurrent/timer_task'
31
33
  require 'concurrent/tvar'
34
+ require 'concurrent/promises'
32
35
 
33
36
  require 'concurrent/thread_safe/synchronized_delegator'
34
37
  require 'concurrent/thread_safe/util'
35
38
 
36
39
  require 'concurrent/options'
37
40
 
38
- # @!macro [new] internal_implementation_note
41
+ # @!macro internal_implementation_note
39
42
  #
40
43
  # @note **Private Implementation:** This abstraction is a private, internal
41
44
  # implementation detail. It should never be used directly.
42
45
 
43
- # @!macro [new] monotonic_clock_warning
46
+ # @!macro monotonic_clock_warning
44
47
  #
45
- # @note Time calculations one all platforms and languages are sensitive to
48
+ # @note Time calculations on all platforms and languages are sensitive to
46
49
  # changes to the system clock. To alleviate the potential problems
47
50
  # associated with changing the system clock while an application is running,
48
51
  # most modern operating systems provide a monotonic clock that operates
@@ -58,7 +61,7 @@ require 'concurrent/options'
58
61
  #
59
62
  # @see http://linux.die.net/man/3/clock_gettime Linux clock_gettime(3)
60
63
 
61
- # @!macro [new] copy_options
64
+ # @!macro copy_options
62
65
  #
63
66
  # ## Copy Options
64
67
  #
@@ -94,7 +97,7 @@ require 'concurrent/options'
94
97
  # as close to the behavior of a "pure" functional language (like Erlang, Clojure,
95
98
  # or Haskell) as we are likely to get in Ruby.
96
99
 
97
- # @!macro [attach] deref_options
100
+ # @!macro deref_options
98
101
  #
99
102
  # @option opts [Boolean] :dup_on_deref (false) Call `#dup` before
100
103
  # returning the data from {#value}
@@ -104,27 +107,28 @@ require 'concurrent/options'
104
107
  # method, call the given proc passing the internal value as the sole
105
108
  # argument then return the new value returned from the proc.
106
109
 
107
- # @!macro [attach] executor_and_deref_options
110
+ # @!macro executor_and_deref_options
108
111
  #
109
112
  # @param [Hash] opts the options used to define the behavior at update and deref
110
113
  # and to specify the executor on which to perform actions
111
114
  # @option opts [Executor] :executor when set use the given `Executor` instance.
112
- # Three special values are also supported: `:task` returns the global task pool,
113
- # `:operation` returns the global operation pool, and `:immediate` returns a new
114
- # `ImmediateExecutor` object.
115
+ # Three special values are also supported: `:io` returns the global pool for
116
+ # long, blocking (IO) tasks, `:fast` returns the global pool for short, fast
117
+ # operations, and `:immediate` returns the global `ImmediateExecutor` object.
115
118
  # @!macro deref_options
116
119
 
117
- # Modern concurrency tools for Ruby. Inspired by Erlang, Clojure, Scala, Haskell,
118
- # F#, C#, Java, and classic concurrency patterns.
120
+ # @!macro warn.edge
121
+ # @api Edge
122
+ # @note **Edge Features** are under active development and may change frequently.
119
123
  #
120
- # The design goals of this gem are:
121
- #
122
- # * Stay true to the spirit of the languages providing inspiration
123
- # * But implement in a way that makes sense for Ruby
124
- # * Keep the semantics as idiomatic Ruby as possible
125
- # * Support features that make sense in Ruby
126
- # * Exclude features that don't make sense in Ruby
127
- # * Be small, lean, and loosely coupled
128
- module Concurrent
124
+ # - Deprecations are not added before incompatible changes.
125
+ # - Edge version: _major_ is always 0, _minor_ bump means incompatible change,
126
+ # _patch_ bump means compatible change.
127
+ # - Edge features may also lack tests and documentation.
128
+ # - Features developed in `concurrent-ruby-edge` are expected to move
129
+ # to `concurrent-ruby` when finalised.
129
130
 
131
+
132
+ # {include:file:README.md}
133
+ module Concurrent
130
134
  end
@@ -129,7 +129,7 @@ module Concurrent
129
129
  # end
130
130
  # ```
131
131
  #
132
- # @!macro [new] agent_await_warning
132
+ # @!macro agent_await_warning
133
133
  #
134
134
  # **NOTE** Never, *under any circumstances*, call any of the "await" methods
135
135
  # ({#await}, {#await_for}, {#await_for!}, and {#wait}) from within an action
@@ -147,7 +147,7 @@ module Concurrent
147
147
  ERROR_MODES = [:continue, :fail].freeze
148
148
  private_constant :ERROR_MODES
149
149
 
150
- AWAIT_FLAG = Object.new
150
+ AWAIT_FLAG = ::Object.new
151
151
  private_constant :AWAIT_FLAG
152
152
 
153
153
  AWAIT_ACTION = ->(value, latch) { latch.count_down; AWAIT_FLAG }
@@ -242,7 +242,7 @@ module Concurrent
242
242
 
243
243
  alias_method :reason, :error
244
244
 
245
- # @!macro [attach] agent_send
245
+ # @!macro agent_send
246
246
  #
247
247
  # Dispatches an action to the Agent and returns immediately. Subsequently,
248
248
  # in a thread from a thread pool, the {#value} will be set to the return
@@ -271,7 +271,7 @@ module Concurrent
271
271
  # action
272
272
  # @yieldreturn [Object] the new value of the Agent
273
273
  #
274
- # @!macro [attach] send_return
274
+ # @!macro send_return
275
275
  # @return [Boolean] true if the action is successfully enqueued, false if
276
276
  # the Agent is {#failed?}
277
277
  def send(*args, &action)
@@ -280,7 +280,7 @@ module Concurrent
280
280
 
281
281
  # @!macro agent_send
282
282
  #
283
- # @!macro [attach] send_bang_return_and_raise
283
+ # @!macro send_bang_return_and_raise
284
284
  # @return [Boolean] true if the action is successfully enqueued
285
285
  # @raise [Concurrent::Agent::Error] if the Agent is {#failed?}
286
286
  def send!(*args, &action)
@@ -326,7 +326,7 @@ module Concurrent
326
326
  #
327
327
  # @param [Proc] action the action dispatch to be enqueued
328
328
  # @return [Concurrent::Agent] self
329
- # @see {#send_off}
329
+ # @see #send_off
330
330
  def <<(action)
331
331
  send_off(&action)
332
332
  self
@@ -397,7 +397,7 @@ module Concurrent
397
397
 
398
398
  # Is the Agent in a failed state?
399
399
  #
400
- # @see {#restart}
400
+ # @see #restart
401
401
  def failed?
402
402
  !@error.value.nil?
403
403
  end
@@ -0,0 +1,66 @@
1
+ require 'concurrent/utility/engine'
2
+ require 'concurrent/thread_safe/util'
3
+
4
+ module Concurrent
5
+
6
+ # @!macro concurrent_array
7
+ #
8
+ # A thread-safe subclass of Array. This version locks against the object
9
+ # itself for every method call, ensuring only one thread can be reading
10
+ # or writing at a time. This includes iteration methods like `#each`.
11
+ #
12
+ # @note `a += b` is **not** a **thread-safe** operation on
13
+ # `Concurrent::Array`. It reads array `a`, then it creates new `Concurrent::Array`
14
+ # which is concatenation of `a` and `b`, then it writes the concatenation to `a`.
15
+ # The read and write are independent operations they do not form a single atomic
16
+ # operation therefore when two `+=` operations are executed concurrently updates
17
+ # may be lost. Use `#concat` instead.
18
+ #
19
+ # @see http://ruby-doc.org/core-2.2.0/Array.html Ruby standard library `Array`
20
+
21
+ # @!macro internal_implementation_note
22
+ ArrayImplementation = case
23
+ when Concurrent.on_cruby?
24
+ # Array is thread-safe in practice because CRuby runs
25
+ # threads one at a time and does not do context
26
+ # switching during the execution of C functions.
27
+ ::Array
28
+
29
+ when Concurrent.on_jruby?
30
+ require 'jruby/synchronized'
31
+
32
+ class JRubyArray < ::Array
33
+ include JRuby::Synchronized
34
+ end
35
+ JRubyArray
36
+
37
+ when Concurrent.on_rbx?
38
+ require 'monitor'
39
+ require 'concurrent/thread_safe/util/data_structures'
40
+
41
+ class RbxArray < ::Array
42
+ end
43
+
44
+ ThreadSafe::Util.make_synchronized_on_rbx RbxArray
45
+ RbxArray
46
+
47
+ when Concurrent.on_truffleruby?
48
+ require 'concurrent/thread_safe/util/data_structures'
49
+
50
+ class TruffleRubyArray < ::Array
51
+ end
52
+
53
+ ThreadSafe::Util.make_synchronized_on_truffleruby TruffleRubyArray
54
+ TruffleRubyArray
55
+
56
+ else
57
+ warn 'Possibly unsupported Ruby implementation'
58
+ ::Array
59
+ end
60
+ private_constant :ArrayImplementation
61
+
62
+ # @!macro concurrent_array
63
+ class Array < ArrayImplementation
64
+ end
65
+
66
+ end
@@ -159,7 +159,7 @@ module Concurrent
159
159
  #
160
160
  # To get the state *at the current* time, irrespective of an enqueued method
161
161
  # calls, a reader method must be called directly. This is inherently unsafe
162
- # unless the instance variable is itself thread-safe, preferrably using one
162
+ # unless the instance variable is itself thread-safe, preferably using one
163
163
  # of the thread-safe classes within this library. Because the thread-safe
164
164
  # classes within this library are internally-locking or non-locking, they can
165
165
  # be safely used from within asynchronous methods without causing deadlocks.
@@ -188,7 +188,7 @@ module Concurrent
188
188
  #
189
189
  # Class variables should be avoided. Class variables represent shared state.
190
190
  # Shared state is anathema to concurrency. Should there be a need to share
191
- # state using class variables they *must* be thread-safe, preferrably
191
+ # state using class variables they *must* be thread-safe, preferably
192
192
  # using the thread-safe classes within this library. When updating class
193
193
  # variables, never assign a new value/object to the variable itself. Assignment
194
194
  # is not thread-safe in Ruby. Instead, use the thread-safe update functions
@@ -333,6 +333,13 @@ module Concurrent
333
333
  ivar
334
334
  end
335
335
 
336
+ # Check whether the method is responsive
337
+ #
338
+ # @param [Symbol] method the method being called
339
+ def respond_to_missing?(method, include_private = false)
340
+ @delegate.respond_to?(method) || super
341
+ end
342
+
336
343
  # Perform all enqueued tasks.
337
344
  #
338
345
  # This method must be called from within the executor. It must not be
@@ -383,6 +390,13 @@ module Concurrent
383
390
  ivar.wait
384
391
  ivar
385
392
  end
393
+
394
+ # Check whether the method is responsive
395
+ #
396
+ # @param [Symbol] method the method being called
397
+ def respond_to_missing?(method, include_private = false)
398
+ @delegate.respond_to?(method) || super
399
+ end
386
400
  end
387
401
  private_constant :AwaitDelegator
388
402
 
@@ -392,7 +406,7 @@ module Concurrent
392
406
  # object's thread. The final disposition of the method call can be obtained
393
407
  # by inspecting the returned future.
394
408
  #
395
- # @!macro [attach] async_thread_safety_warning
409
+ # @!macro async_thread_safety_warning
396
410
  # @note The method call is guaranteed to be thread safe with respect to
397
411
  # all other method calls against the same object that are called with
398
412
  # either `async` or `await`. The mutable nature of Ruby references
@@ -435,7 +449,7 @@ module Concurrent
435
449
  #
436
450
  # @!visibility private
437
451
  def init_synchronization
438
- return self if @__async_initialized__
452
+ return self if defined?(@__async_initialized__) && @__async_initialized__
439
453
  @__async_initialized__ = true
440
454
  @__async_delegator__ = AsyncDelegator.new(self)
441
455
  @__await_delegator__ = AwaitDelegator.new(@__async_delegator__)