concurrent-ruby 0.7.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 (112) hide show
  1. data/LICENSE.txt +21 -0
  2. data/README.md +217 -0
  3. data/lib/concurrent.rb +45 -0
  4. data/lib/concurrent/actor.rb +104 -0
  5. data/lib/concurrent/actor/behaviour.rb +70 -0
  6. data/lib/concurrent/actor/behaviour/abstract.rb +48 -0
  7. data/lib/concurrent/actor/behaviour/awaits.rb +21 -0
  8. data/lib/concurrent/actor/behaviour/buffer.rb +54 -0
  9. data/lib/concurrent/actor/behaviour/errors_on_unknown_message.rb +12 -0
  10. data/lib/concurrent/actor/behaviour/executes_context.rb +18 -0
  11. data/lib/concurrent/actor/behaviour/linking.rb +42 -0
  12. data/lib/concurrent/actor/behaviour/pausing.rb +77 -0
  13. data/lib/concurrent/actor/behaviour/removes_child.rb +16 -0
  14. data/lib/concurrent/actor/behaviour/sets_results.rb +36 -0
  15. data/lib/concurrent/actor/behaviour/supervised.rb +58 -0
  16. data/lib/concurrent/actor/behaviour/supervising.rb +34 -0
  17. data/lib/concurrent/actor/behaviour/terminates_children.rb +13 -0
  18. data/lib/concurrent/actor/behaviour/termination.rb +54 -0
  19. data/lib/concurrent/actor/context.rb +153 -0
  20. data/lib/concurrent/actor/core.rb +213 -0
  21. data/lib/concurrent/actor/default_dead_letter_handler.rb +9 -0
  22. data/lib/concurrent/actor/envelope.rb +41 -0
  23. data/lib/concurrent/actor/errors.rb +27 -0
  24. data/lib/concurrent/actor/internal_delegations.rb +49 -0
  25. data/lib/concurrent/actor/public_delegations.rb +40 -0
  26. data/lib/concurrent/actor/reference.rb +81 -0
  27. data/lib/concurrent/actor/root.rb +37 -0
  28. data/lib/concurrent/actor/type_check.rb +48 -0
  29. data/lib/concurrent/actor/utils.rb +10 -0
  30. data/lib/concurrent/actor/utils/ad_hoc.rb +21 -0
  31. data/lib/concurrent/actor/utils/balancer.rb +40 -0
  32. data/lib/concurrent/actor/utils/broadcast.rb +52 -0
  33. data/lib/concurrent/actor/utils/pool.rb +59 -0
  34. data/lib/concurrent/actress.rb +3 -0
  35. data/lib/concurrent/agent.rb +230 -0
  36. data/lib/concurrent/async.rb +284 -0
  37. data/lib/concurrent/atomic.rb +91 -0
  38. data/lib/concurrent/atomic/atomic_boolean.rb +202 -0
  39. data/lib/concurrent/atomic/atomic_fixnum.rb +203 -0
  40. data/lib/concurrent/atomic/condition.rb +67 -0
  41. data/lib/concurrent/atomic/copy_on_notify_observer_set.rb +118 -0
  42. data/lib/concurrent/atomic/copy_on_write_observer_set.rb +117 -0
  43. data/lib/concurrent/atomic/count_down_latch.rb +116 -0
  44. data/lib/concurrent/atomic/cyclic_barrier.rb +106 -0
  45. data/lib/concurrent/atomic/event.rb +98 -0
  46. data/lib/concurrent/atomic/synchronization.rb +51 -0
  47. data/lib/concurrent/atomic/thread_local_var.rb +82 -0
  48. data/lib/concurrent/atomic_reference/concurrent_update_error.rb +8 -0
  49. data/lib/concurrent/atomic_reference/direct_update.rb +50 -0
  50. data/lib/concurrent/atomic_reference/jruby.rb +14 -0
  51. data/lib/concurrent/atomic_reference/mutex_atomic.rb +77 -0
  52. data/lib/concurrent/atomic_reference/numeric_cas_wrapper.rb +25 -0
  53. data/lib/concurrent/atomic_reference/rbx.rb +19 -0
  54. data/lib/concurrent/atomic_reference/ruby.rb +37 -0
  55. data/lib/concurrent/atomics.rb +11 -0
  56. data/lib/concurrent/channel/buffered_channel.rb +85 -0
  57. data/lib/concurrent/channel/channel.rb +41 -0
  58. data/lib/concurrent/channel/unbuffered_channel.rb +35 -0
  59. data/lib/concurrent/channel/waitable_list.rb +40 -0
  60. data/lib/concurrent/channels.rb +5 -0
  61. data/lib/concurrent/collection/blocking_ring_buffer.rb +71 -0
  62. data/lib/concurrent/collection/priority_queue.rb +305 -0
  63. data/lib/concurrent/collection/ring_buffer.rb +59 -0
  64. data/lib/concurrent/collections.rb +3 -0
  65. data/lib/concurrent/configuration.rb +161 -0
  66. data/lib/concurrent/dataflow.rb +108 -0
  67. data/lib/concurrent/delay.rb +104 -0
  68. data/lib/concurrent/dereferenceable.rb +101 -0
  69. data/lib/concurrent/errors.rb +30 -0
  70. data/lib/concurrent/exchanger.rb +34 -0
  71. data/lib/concurrent/executor/cached_thread_pool.rb +44 -0
  72. data/lib/concurrent/executor/executor.rb +282 -0
  73. data/lib/concurrent/executor/fixed_thread_pool.rb +33 -0
  74. data/lib/concurrent/executor/immediate_executor.rb +65 -0
  75. data/lib/concurrent/executor/java_cached_thread_pool.rb +31 -0
  76. data/lib/concurrent/executor/java_fixed_thread_pool.rb +41 -0
  77. data/lib/concurrent/executor/java_single_thread_executor.rb +22 -0
  78. data/lib/concurrent/executor/java_thread_pool_executor.rb +180 -0
  79. data/lib/concurrent/executor/per_thread_executor.rb +100 -0
  80. data/lib/concurrent/executor/ruby_cached_thread_pool.rb +29 -0
  81. data/lib/concurrent/executor/ruby_fixed_thread_pool.rb +32 -0
  82. data/lib/concurrent/executor/ruby_single_thread_executor.rb +74 -0
  83. data/lib/concurrent/executor/ruby_thread_pool_executor.rb +288 -0
  84. data/lib/concurrent/executor/ruby_thread_pool_worker.rb +72 -0
  85. data/lib/concurrent/executor/safe_task_executor.rb +35 -0
  86. data/lib/concurrent/executor/serialized_execution.rb +126 -0
  87. data/lib/concurrent/executor/single_thread_executor.rb +35 -0
  88. data/lib/concurrent/executor/thread_pool_executor.rb +68 -0
  89. data/lib/concurrent/executor/timer_set.rb +143 -0
  90. data/lib/concurrent/executors.rb +9 -0
  91. data/lib/concurrent/future.rb +125 -0
  92. data/lib/concurrent/ivar.rb +111 -0
  93. data/lib/concurrent/lazy_register.rb +58 -0
  94. data/lib/concurrent/logging.rb +17 -0
  95. data/lib/concurrent/mvar.rb +200 -0
  96. data/lib/concurrent/obligation.rb +171 -0
  97. data/lib/concurrent/observable.rb +40 -0
  98. data/lib/concurrent/options_parser.rb +48 -0
  99. data/lib/concurrent/promise.rb +170 -0
  100. data/lib/concurrent/scheduled_task.rb +79 -0
  101. data/lib/concurrent/timer_task.rb +341 -0
  102. data/lib/concurrent/tvar.rb +248 -0
  103. data/lib/concurrent/utilities.rb +3 -0
  104. data/lib/concurrent/utility/processor_count.rb +152 -0
  105. data/lib/concurrent/utility/timeout.rb +35 -0
  106. data/lib/concurrent/utility/timer.rb +21 -0
  107. data/lib/concurrent/version.rb +3 -0
  108. data/lib/concurrent_ruby.rb +1 -0
  109. data/lib/concurrent_ruby_ext.jar +0 -0
  110. data/lib/concurrent_ruby_ext.so +0 -0
  111. data/lib/extension_helper.rb +28 -0
  112. metadata +163 -0
@@ -0,0 +1,98 @@
1
+ require 'thread'
2
+ require 'concurrent/atomic/condition'
3
+
4
+ module Concurrent
5
+
6
+ # Old school kernel-style event reminiscent of Win32 programming in C++.
7
+ #
8
+ # When an `Event` is created it is in the `unset` state. Threads can choose to
9
+ # `#wait` on the event, blocking until released by another thread. When one
10
+ # thread wants to alert all blocking threads it calls the `#set` method which
11
+ # will then wake up all listeners. Once an `Event` has been set it remains set.
12
+ # New threads calling `#wait` will return immediately. An `Event` may be
13
+ # `#reset` at any time once it has been set.
14
+ #
15
+ # @see http://msdn.microsoft.com/en-us/library/windows/desktop/ms682655.aspx
16
+ class Event
17
+
18
+ # Creates a new `Event` in the unset state. Threads calling `#wait` on the
19
+ # `Event` will block.
20
+ def initialize
21
+ @set = false
22
+ @mutex = Mutex.new
23
+ @condition = Condition.new
24
+ end
25
+
26
+ # Is the object in the set state?
27
+ #
28
+ # @return [Boolean] indicating whether or not the `Event` has been set
29
+ def set?
30
+ @mutex.lock
31
+ @set
32
+ ensure
33
+ @mutex.unlock
34
+ end
35
+
36
+ # Trigger the event, setting the state to `set` and releasing all threads
37
+ # waiting on the event. Has no effect if the `Event` has already been set.
38
+ #
39
+ # @return [Boolean] should always return `true`
40
+ def set
41
+ @mutex.lock
42
+ unless @set
43
+ @set = true
44
+ @condition.broadcast
45
+ end
46
+ true
47
+ ensure
48
+ @mutex.unlock
49
+ end
50
+
51
+ def try?
52
+ @mutex.lock
53
+
54
+ if @set
55
+ false
56
+ else
57
+ @set = true
58
+ @condition.broadcast
59
+ true
60
+ end
61
+
62
+ ensure
63
+ @mutex.unlock
64
+ end
65
+
66
+ # Reset a previously set event back to the `unset` state.
67
+ # Has no effect if the `Event` has not yet been set.
68
+ #
69
+ # @return [Boolean] should always return `true`
70
+ def reset
71
+ @mutex.lock
72
+ @set = false
73
+ true
74
+ ensure
75
+ @mutex.unlock
76
+ end
77
+
78
+ # Wait a given number of seconds for the `Event` to be set by another
79
+ # thread. Will wait forever when no `timeout` value is given. Returns
80
+ # immediately if the `Event` has already been set.
81
+ #
82
+ # @return [Boolean] true if the `Event` was set before timeout else false
83
+ def wait(timeout = nil)
84
+ @mutex.lock
85
+
86
+ unless @set
87
+ remaining = Condition::Result.new(timeout)
88
+ while !@set && remaining.can_wait?
89
+ remaining = @condition.wait(@mutex, remaining.remaining_time)
90
+ end
91
+ end
92
+
93
+ @set
94
+ ensure
95
+ @mutex.unlock
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,51 @@
1
+ module Concurrent
2
+
3
+ # Safe synchronization under JRuby, prevents reading uninitialized @mutex variable.
4
+ # @note synchronized needs to be called in #initialize for this module to work properly
5
+ # @example usage
6
+ # class AClass
7
+ # include Synchronized
8
+ #
9
+ # def initialize
10
+ # synchronize do
11
+ # # body of the constructor ...
12
+ # end
13
+ # end
14
+ #
15
+ # def a_method
16
+ # synchronize do
17
+ # # body of a_method ...
18
+ # end
19
+ # end
20
+ # end
21
+ module Synchronization
22
+
23
+ engine = defined?(RUBY_ENGINE) && RUBY_ENGINE
24
+
25
+ case engine
26
+ when 'jruby'
27
+ require 'jruby'
28
+
29
+ def synchronize
30
+ JRuby.reference0(self).synchronized { yield }
31
+ end
32
+
33
+ when 'rbx'
34
+
35
+ def synchronize
36
+ Rubinius.lock(self)
37
+ yield
38
+ ensure
39
+ Rubinius.unlock(self)
40
+ end
41
+
42
+ else
43
+
44
+ def synchronize
45
+ @mutex ||= Mutex.new
46
+ @mutex.synchronize { yield }
47
+ end
48
+
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,82 @@
1
+ require 'concurrent/atomic'
2
+
3
+ module Concurrent
4
+
5
+ module ThreadLocalRubyStorage
6
+
7
+ def allocate_storage
8
+ @storage = Atomic.new Hash.new
9
+ end
10
+
11
+ def get
12
+ @storage.get[Thread.current]
13
+ end
14
+
15
+ def set(value)
16
+ @storage.update { |s| s.merge Thread.current => value }
17
+ end
18
+
19
+ end
20
+
21
+ module ThreadLocalJavaStorage
22
+
23
+ protected
24
+
25
+ def allocate_storage
26
+ @var = java.lang.ThreadLocal.new
27
+ end
28
+
29
+ def get
30
+ @var.get
31
+ end
32
+
33
+ def set(value)
34
+ @var.set(value)
35
+ end
36
+
37
+ end
38
+
39
+ class AbstractThreadLocalVar
40
+
41
+ NIL_SENTINEL = Object.new
42
+
43
+ def initialize(default = nil)
44
+ @default = default
45
+ allocate_storage
46
+ end
47
+
48
+ def value
49
+ value = get
50
+
51
+ if value.nil?
52
+ @default
53
+ elsif value == NIL_SENTINEL
54
+ nil
55
+ else
56
+ value
57
+ end
58
+ end
59
+
60
+ def value=(value)
61
+ if value.nil?
62
+ stored_value = NIL_SENTINEL
63
+ else
64
+ stored_value = value
65
+ end
66
+
67
+ set stored_value
68
+
69
+ value
70
+ end
71
+
72
+ end
73
+
74
+ class ThreadLocalVar < AbstractThreadLocalVar
75
+ if RUBY_PLATFORM == 'java'
76
+ include ThreadLocalJavaStorage
77
+ else
78
+ include ThreadLocalRubyStorage
79
+ end
80
+ end
81
+
82
+ end
@@ -0,0 +1,8 @@
1
+ module Concurrent
2
+
3
+ # @!macro atomic_reference
4
+ class ConcurrentUpdateError < ThreadError
5
+ # frozen pre-allocated backtrace to speed ConcurrentUpdateError
6
+ CONC_UP_ERR_BACKTRACE = ['backtrace elided; set verbose to enable'].freeze
7
+ end
8
+ end
@@ -0,0 +1,50 @@
1
+ require 'concurrent/atomic_reference/concurrent_update_error'
2
+
3
+ module Concurrent
4
+
5
+ # Define update methods that use direct paths
6
+ module AtomicDirectUpdate
7
+
8
+ # @!macro [attach] atomic_reference_method_update
9
+ #
10
+ # Pass the current value to the given block, replacing it
11
+ # with the block's result. May retry if the value changes
12
+ # during the block's execution.
13
+ #
14
+ # @yield [Object] Calculate a new value for the atomic reference using
15
+ # given (old) value
16
+ # @yieldparam [Object] old_value the starting value of the atomic reference
17
+ #
18
+ # @return [Object] the new value
19
+ def update
20
+ true until compare_and_set(old_value = get, new_value = yield(old_value))
21
+ new_value
22
+ end
23
+
24
+ # @!macro [attach] atomic_reference_method_try_update
25
+ #
26
+ # Pass the current value to the given block, replacing it
27
+ # with the block's result. Raise an exception if the update
28
+ # fails.
29
+ #
30
+ # @yield [Object] Calculate a new value for the atomic reference using
31
+ # given (old) value
32
+ # @yieldparam [Object] old_value the starting value of the atomic reference
33
+ #
34
+ # @return [Object] the new value
35
+ #
36
+ # @raise [Concurrent::ConcurrentUpdateError] if the update fails
37
+ def try_update
38
+ old_value = get
39
+ new_value = yield old_value
40
+ unless compare_and_set(old_value, new_value)
41
+ if $VERBOSE
42
+ raise ConcurrentUpdateError, "Update failed"
43
+ else
44
+ raise ConcurrentUpdateError, "Update failed", ConcurrentUpdateError::CONC_UP_ERR_BACKTRACE
45
+ end
46
+ end
47
+ new_value
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,14 @@
1
+ require_relative '../../extension_helper'
2
+ Concurrent.safe_require_java_extensions
3
+
4
+ if defined?(Concurrent::JavaAtomic)
5
+ require 'concurrent/atomic_reference/direct_update'
6
+
7
+ module Concurrent
8
+
9
+ # @!macro atomic_reference
10
+ class JavaAtomic
11
+ include Concurrent::AtomicDirectUpdate
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,77 @@
1
+ require 'thread'
2
+ require 'concurrent/atomic_reference/direct_update'
3
+ require 'concurrent/atomic_reference/numeric_cas_wrapper'
4
+
5
+ module Concurrent
6
+
7
+ # @!macro atomic_reference
8
+ class MutexAtomic
9
+ include Concurrent::AtomicDirectUpdate
10
+ include Concurrent::AtomicNumericCompareAndSetWrapper
11
+
12
+ # @!macro [attach] atomic_reference_method_initialize
13
+ def initialize(value = nil)
14
+ @mutex = Mutex.new
15
+ @value = value
16
+ end
17
+
18
+ # @!macro [attach] atomic_reference_method_get
19
+ #
20
+ # Gets the current value.
21
+ #
22
+ # @return [Object] the current value
23
+ def get
24
+ @mutex.synchronize { @value }
25
+ end
26
+ alias_method :value, :get
27
+
28
+ # @!macro [attach] atomic_reference_method_set
29
+ #
30
+ # Sets to the given value.
31
+ #
32
+ # @param [Object] new_value the new value
33
+ #
34
+ # @return [Object] the new value
35
+ def set(new_value)
36
+ @mutex.synchronize { @value = new_value }
37
+ end
38
+ alias_method :value=, :set
39
+
40
+ # @!macro [attach] atomic_reference_method_get_and_set
41
+ #
42
+ # Atomically sets to the given value and returns the old value.
43
+ #
44
+ # @param [Object] new_value the new value
45
+ #
46
+ # @return [Object] the old value
47
+ def get_and_set(new_value)
48
+ @mutex.synchronize do
49
+ old_value = @value
50
+ @value = new_value
51
+ old_value
52
+ end
53
+ end
54
+ alias_method :swap, :get_and_set
55
+
56
+ # @!macro [attach] atomic_reference_method_compare_and_set
57
+ #
58
+ # Atomically sets the value to the given updated value if
59
+ # the current value == the expected value.
60
+ #
61
+ # @param [Object] old_value the expected value
62
+ # @param [Object] new_value the new value
63
+ #
64
+ # @return [Boolean] `true` if successful. A `false` return indicates
65
+ # that the actual value was not equal to the expected value.
66
+ def _compare_and_set(old_value, new_value) #:nodoc:
67
+ return false unless @mutex.try_lock
68
+ begin
69
+ return false unless @value.equal? old_value
70
+ @value = new_value
71
+ ensure
72
+ @mutex.unlock
73
+ end
74
+ true
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,25 @@
1
+ module Concurrent
2
+
3
+ # Special "compare and set" handling of numeric values.
4
+ module AtomicNumericCompareAndSetWrapper
5
+
6
+ # @!macro atomic_reference_method_compare_and_set
7
+ def compare_and_set(old_value, new_value)
8
+ if old_value.kind_of? Numeric
9
+ while true
10
+ old = get
11
+
12
+ return false unless old.kind_of? Numeric
13
+
14
+ return false unless old == old_value
15
+
16
+ result = _compare_and_set(old, new_value)
17
+ return result if result
18
+ end
19
+ else
20
+ _compare_and_set(old_value, new_value)
21
+ end
22
+ end
23
+ alias_method :compare_and_swap, :compare_and_set
24
+ end
25
+ end
@@ -0,0 +1,19 @@
1
+ require 'concurrent/atomic_reference/direct_update'
2
+ require 'concurrent/atomic_reference/numeric_cas_wrapper'
3
+
4
+ module Concurrent
5
+
6
+ # @!macro atomic_reference
7
+ #
8
+ # @note Extends `Rubinius::AtomicReference` version adding aliases
9
+ # and numeric logic.
10
+ class RbxAtomic < Rubinius::AtomicReference
11
+ alias _compare_and_set compare_and_set
12
+ include Concurrent::AtomicDirectUpdate
13
+ include Concurrent::AtomicNumericCompareAndSetWrapper
14
+
15
+ alias_method :value, :get
16
+ alias_method :value=, :set
17
+ alias_method :swap, :get_and_set
18
+ end
19
+ end
@@ -0,0 +1,37 @@
1
+ require_relative '../../extension_helper'
2
+
3
+ if Concurrent.allow_c_extensions?
4
+ begin
5
+ require 'concurrent_ruby_ext'
6
+ rescue LoadError
7
+ # may be a Windows cross-compiled native gem
8
+ require "#{RUBY_VERSION[0..2]}/concurrent_ruby_ext"
9
+ end
10
+ end
11
+
12
+ require 'concurrent/atomic_reference/direct_update'
13
+ require 'concurrent/atomic_reference/numeric_cas_wrapper'
14
+
15
+ module Concurrent
16
+
17
+ # @!macro atomic_reference
18
+ class CAtomic
19
+ include Concurrent::AtomicDirectUpdate
20
+ include Concurrent::AtomicNumericCompareAndSetWrapper
21
+
22
+ # @!method initialize
23
+ # @!macro atomic_reference_method_initialize
24
+
25
+ # @!method get
26
+ # @!macro atomic_reference_method_get
27
+
28
+ # @!method set
29
+ # @!macro atomic_reference_method_set
30
+
31
+ # @!method get_and_set
32
+ # @!macro atomic_reference_method_get_and_set
33
+
34
+ # @!method _compare_and_set
35
+ # @!macro atomic_reference_method_compare_and_set
36
+ end
37
+ end