concurrent-ruby 0.8.0.pre2-java → 0.9.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 (145) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +114 -3
  3. data/README.md +111 -55
  4. data/lib/concurrent.rb +90 -14
  5. data/lib/concurrent/async.rb +143 -51
  6. data/lib/concurrent/atom.rb +131 -0
  7. data/lib/concurrent/atomic/atomic_boolean.rb +57 -107
  8. data/lib/concurrent/atomic/atomic_fixnum.rb +73 -101
  9. data/lib/concurrent/atomic/atomic_reference.rb +49 -0
  10. data/lib/concurrent/atomic/condition.rb +23 -12
  11. data/lib/concurrent/atomic/count_down_latch.rb +23 -21
  12. data/lib/concurrent/atomic/cyclic_barrier.rb +47 -47
  13. data/lib/concurrent/atomic/event.rb +33 -42
  14. data/lib/concurrent/atomic/read_write_lock.rb +252 -0
  15. data/lib/concurrent/atomic/semaphore.rb +64 -89
  16. data/lib/concurrent/atomic/thread_local_var.rb +130 -58
  17. data/lib/concurrent/atomic/thread_local_var/weak_key_map.rb +236 -0
  18. data/lib/concurrent/atomic_reference/direct_update.rb +34 -3
  19. data/lib/concurrent/atomic_reference/jruby.rb +6 -3
  20. data/lib/concurrent/atomic_reference/mutex_atomic.rb +17 -39
  21. data/lib/concurrent/atomic_reference/numeric_cas_wrapper.rb +3 -0
  22. data/lib/concurrent/atomic_reference/rbx.rb +4 -1
  23. data/lib/concurrent/atomic_reference/ruby.rb +6 -3
  24. data/lib/concurrent/atomics.rb +74 -4
  25. data/lib/concurrent/collection/copy_on_notify_observer_set.rb +115 -0
  26. data/lib/concurrent/collection/copy_on_write_observer_set.rb +119 -0
  27. data/lib/concurrent/collection/priority_queue.rb +300 -245
  28. data/lib/concurrent/concern/deprecation.rb +34 -0
  29. data/lib/concurrent/concern/dereferenceable.rb +88 -0
  30. data/lib/concurrent/concern/logging.rb +27 -0
  31. data/lib/concurrent/concern/obligation.rb +228 -0
  32. data/lib/concurrent/concern/observable.rb +85 -0
  33. data/lib/concurrent/configuration.rb +234 -109
  34. data/lib/concurrent/dataflow.rb +2 -3
  35. data/lib/concurrent/delay.rb +141 -50
  36. data/lib/concurrent/edge.rb +30 -0
  37. data/lib/concurrent/errors.rb +19 -7
  38. data/lib/concurrent/exchanger.rb +25 -1
  39. data/lib/concurrent/executor/cached_thread_pool.rb +51 -33
  40. data/lib/concurrent/executor/executor.rb +46 -299
  41. data/lib/concurrent/executor/executor_service.rb +521 -0
  42. data/lib/concurrent/executor/fixed_thread_pool.rb +196 -23
  43. data/lib/concurrent/executor/immediate_executor.rb +9 -9
  44. data/lib/concurrent/executor/indirect_immediate_executor.rb +4 -3
  45. data/lib/concurrent/executor/java_single_thread_executor.rb +17 -16
  46. data/lib/concurrent/executor/java_thread_pool_executor.rb +55 -102
  47. data/lib/concurrent/executor/ruby_single_thread_executor.rb +14 -16
  48. data/lib/concurrent/executor/ruby_thread_pool_executor.rb +250 -166
  49. data/lib/concurrent/executor/safe_task_executor.rb +5 -4
  50. data/lib/concurrent/executor/serialized_execution.rb +22 -18
  51. data/lib/concurrent/executor/{per_thread_executor.rb → simple_executor_service.rb} +29 -20
  52. data/lib/concurrent/executor/single_thread_executor.rb +32 -21
  53. data/lib/concurrent/executor/thread_pool_executor.rb +73 -60
  54. data/lib/concurrent/executor/timer_set.rb +96 -84
  55. data/lib/concurrent/executors.rb +1 -1
  56. data/lib/concurrent/future.rb +71 -38
  57. data/lib/concurrent/immutable_struct.rb +89 -0
  58. data/lib/concurrent/ivar.rb +152 -60
  59. data/lib/concurrent/lazy_register.rb +40 -20
  60. data/lib/concurrent/maybe.rb +226 -0
  61. data/lib/concurrent/mutable_struct.rb +227 -0
  62. data/lib/concurrent/mvar.rb +44 -43
  63. data/lib/concurrent/promise.rb +229 -136
  64. data/lib/concurrent/scheduled_task.rb +341 -43
  65. data/lib/concurrent/settable_struct.rb +127 -0
  66. data/lib/concurrent/synchronization.rb +17 -0
  67. data/lib/concurrent/synchronization/abstract_object.rb +163 -0
  68. data/lib/concurrent/synchronization/abstract_struct.rb +158 -0
  69. data/lib/concurrent/synchronization/condition.rb +53 -0
  70. data/lib/concurrent/synchronization/java_object.rb +34 -0
  71. data/lib/concurrent/synchronization/lock.rb +32 -0
  72. data/lib/concurrent/synchronization/monitor_object.rb +26 -0
  73. data/lib/concurrent/synchronization/mutex_object.rb +43 -0
  74. data/lib/concurrent/synchronization/object.rb +78 -0
  75. data/lib/concurrent/synchronization/rbx_object.rb +75 -0
  76. data/lib/concurrent/timer_task.rb +92 -103
  77. data/lib/concurrent/tvar.rb +42 -38
  78. data/lib/concurrent/utilities.rb +3 -1
  79. data/lib/concurrent/utility/at_exit.rb +97 -0
  80. data/lib/concurrent/utility/engine.rb +44 -0
  81. data/lib/concurrent/utility/monotonic_time.rb +59 -0
  82. data/lib/concurrent/utility/native_extension_loader.rb +56 -0
  83. data/lib/concurrent/utility/processor_counter.rb +156 -0
  84. data/lib/concurrent/utility/timeout.rb +18 -14
  85. data/lib/concurrent/utility/timer.rb +11 -6
  86. data/lib/concurrent/version.rb +2 -1
  87. data/lib/concurrent_ruby.rb +1 -0
  88. data/lib/concurrent_ruby_ext.jar +0 -0
  89. metadata +46 -66
  90. data/lib/concurrent/actor.rb +0 -103
  91. data/lib/concurrent/actor/behaviour.rb +0 -70
  92. data/lib/concurrent/actor/behaviour/abstract.rb +0 -48
  93. data/lib/concurrent/actor/behaviour/awaits.rb +0 -21
  94. data/lib/concurrent/actor/behaviour/buffer.rb +0 -54
  95. data/lib/concurrent/actor/behaviour/errors_on_unknown_message.rb +0 -12
  96. data/lib/concurrent/actor/behaviour/executes_context.rb +0 -18
  97. data/lib/concurrent/actor/behaviour/linking.rb +0 -45
  98. data/lib/concurrent/actor/behaviour/pausing.rb +0 -77
  99. data/lib/concurrent/actor/behaviour/removes_child.rb +0 -16
  100. data/lib/concurrent/actor/behaviour/sets_results.rb +0 -36
  101. data/lib/concurrent/actor/behaviour/supervised.rb +0 -59
  102. data/lib/concurrent/actor/behaviour/supervising.rb +0 -34
  103. data/lib/concurrent/actor/behaviour/terminates_children.rb +0 -13
  104. data/lib/concurrent/actor/behaviour/termination.rb +0 -54
  105. data/lib/concurrent/actor/context.rb +0 -154
  106. data/lib/concurrent/actor/core.rb +0 -217
  107. data/lib/concurrent/actor/default_dead_letter_handler.rb +0 -9
  108. data/lib/concurrent/actor/envelope.rb +0 -41
  109. data/lib/concurrent/actor/errors.rb +0 -27
  110. data/lib/concurrent/actor/internal_delegations.rb +0 -49
  111. data/lib/concurrent/actor/public_delegations.rb +0 -40
  112. data/lib/concurrent/actor/reference.rb +0 -81
  113. data/lib/concurrent/actor/root.rb +0 -37
  114. data/lib/concurrent/actor/type_check.rb +0 -48
  115. data/lib/concurrent/actor/utils.rb +0 -10
  116. data/lib/concurrent/actor/utils/ad_hoc.rb +0 -21
  117. data/lib/concurrent/actor/utils/balancer.rb +0 -42
  118. data/lib/concurrent/actor/utils/broadcast.rb +0 -52
  119. data/lib/concurrent/actor/utils/pool.rb +0 -59
  120. data/lib/concurrent/actress.rb +0 -3
  121. data/lib/concurrent/agent.rb +0 -209
  122. data/lib/concurrent/atomic.rb +0 -92
  123. data/lib/concurrent/atomic/copy_on_notify_observer_set.rb +0 -118
  124. data/lib/concurrent/atomic/copy_on_write_observer_set.rb +0 -117
  125. data/lib/concurrent/atomic/synchronization.rb +0 -51
  126. data/lib/concurrent/channel/buffered_channel.rb +0 -85
  127. data/lib/concurrent/channel/channel.rb +0 -41
  128. data/lib/concurrent/channel/unbuffered_channel.rb +0 -35
  129. data/lib/concurrent/channel/waitable_list.rb +0 -40
  130. data/lib/concurrent/channels.rb +0 -5
  131. data/lib/concurrent/collection/blocking_ring_buffer.rb +0 -71
  132. data/lib/concurrent/collection/ring_buffer.rb +0 -59
  133. data/lib/concurrent/collections.rb +0 -3
  134. data/lib/concurrent/dereferenceable.rb +0 -108
  135. data/lib/concurrent/executor/java_cached_thread_pool.rb +0 -32
  136. data/lib/concurrent/executor/java_fixed_thread_pool.rb +0 -31
  137. data/lib/concurrent/executor/ruby_cached_thread_pool.rb +0 -29
  138. data/lib/concurrent/executor/ruby_fixed_thread_pool.rb +0 -32
  139. data/lib/concurrent/executor/ruby_thread_pool_worker.rb +0 -73
  140. data/lib/concurrent/logging.rb +0 -20
  141. data/lib/concurrent/obligation.rb +0 -171
  142. data/lib/concurrent/observable.rb +0 -73
  143. data/lib/concurrent/options_parser.rb +0 -48
  144. data/lib/concurrent/utility/processor_count.rb +0 -152
  145. data/lib/extension_helper.rb +0 -37
@@ -1,27 +0,0 @@
1
- module Concurrent
2
- module Actor
3
- Error = Class.new(StandardError)
4
-
5
- class ActorTerminated < Error
6
- include TypeCheck
7
-
8
- attr_reader :reference
9
-
10
- def initialize(reference)
11
- @reference = Type! reference, Reference
12
- super reference.path
13
- end
14
- end
15
-
16
- class UnknownMessage < Error
17
- include TypeCheck
18
-
19
- attr_reader :envelope
20
-
21
- def initialize(envelope)
22
- @envelope = Type! envelope, Envelope
23
- super envelope.message.inspect
24
- end
25
- end
26
- end
27
- end
@@ -1,49 +0,0 @@
1
- module Concurrent
2
- module Actor
3
- module InternalDelegations
4
- include PublicDelegations
5
-
6
- # @see Core#children
7
- def children
8
- core.children
9
- end
10
-
11
- # @see Core#terminate!
12
- def terminate!
13
- behaviour!(Behaviour::Termination).terminate!
14
- end
15
-
16
- # delegates to core.log
17
- # @see Logging#log
18
- def log(level, message = nil, &block)
19
- core.log(level, message, &block)
20
- end
21
-
22
- # @see AbstractContext#dead_letter_routing
23
- def dead_letter_routing
24
- context.dead_letter_routing
25
- end
26
-
27
- def redirect(reference, envelope = self.envelope)
28
- reference.message(envelope.message, envelope.ivar)
29
- Behaviour::MESSAGE_PROCESSED
30
- end
31
-
32
- # @return [AbstractContext]
33
- def context
34
- core.context
35
- end
36
-
37
- # see Core#behaviour
38
- def behaviour(behaviour_class)
39
- core.behaviour(behaviour_class)
40
- end
41
-
42
- # see Core#behaviour!
43
- def behaviour!(behaviour_class)
44
- core.behaviour!(behaviour_class)
45
- end
46
-
47
- end
48
- end
49
- end
@@ -1,40 +0,0 @@
1
- module Concurrent
2
- module Actor
3
-
4
- # Provides publicly expose-able methods from {Core}.
5
- module PublicDelegations
6
- # @see Core#name
7
- def name
8
- core.name
9
- end
10
-
11
- # @see Core#path
12
- def path
13
- core.path
14
- end
15
-
16
- # @see Core#parent
17
- def parent
18
- core.parent
19
- end
20
-
21
- # @see Core#reference
22
- def reference
23
- core.reference
24
- end
25
-
26
- # @see Core#executor
27
- def executor
28
- core.executor
29
- end
30
-
31
- # @see Core#context_class
32
- def context_class
33
- core.context_class
34
- end
35
-
36
- alias_method :ref, :reference
37
- alias_method :actor_class, :context_class
38
- end
39
- end
40
- end
@@ -1,81 +0,0 @@
1
- module Concurrent
2
- module Actor
3
-
4
- # Reference is public interface of Actor instances. It is used for sending messages and can
5
- # be freely passed around the program. It also provides some basic information about the actor,
6
- # see {PublicDelegations}.
7
- class Reference
8
- include TypeCheck
9
- include PublicDelegations
10
-
11
- attr_reader :core
12
- private :core
13
-
14
- # @!visibility private
15
- def initialize(core)
16
- @core = Type! core, Core
17
- end
18
-
19
- # tells message to the actor, returns immediately
20
- # @param [Object] message
21
- # @return [Reference] self
22
- def tell(message)
23
- message message, nil
24
- end
25
-
26
- alias_method :<<, :tell
27
-
28
- # @note it's a good practice to use tell whenever possible. Ask should be used only for
29
- # testing and when it returns very shortly. It can lead to deadlock if all threads in
30
- # global_task_pool will block on while asking. It's fine to use it form outside of actors and
31
- # global_task_pool.
32
- #
33
- # sends message to the actor and asks for the result of its processing, returns immediately
34
- # @param [Object] message
35
- # @param [Ivar] ivar to be fulfilled be message's processing result
36
- # @return [IVar] supplied ivar
37
- def ask(message, ivar = IVar.new)
38
- message message, ivar
39
- end
40
-
41
- # @note it's a good practice to use tell whenever possible. Ask should be used only for
42
- # testing and when it returns very shortly. It can lead to deadlock if all threads in
43
- # global_task_pool will block on while asking. It's fine to use it form outside of actors and
44
- # global_task_pool.
45
- #
46
- # sends message to the actor and asks for the result of its processing, blocks
47
- # @param [Object] message
48
- # @param [Ivar] ivar to be fulfilled be message's processing result
49
- # @return [Object] message's processing result
50
- # @raise [Exception] ivar.reason if ivar is #rejected?
51
- def ask!(message, ivar = IVar.new)
52
- ask(message, ivar).value!
53
- end
54
-
55
- # behaves as {#tell} when no ivar and as {#ask} when ivar
56
- def message(message, ivar = nil)
57
- core.on_envelope Envelope.new(message, ivar, Actor.current || Thread.current, self)
58
- return ivar || self
59
- end
60
-
61
- # @see AbstractContext#dead_letter_routing
62
- def dead_letter_routing
63
- core.dead_letter_routing
64
- end
65
-
66
- def to_s
67
- "#<#{self.class} #{path} (#{actor_class})>"
68
- end
69
-
70
- alias_method :inspect, :to_s
71
-
72
- def ==(other)
73
- Type? other, self.class and other.send(:core) == core
74
- end
75
-
76
- # to avoid confusion with Kernel.spawn
77
- undef_method :spawn
78
- end
79
-
80
- end
81
- end
@@ -1,37 +0,0 @@
1
- module Concurrent
2
- module Actor
3
- # implements the root actor
4
- class Root < AbstractContext
5
-
6
- def initialize
7
- # noinspection RubyArgCount
8
- @dead_letter_router = Core.new(parent: reference,
9
- class: DefaultDeadLetterHandler,
10
- supervise: true,
11
- name: :default_dead_letter_handler).reference
12
- end
13
-
14
- # to allow spawning of new actors, spawn needs to be called inside the parent Actor
15
- def on_message(message)
16
- case
17
- when message.is_a?(Array) && message.first == :spawn
18
- Actor.spawn message[1], &message[2]
19
- when message == :dead_letter_routing
20
- @dead_letter_router
21
- else
22
- # ignore
23
- end
24
- end
25
-
26
- def dead_letter_routing
27
- @dead_letter_router
28
- end
29
-
30
- def behaviour_definition
31
- [*Behaviour.base,
32
- [Behaviour::Supervising, [:reset!, :one_for_one]],
33
- *Behaviour.user_messages(:just_log)]
34
- end
35
- end
36
- end
37
- end
@@ -1,48 +0,0 @@
1
- module Concurrent
2
- module Actor
3
-
4
- # taken from Algebrick
5
- # supplies type-checking helpers whenever included
6
- module TypeCheck
7
-
8
- def Type?(value, *types)
9
- types.any? { |t| value.is_a? t }
10
- end
11
-
12
- def Type!(value, *types)
13
- Type?(value, *types) or
14
- TypeCheck.error(value, 'is not', types)
15
- value
16
- end
17
-
18
- def Match?(value, *types)
19
- types.any? { |t| t === value }
20
- end
21
-
22
- def Match!(value, *types)
23
- Match?(value, *types) or
24
- TypeCheck.error(value, 'is not matching', types)
25
- value
26
- end
27
-
28
- def Child?(value, *types)
29
- Type?(value, Class) &&
30
- types.any? { |t| value <= t }
31
- end
32
-
33
- def Child!(value, *types)
34
- Child?(value, *types) or
35
- TypeCheck.error(value, 'is not child', types)
36
- value
37
- end
38
-
39
- private
40
-
41
- def self.error(value, message, types)
42
- raise TypeError,
43
- "Value (#{value.class}) '#{value}' #{message} any of: #{types.join('; ')}."
44
- end
45
- end
46
- end
47
- end
48
-
@@ -1,10 +0,0 @@
1
- module Concurrent
2
- module Actor
3
- module Utils
4
- require 'concurrent/actor/utils/ad_hoc'
5
- require 'concurrent/actor/utils/broadcast'
6
- require 'concurrent/actor/utils/balancer'
7
- require 'concurrent/actor/utils/pool'
8
- end
9
- end
10
- end
@@ -1,21 +0,0 @@
1
- module Concurrent
2
- module Actor
3
- module Utils
4
- # Allows quick creation of actors with behaviour defined by blocks.
5
- # @example ping
6
- # AdHoc.spawn :forward, an_actor do |where|
7
- # # this block has to return proc defining #on_message behaviour
8
- # -> message { where.tell message }
9
- # end
10
- class AdHoc < Context
11
- def initialize(*args, &initializer)
12
- @on_message = Type! initializer.call(*args), Proc
13
- end
14
-
15
- def on_message(message)
16
- instance_exec message, &@on_message
17
- end
18
- end
19
- end
20
- end
21
- end
@@ -1,42 +0,0 @@
1
- module Concurrent
2
- module Actor
3
- module Utils
4
-
5
- # Distributes messages between subscribed actors. Each actor'll get only one message then
6
- # it's unsubscribed. The actor needs to resubscribe when it's ready to receive next message.
7
- # It will buffer the messages if there is no worker registered.
8
- # @see Pool
9
- class Balancer < RestartingContext
10
-
11
- def initialize
12
- @receivers = []
13
- @buffer = []
14
- end
15
-
16
- def on_message(message)
17
- case message
18
- when :subscribe
19
- @receivers << envelope.sender
20
- distribute
21
- true
22
- when :unsubscribe
23
- @receivers.delete envelope.sender
24
- true
25
- when :subscribed?
26
- @receivers.include? envelope.sender
27
- else
28
- @buffer << envelope
29
- distribute
30
- Behaviour::MESSAGE_PROCESSED
31
- end
32
- end
33
-
34
- def distribute
35
- while !@receivers.empty? && !@buffer.empty?
36
- redirect @receivers.shift, @buffer.shift
37
- end
38
- end
39
- end
40
- end
41
- end
42
- end
@@ -1,52 +0,0 @@
1
- require 'set'
2
-
3
- module Concurrent
4
- module Actor
5
- module Utils
6
-
7
- # Allows to build pub/sub easily.
8
- # @example news
9
- # news_channel = Concurrent::Actor::Utils::Broadcast.spawn :news
10
- #
11
- # 2.times do |i|
12
- # Concurrent::Actor::Utils::AdHoc.spawn "listener-#{i}" do
13
- # news_channel << :subscribe
14
- # -> message { puts message }
15
- # end
16
- # end
17
- #
18
- # news_channel << 'Ruby rocks!'
19
- # # prints: 'Ruby rocks!' twice
20
- class Broadcast < RestartingContext
21
-
22
- def initialize
23
- @receivers = Set.new
24
- end
25
-
26
- def on_message(message)
27
- case message
28
- when :subscribe
29
- if envelope.sender.is_a? Reference
30
- @receivers.add envelope.sender
31
- true
32
- else
33
- false
34
- end
35
- when :unsubscribe
36
- !!@receivers.delete(envelope.sender)
37
- when :subscribed?
38
- @receivers.include? envelope.sender
39
- else
40
- filtered_receivers.each { |r| r << message }
41
- end
42
- end
43
-
44
- # override to define different behaviour, filtering etc
45
- def filtered_receivers
46
- @receivers
47
- end
48
- end
49
-
50
- end
51
- end
52
- end
@@ -1,59 +0,0 @@
1
- require 'concurrent/actor/utils/balancer'
2
-
3
- module Concurrent
4
- module Actor
5
- module Utils
6
-
7
- # Allows to create a pool of workers and distribute work between them
8
- # @param [Integer] size number of workers
9
- # @yield [balancer, index] a block spawning an worker instance. called +size+ times.
10
- # The worker should be descendant of AbstractWorker and supervised, see example.
11
- # @yieldparam [Balancer] balancer to pass to the worker
12
- # @yieldparam [Integer] index of the worker, usually used in its name
13
- # @yieldreturn [Reference] the reference of newly created worker
14
- # @example
15
- # class Worker < Concurrent::Actor::Utils::AbstractWorker
16
- # def work(message)
17
- # p message * 5
18
- # end
19
- # end
20
- #
21
- # pool = Concurrent::Actor::Utils::Pool.spawn! 'pool', 5 do |balancer, index|
22
- # Worker.spawn name: "worker-#{index}", supervise: true, args: [balancer]
23
- # end
24
- #
25
- # pool << 'asd' << 2
26
- # # prints:
27
- # # "asdasdasdasdasd"
28
- # # 10
29
- class Pool < RestartingContext
30
- def initialize(size, &worker_initializer)
31
- @balancer = Balancer.spawn name: :balancer, supervise: true
32
- @workers = Array.new(size, &worker_initializer.curry[@balancer])
33
- @workers.each { |w| Type! w, Reference }
34
- end
35
-
36
- def on_message(message)
37
- redirect @balancer
38
- end
39
- end
40
-
41
- class AbstractWorker < RestartingContext
42
- def initialize(balancer)
43
- @balancer = balancer
44
- @balancer << :subscribe
45
- end
46
-
47
- def on_message(message)
48
- work message
49
- ensure
50
- @balancer << :subscribe
51
- end
52
-
53
- def work(message)
54
- raise NotImplementedError
55
- end
56
- end
57
- end
58
- end
59
- end