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
@@ -2,7 +2,9 @@ require 'concurrent/synchronization'
2
2
 
3
3
  module Concurrent
4
4
 
5
- class CyclicBarrier < Synchronization::Object
5
+ # A synchronization aid that allows a set of threads to all wait for each
6
+ # other to reach a common barrier point.
7
+ class CyclicBarrier < Synchronization::LockableObject
6
8
 
7
9
  # @!visibility private
8
10
  Generation = Struct.new(:status)
@@ -13,7 +13,7 @@ module Concurrent
13
13
  # `#reset` at any time once it has been set.
14
14
  #
15
15
  # @see http://msdn.microsoft.com/en-us/library/windows/desktop/ms682655.aspx
16
- class Event < Synchronization::Object
16
+ class Event < Synchronization::LockableObject
17
17
 
18
18
  # Creates a new `Event` in the unset state. Threads calling `#wait` on the
19
19
  # `Event` will block.
@@ -0,0 +1,39 @@
1
+ if Concurrent.on_jruby?
2
+
3
+ module Concurrent
4
+
5
+ # @!macro count_down_latch
6
+ # @!visibility private
7
+ # @!macro internal_implementation_note
8
+ class JavaCountDownLatch
9
+
10
+ # @!macro count_down_latch_method_initialize
11
+ def initialize(count = 1)
12
+ unless count.is_a?(Fixnum) && count >= 0
13
+ raise ArgumentError.new('count must be in integer greater than or equal zero')
14
+ end
15
+ @latch = java.util.concurrent.CountDownLatch.new(count)
16
+ end
17
+
18
+ # @!macro count_down_latch_method_wait
19
+ def wait(timeout = nil)
20
+ if timeout.nil?
21
+ @latch.await
22
+ true
23
+ else
24
+ @latch.await(1000 * timeout, java.util.concurrent.TimeUnit::MILLISECONDS)
25
+ end
26
+ end
27
+
28
+ # @!macro count_down_latch_method_count_down
29
+ def count_down
30
+ @latch.countDown
31
+ end
32
+
33
+ # @!macro count_down_latch_method_count
34
+ def count
35
+ @latch.getCount
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,50 @@
1
+ require 'concurrent/atomic/abstract_thread_local_var'
2
+
3
+ if Concurrent.on_jruby?
4
+
5
+ module Concurrent
6
+
7
+ # @!visibility private
8
+ # @!macro internal_implementation_note
9
+ class JavaThreadLocalVar < AbstractThreadLocalVar
10
+
11
+ # @!macro thread_local_var_method_get
12
+ def value
13
+ value = @var.get
14
+
15
+ if value.nil?
16
+ @default
17
+ elsif value == NULL
18
+ nil
19
+ else
20
+ value
21
+ end
22
+ end
23
+
24
+ # @!macro thread_local_var_method_set
25
+ def value=(value)
26
+ @var.set(value)
27
+ end
28
+
29
+ # @!macro thread_local_var_method_bind
30
+ def bind(value, &block)
31
+ if block_given?
32
+ old_value = @var.get
33
+ begin
34
+ @var.set(value)
35
+ yield
36
+ ensure
37
+ @var.set(old_value)
38
+ end
39
+ end
40
+ end
41
+
42
+ protected
43
+
44
+ # @!visibility private
45
+ def allocate_storage
46
+ @var = java.lang.ThreadLocal.new
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,60 @@
1
+ require 'concurrent/synchronization'
2
+
3
+ module Concurrent
4
+
5
+ # @!macro atomic_boolean
6
+ # @!visibility private
7
+ # @!macro internal_implementation_note
8
+ class MutexAtomicBoolean < Synchronization::LockableObject
9
+
10
+ # @!macro atomic_boolean_method_initialize
11
+ def initialize(initial = false)
12
+ super()
13
+ synchronize { ns_initialize(initial) }
14
+ end
15
+
16
+ # @!macro atomic_boolean_method_value_get
17
+ def value
18
+ synchronize { @value }
19
+ end
20
+
21
+ # @!macro atomic_boolean_method_value_set
22
+ def value=(value)
23
+ synchronize { @value = !!value }
24
+ end
25
+
26
+ # @!macro atomic_boolean_method_true_question
27
+ def true?
28
+ synchronize { @value }
29
+ end
30
+
31
+ # @!macro atomic_boolean_method_false_question
32
+ def false?
33
+ synchronize { !@value }
34
+ end
35
+
36
+ # @!macro atomic_boolean_method_make_true
37
+ def make_true
38
+ synchronize { ns_make_value(true) }
39
+ end
40
+
41
+ # @!macro atomic_boolean_method_make_false
42
+ def make_false
43
+ synchronize { ns_make_value(false) }
44
+ end
45
+
46
+ protected
47
+
48
+ # @!visibility private
49
+ def ns_initialize(initial)
50
+ @value = !!initial
51
+ end
52
+
53
+ # @!visibility private
54
+ def ns_make_value(value)
55
+ old = @value
56
+ @value = value
57
+ old != @value
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,91 @@
1
+ require 'concurrent/synchronization'
2
+
3
+ module Concurrent
4
+
5
+ # @!macro atomic_fixnum
6
+ # @!visibility private
7
+ # @!macro internal_implementation_note
8
+ class MutexAtomicFixnum < Synchronization::LockableObject
9
+
10
+ # http://stackoverflow.com/questions/535721/ruby-max-integer
11
+ MIN_VALUE = -(2**(0.size * 8 - 2))
12
+ MAX_VALUE = (2**(0.size * 8 - 2) - 1)
13
+
14
+ # @!macro atomic_fixnum_method_initialize
15
+ def initialize(initial = 0)
16
+ super()
17
+ synchronize { ns_initialize(initial) }
18
+ end
19
+
20
+ # @!macro atomic_fixnum_method_value_get
21
+ def value
22
+ synchronize { @value }
23
+ end
24
+
25
+ # @!macro atomic_fixnum_method_value_set
26
+ def value=(value)
27
+ synchronize { ns_set(value) }
28
+ end
29
+
30
+ # @!macro atomic_fixnum_method_increment
31
+ def increment(delta = 1)
32
+ synchronize { ns_set(@value + delta.to_i) }
33
+ end
34
+
35
+ alias_method :up, :increment
36
+
37
+ # @!macro atomic_fixnum_method_decrement
38
+ def decrement(delta = 1)
39
+ synchronize { ns_set(@value - delta.to_i) }
40
+ end
41
+
42
+ alias_method :down, :decrement
43
+
44
+ # @!macro atomic_fixnum_method_compare_and_set
45
+ def compare_and_set(expect, update)
46
+ synchronize do
47
+ if @value == expect.to_i
48
+ @value = update.to_i
49
+ true
50
+ else
51
+ false
52
+ end
53
+ end
54
+ end
55
+
56
+ # @!macro atomic_fixnum_method_update
57
+ def update
58
+ synchronize do
59
+ @value = yield @value
60
+ end
61
+ end
62
+
63
+ protected
64
+
65
+ # @!visibility private
66
+ def ns_initialize(initial)
67
+ ns_set(initial)
68
+ end
69
+
70
+ private
71
+
72
+ # @!visibility private
73
+ def ns_set(value)
74
+ range_check!(value)
75
+ @value = value
76
+ end
77
+
78
+ # @!visibility private
79
+ def range_check!(value)
80
+ if !value.is_a?(Fixnum)
81
+ raise ArgumentError.new('value value must be a Fixnum')
82
+ elsif value > MAX_VALUE
83
+ raise RangeError.new("#{value} is greater than the maximum value of #{MAX_VALUE}")
84
+ elsif value < MIN_VALUE
85
+ raise RangeError.new("#{value} is less than the maximum value of #{MIN_VALUE}")
86
+ else
87
+ value
88
+ end
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,43 @@
1
+ require 'concurrent/synchronization'
2
+
3
+ module Concurrent
4
+
5
+ # @!macro count_down_latch
6
+ # @!visibility private
7
+ # @!macro internal_implementation_note
8
+ class MutexCountDownLatch < Synchronization::LockableObject
9
+
10
+ # @!macro count_down_latch_method_initialize
11
+ def initialize(count = 1)
12
+ unless count.is_a?(Fixnum) && count >= 0
13
+ raise ArgumentError.new('count must be in integer greater than or equal zero')
14
+ end
15
+ super()
16
+ synchronize { ns_initialize count }
17
+ end
18
+
19
+ # @!macro count_down_latch_method_wait
20
+ def wait(timeout = nil)
21
+ synchronize { ns_wait_until(timeout) { @count == 0 } }
22
+ end
23
+
24
+ # @!macro count_down_latch_method_count_down
25
+ def count_down
26
+ synchronize do
27
+ @count -= 1 if @count > 0
28
+ ns_broadcast if @count == 0
29
+ end
30
+ end
31
+
32
+ # @!macro count_down_latch_method_count
33
+ def count
34
+ synchronize { @count }
35
+ end
36
+
37
+ protected
38
+
39
+ def ns_initialize(count)
40
+ @count = count
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,115 @@
1
+ require 'concurrent/synchronization'
2
+
3
+ module Concurrent
4
+
5
+ # @!macro semaphore
6
+ # @!visibility private
7
+ # @!macro internal_implementation_note
8
+ class MutexSemaphore < Synchronization::LockableObject
9
+
10
+ # @!macro semaphore_method_initialize
11
+ def initialize(count)
12
+ unless count.is_a?(Fixnum) && count >= 0
13
+ fail ArgumentError, 'count must be an non-negative integer'
14
+ end
15
+ super()
16
+ synchronize { ns_initialize count }
17
+ end
18
+
19
+ # @!macro semaphore_method_acquire
20
+ def acquire(permits = 1)
21
+ unless permits.is_a?(Fixnum) && permits > 0
22
+ fail ArgumentError, 'permits must be an integer greater than zero'
23
+ end
24
+ synchronize do
25
+ try_acquire_timed(permits, nil)
26
+ nil
27
+ end
28
+ end
29
+
30
+ # @!macro semaphore_method_available_permits
31
+ def available_permits
32
+ synchronize { @free }
33
+ end
34
+
35
+ # @!macro semaphore_method_drain_permits
36
+ #
37
+ # Acquires and returns all permits that are immediately available.
38
+ #
39
+ # @return [Integer]
40
+ def drain_permits
41
+ synchronize do
42
+ @free.tap { |_| @free = 0 }
43
+ end
44
+ end
45
+
46
+ # @!macro semaphore_method_try_acquire
47
+ def try_acquire(permits = 1, timeout = nil)
48
+ unless permits.is_a?(Fixnum) && permits > 0
49
+ fail ArgumentError, 'permits must be an integer greater than zero'
50
+ end
51
+ synchronize do
52
+ if timeout.nil?
53
+ try_acquire_now(permits)
54
+ else
55
+ try_acquire_timed(permits, timeout)
56
+ end
57
+ end
58
+ end
59
+
60
+ # @!macro semaphore_method_release
61
+ def release(permits = 1)
62
+ unless permits.is_a?(Fixnum) && permits > 0
63
+ fail ArgumentError, 'permits must be an integer greater than zero'
64
+ end
65
+ synchronize do
66
+ @free += permits
67
+ permits.times { ns_signal }
68
+ end
69
+ nil
70
+ end
71
+
72
+ # Shrinks the number of available permits by the indicated reduction.
73
+ #
74
+ # @param [Fixnum] reduction Number of permits to remove.
75
+ #
76
+ # @raise [ArgumentError] if `reduction` is not an integer or is negative
77
+ #
78
+ # @raise [ArgumentError] if `@free` - `@reduction` is less than zero
79
+ #
80
+ # @return [nil]
81
+ #
82
+ # @!visibility private
83
+ def reduce_permits(reduction)
84
+ unless reduction.is_a?(Fixnum) && reduction >= 0
85
+ fail ArgumentError, 'reduction must be an non-negative integer'
86
+ end
87
+ synchronize { @free -= reduction }
88
+ nil
89
+ end
90
+
91
+ protected
92
+
93
+ # @!visibility private
94
+ def ns_initialize(count)
95
+ @free = count
96
+ end
97
+
98
+ private
99
+
100
+ # @!visibility private
101
+ def try_acquire_now(permits)
102
+ if @free >= permits
103
+ @free -= permits
104
+ true
105
+ else
106
+ false
107
+ end
108
+ end
109
+
110
+ # @!visibility private
111
+ def try_acquire_timed(permits, timeout)
112
+ ns_wait_until(timeout) { try_acquire_now(permits) }
113
+ end
114
+ end
115
+ end
@@ -41,10 +41,12 @@ module Concurrent
41
41
  # @!visibility private
42
42
  MAX_WRITERS = RUNNING_WRITER - MAX_READERS - 1
43
43
 
44
- # Implementation notes:
44
+ safe_initialization!
45
+
46
+ # Implementation notes:
45
47
  # A goal is to make the uncontended path for both readers/writers lock-free
46
48
  # Only if there is reader-writer or writer-writer contention, should locks be used
47
- # Internal state is represented by a single integer ("counter"), and updated
49
+ # Internal state is represented by a single integer ("counter"), and updated
48
50
  # using atomic compare-and-swap operations
49
51
  # When the counter is 0, the lock is free
50
52
  # Each reader increments the counter by 1 when acquiring a read lock
@@ -54,11 +56,10 @@ module Concurrent
54
56
 
55
57
  # Create a new `ReadWriteLock` in the unlocked state.
56
58
  def initialize
59
+ super()
57
60
  @Counter = AtomicFixnum.new(0) # single integer which represents lock state
58
61
  @ReadLock = Synchronization::Lock.new
59
62
  @WriteLock = Synchronization::Lock.new
60
- ensure_ivar_visibility!
61
- super()
62
63
  end
63
64
 
64
65
  # Execute a block operation within a read lock.