concurrent-ruby 0.7.0-java

Sign up to get free protection for your applications and to get access to all the features.
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,48 @@
1
+ module Concurrent
2
+ module Actor
3
+ module Behaviour
4
+ class Abstract
5
+ include TypeCheck
6
+ include InternalDelegations
7
+
8
+ attr_reader :core, :subsequent
9
+
10
+ def initialize(core, subsequent)
11
+ @core = Type! core, Core
12
+ @subsequent = Type! subsequent, Abstract, NilClass
13
+ end
14
+
15
+ # override to add extra behaviour
16
+ # @note super needs to be called not to break the chain
17
+ def on_envelope(envelope)
18
+ pass envelope
19
+ end
20
+
21
+ # @param [Envelope] envelope to pass to {#subsequent} behaviour
22
+ def pass(envelope)
23
+ subsequent.on_envelope envelope
24
+ end
25
+
26
+ # override to add extra behaviour
27
+ # @note super needs to be called not to break the chain
28
+ def on_event(event)
29
+ subsequent.on_event event if subsequent
30
+ end
31
+
32
+ # broadcasts event to all behaviours and context
33
+ # @see #on_event
34
+ # @see AbstractContext#on_event
35
+ def broadcast(event)
36
+ core.broadcast(event)
37
+ end
38
+
39
+ def reject_envelope(envelope)
40
+ envelope.reject! ActorTerminated.new(reference)
41
+ dead_letter_routing << envelope unless envelope.ivar
42
+ log Logging::DEBUG, "rejected #{envelope.message} from #{envelope.sender_path}"
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
48
+
@@ -0,0 +1,21 @@
1
+ module Concurrent
2
+ module Actor
3
+ module Behaviour
4
+
5
+ # Handles `:await` messages. Which allows to wait on Actor to process all previously send
6
+ # messages.
7
+ # @example
8
+ # actor << :a << :b
9
+ # actor.ask(:await).wait # blocks until :a and :b are processed
10
+ class Awaits < Abstract
11
+ def on_envelope(envelope)
12
+ if envelope.message == :await
13
+ true
14
+ else
15
+ pass envelope
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,54 @@
1
+ module Concurrent
2
+ module Actor
3
+ module Behaviour
4
+
5
+ # Any message reaching this behaviour is buffered. Only one message is is scheduled
6
+ # at any given time. Others are kept in buffer until another one can be scheduled.
7
+ # This effective means that messages handled by behaviours before buffer have higher priority
8
+ # and they can be processed before messages arriving into buffer. This allows to
9
+ # process internal actor messages like (`:link`, `:supervise`) processed first.
10
+ class Buffer < Abstract
11
+ def initialize(core, subsequent)
12
+ super core, subsequent
13
+ @buffer = []
14
+ @receive_envelope_scheduled = false
15
+ end
16
+
17
+ def on_envelope(envelope)
18
+ @buffer.push envelope
19
+ process_envelopes?
20
+ MESSAGE_PROCESSED
21
+ end
22
+
23
+ # Ensures that only one envelope processing is scheduled with #schedule_execution,
24
+ # this allows other scheduled blocks to be executed before next envelope processing.
25
+ # Simply put this ensures that Core is still responsive to internal calls (like add_child)
26
+ # even though the Actor is flooded with messages.
27
+ def process_envelopes?
28
+ unless @buffer.empty? || @receive_envelope_scheduled
29
+ @receive_envelope_scheduled = true
30
+ process_envelope
31
+ end
32
+ end
33
+
34
+ def process_envelope
35
+ envelope = @buffer.shift
36
+ return nil unless envelope
37
+ pass envelope
38
+ ensure
39
+ @receive_envelope_scheduled = false
40
+ core.schedule_execution { process_envelopes? }
41
+ end
42
+
43
+ def on_event(event)
44
+ case event
45
+ when :terminated, :restarted
46
+ @buffer.each { |envelope| reject_envelope envelope }
47
+ @buffer.clear
48
+ end
49
+ super event
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,12 @@
1
+ module Concurrent
2
+ module Actor
3
+ module Behaviour
4
+ # Simply fails when message arrives here.
5
+ class ErrorsOnUnknownMessage < Abstract
6
+ def on_envelope(envelope)
7
+ raise UnknownMessage, envelope
8
+ end
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,18 @@
1
+ module Concurrent
2
+ module Actor
3
+ module Behaviour
4
+ # Delegates messages and events to {AbstractContext} instance
5
+ class ExecutesContext < Abstract
6
+ def on_envelope(envelope)
7
+ context.on_envelope envelope
8
+ end
9
+
10
+ def on_event(event)
11
+ context.on_event(event)
12
+ core.log Logging::DEBUG, "event: #{event.inspect}"
13
+ super event
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,42 @@
1
+ module Concurrent
2
+ module Actor
3
+ module Behaviour
4
+
5
+ # Links the actor to other actors and sends events to them,
6
+ # like: `:terminated`, `:paused`, errors, etc
7
+ class Linking < Abstract
8
+ def initialize(core, subsequent)
9
+ super core, subsequent
10
+ @linked = Set.new
11
+ end
12
+
13
+ def on_envelope(envelope)
14
+ case envelope.message
15
+ when :link
16
+ link envelope.sender
17
+ when :unlink
18
+ unlink envelope.sender
19
+ else
20
+ pass envelope
21
+ end
22
+ end
23
+
24
+ def link(ref)
25
+ @linked.add(ref)
26
+ true
27
+ end
28
+
29
+ def unlink(ref)
30
+ @linked.delete(ref)
31
+ true
32
+ end
33
+
34
+ def on_event(event)
35
+ @linked.each { |a| a << event }
36
+ @linked.clear if event == :terminated
37
+ super event
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,77 @@
1
+ module Concurrent
2
+ module Actor
3
+ module Behaviour
4
+
5
+ # Allows to pause actors on errors.
6
+ # When paused all arriving messages are collected and processed after the actor
7
+ # is resumed or reset. Resume will simply continue with next message.
8
+ # Reset also reinitialized context. `:reset!` and `:resume!` messages are only accepted
9
+ # form supervisor, see Supervised behaviour.
10
+ class Pausing < Abstract
11
+ def initialize(core, subsequent)
12
+ super core, subsequent
13
+ @paused = false
14
+ @buffer = []
15
+ end
16
+
17
+ def on_envelope(envelope)
18
+ case envelope.message
19
+ when :pause!
20
+ pause!
21
+ when :resume!
22
+ resume!
23
+ when :reset!
24
+ reset!
25
+ when :restart!
26
+ restart!
27
+ else
28
+ if @paused
29
+ @buffer << envelope
30
+ MESSAGE_PROCESSED
31
+ else
32
+ pass envelope
33
+ end
34
+ end
35
+ end
36
+
37
+ def pause!(error = nil)
38
+ @paused = true
39
+ broadcast(error || :paused)
40
+ true
41
+ end
42
+
43
+ def resume!(broadcast = true)
44
+ @paused = false
45
+ broadcast(:resumed) if broadcast
46
+ true
47
+ end
48
+
49
+ def reset!(broadcast = true)
50
+ core.allocate_context
51
+ core.build_context
52
+ resume!(false)
53
+ broadcast(:reset) if broadcast
54
+ true
55
+ end
56
+
57
+ def restart!
58
+ reset! false
59
+ broadcast(:restarted)
60
+ true
61
+ end
62
+
63
+ def on_event(event)
64
+ case event
65
+ when :terminated, :restarted
66
+ @buffer.each { |envelope| reject_envelope envelope }
67
+ @buffer.clear
68
+ when :resumed, :reset
69
+ @buffer.each { |envelope| core.schedule_execution { pass envelope } }
70
+ @buffer.clear
71
+ end
72
+ super event
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,16 @@
1
+ module Concurrent
2
+ module Actor
3
+ module Behaviour
4
+ # Removes terminated children.
5
+ class RemovesChild < Abstract
6
+ def on_envelope(envelope)
7
+ if envelope.message == :remove_child
8
+ core.remove_child envelope.sender
9
+ else
10
+ pass envelope
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,36 @@
1
+ module Concurrent
2
+ module Actor
3
+ module Behaviour
4
+ # Collects returning value and sets the IVar in the {Envelope} or error on failure.
5
+ class SetResults < Abstract
6
+ attr_reader :error_strategy
7
+
8
+ def initialize(core, subsequent, error_strategy)
9
+ super core, subsequent
10
+ @error_strategy = Match! error_strategy, :just_log, :terminate!, :pause!
11
+ end
12
+
13
+ def on_envelope(envelope)
14
+ result = pass envelope
15
+ if result != MESSAGE_PROCESSED && !envelope.ivar.nil?
16
+ envelope.ivar.set result
17
+ end
18
+ nil
19
+ rescue => error
20
+ log Logging::ERROR, error
21
+ case error_strategy
22
+ when :terminate!
23
+ terminate!
24
+ when :pause!
25
+ behaviour!(Pausing).pause!(error)
26
+ when :just_log
27
+ # nothing
28
+ else
29
+ raise
30
+ end
31
+ envelope.ivar.fail error unless envelope.ivar.nil?
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,58 @@
1
+ module Concurrent
2
+ module Actor
3
+ module Behaviour
4
+
5
+ # Sets and holds the supervisor of the actor if any. There is at most one supervisor
6
+ # for each actor. Each supervisor is automatically linked.
7
+ class Supervised < Abstract
8
+ attr_reader :supervisor
9
+
10
+ def initialize(core, subsequent)
11
+ super core, subsequent
12
+ @supervisor = nil
13
+ end
14
+
15
+ def on_envelope(envelope)
16
+ case envelope.message
17
+ when :supervise
18
+ supervise envelope.sender
19
+ when :supervisor
20
+ supervisor
21
+ when :un_supervise
22
+ un_supervise envelope.sender
23
+ when :pause!, :resume!, :reset!, :restart!
24
+ # allow only supervisor to control the actor
25
+ if @supervisor == envelope.sender
26
+ pass envelope
27
+ else
28
+ false
29
+ end
30
+ else
31
+ pass envelope
32
+ end
33
+ end
34
+
35
+ def supervise(ref)
36
+ @supervisor = ref
37
+ behaviour!(Linking).link ref
38
+ true
39
+ end
40
+
41
+ def un_supervise(ref)
42
+ if @supervisor == ref
43
+ behaviour!(Linking).unlink ref
44
+ @supervisor = nil
45
+ true
46
+ else
47
+ false
48
+ end
49
+ end
50
+
51
+ def on_event(event)
52
+ @supervisor = nil if event == :terminated
53
+ super event
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,34 @@
1
+ module Concurrent
2
+ module Actor
3
+ module Behaviour
4
+ class Supervising < Abstract
5
+ def initialize(core, subsequent, handle, strategy)
6
+ super core, subsequent
7
+ @handle = Match! handle, :terminate!, :resume!, :reset!, :restart!
8
+ @strategy = case @handle
9
+ when :terminate!
10
+ Match! strategy, nil
11
+ when :resume!
12
+ Match! strategy, :one_for_one
13
+ when :reset!, :restart!
14
+ Match! strategy, :one_for_one, :one_for_all
15
+ end
16
+ end
17
+
18
+ def on_envelope(envelope)
19
+ case envelope.message
20
+ when Exception, :paused
21
+ receivers = if @strategy == :one_for_all
22
+ children
23
+ else
24
+ [envelope.sender]
25
+ end
26
+ receivers.each { |ch| ch << @handle }
27
+ else
28
+ pass envelope
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,13 @@
1
+ module Concurrent
2
+ module Actor
3
+ module Behaviour
4
+ # Terminates all children when the actor terminates.
5
+ class TerminatesChildren < Abstract
6
+ def on_event(event)
7
+ children.map { |ch| ch.ask :terminate! }.each(&:wait) if event == :terminated
8
+ super event
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end