concurrent-ruby 0.8.0 → 0.9.0.pre2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (144) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +97 -2
  3. data/README.md +103 -54
  4. data/lib/concurrent.rb +34 -14
  5. data/lib/concurrent/async.rb +164 -50
  6. data/lib/concurrent/atom.rb +171 -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 +3 -0
  19. data/lib/concurrent/atomic_reference/jruby.rb +6 -3
  20. data/lib/concurrent/atomic_reference/mutex_atomic.rb +10 -32
  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 +27 -0
  29. data/lib/concurrent/concern/dereferenceable.rb +88 -0
  30. data/lib/concurrent/concern/logging.rb +25 -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 +226 -112
  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 +10 -0
  38. data/lib/concurrent/exchanger.rb +25 -1
  39. data/lib/concurrent/executor/cached_thread_pool.rb +46 -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 +206 -26
  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_cached_thread_pool.rb +18 -16
  46. data/lib/concurrent/executor/java_fixed_thread_pool.rb +11 -18
  47. data/lib/concurrent/executor/java_single_thread_executor.rb +17 -16
  48. data/lib/concurrent/executor/java_thread_pool_executor.rb +55 -102
  49. data/lib/concurrent/executor/ruby_cached_thread_pool.rb +9 -18
  50. data/lib/concurrent/executor/ruby_fixed_thread_pool.rb +10 -21
  51. data/lib/concurrent/executor/ruby_single_thread_executor.rb +14 -16
  52. data/lib/concurrent/executor/ruby_thread_pool_executor.rb +250 -166
  53. data/lib/concurrent/executor/safe_task_executor.rb +5 -4
  54. data/lib/concurrent/executor/serialized_execution.rb +22 -18
  55. data/lib/concurrent/executor/{per_thread_executor.rb → simple_executor_service.rb} +29 -20
  56. data/lib/concurrent/executor/single_thread_executor.rb +32 -21
  57. data/lib/concurrent/executor/thread_pool_executor.rb +72 -60
  58. data/lib/concurrent/executor/timer_set.rb +96 -84
  59. data/lib/concurrent/executors.rb +1 -1
  60. data/lib/concurrent/future.rb +70 -38
  61. data/lib/concurrent/immutable_struct.rb +89 -0
  62. data/lib/concurrent/ivar.rb +152 -60
  63. data/lib/concurrent/lazy_register.rb +40 -20
  64. data/lib/concurrent/maybe.rb +226 -0
  65. data/lib/concurrent/mutable_struct.rb +227 -0
  66. data/lib/concurrent/mvar.rb +44 -43
  67. data/lib/concurrent/promise.rb +208 -134
  68. data/lib/concurrent/scheduled_task.rb +339 -43
  69. data/lib/concurrent/settable_struct.rb +127 -0
  70. data/lib/concurrent/synchronization.rb +17 -0
  71. data/lib/concurrent/synchronization/abstract_object.rb +163 -0
  72. data/lib/concurrent/synchronization/abstract_struct.rb +158 -0
  73. data/lib/concurrent/synchronization/condition.rb +53 -0
  74. data/lib/concurrent/synchronization/java_object.rb +35 -0
  75. data/lib/concurrent/synchronization/lock.rb +32 -0
  76. data/lib/concurrent/synchronization/monitor_object.rb +24 -0
  77. data/lib/concurrent/synchronization/mutex_object.rb +43 -0
  78. data/lib/concurrent/synchronization/object.rb +78 -0
  79. data/lib/concurrent/synchronization/rbx_object.rb +75 -0
  80. data/lib/concurrent/timer_task.rb +87 -100
  81. data/lib/concurrent/tvar.rb +42 -38
  82. data/lib/concurrent/utilities.rb +3 -1
  83. data/lib/concurrent/utility/at_exit.rb +97 -0
  84. data/lib/concurrent/utility/engine.rb +40 -0
  85. data/lib/concurrent/utility/monotonic_time.rb +59 -0
  86. data/lib/concurrent/utility/native_extension_loader.rb +56 -0
  87. data/lib/concurrent/utility/processor_counter.rb +156 -0
  88. data/lib/concurrent/utility/timeout.rb +18 -14
  89. data/lib/concurrent/utility/timer.rb +11 -6
  90. data/lib/concurrent/version.rb +2 -1
  91. data/lib/concurrent_ruby.rb +1 -0
  92. metadata +47 -83
  93. data/lib/concurrent/actor.rb +0 -103
  94. data/lib/concurrent/actor/behaviour.rb +0 -70
  95. data/lib/concurrent/actor/behaviour/abstract.rb +0 -48
  96. data/lib/concurrent/actor/behaviour/awaits.rb +0 -21
  97. data/lib/concurrent/actor/behaviour/buffer.rb +0 -54
  98. data/lib/concurrent/actor/behaviour/errors_on_unknown_message.rb +0 -12
  99. data/lib/concurrent/actor/behaviour/executes_context.rb +0 -18
  100. data/lib/concurrent/actor/behaviour/linking.rb +0 -45
  101. data/lib/concurrent/actor/behaviour/pausing.rb +0 -77
  102. data/lib/concurrent/actor/behaviour/removes_child.rb +0 -16
  103. data/lib/concurrent/actor/behaviour/sets_results.rb +0 -36
  104. data/lib/concurrent/actor/behaviour/supervised.rb +0 -59
  105. data/lib/concurrent/actor/behaviour/supervising.rb +0 -34
  106. data/lib/concurrent/actor/behaviour/terminates_children.rb +0 -13
  107. data/lib/concurrent/actor/behaviour/termination.rb +0 -54
  108. data/lib/concurrent/actor/context.rb +0 -154
  109. data/lib/concurrent/actor/core.rb +0 -217
  110. data/lib/concurrent/actor/default_dead_letter_handler.rb +0 -9
  111. data/lib/concurrent/actor/envelope.rb +0 -41
  112. data/lib/concurrent/actor/errors.rb +0 -27
  113. data/lib/concurrent/actor/internal_delegations.rb +0 -49
  114. data/lib/concurrent/actor/public_delegations.rb +0 -40
  115. data/lib/concurrent/actor/reference.rb +0 -81
  116. data/lib/concurrent/actor/root.rb +0 -37
  117. data/lib/concurrent/actor/type_check.rb +0 -48
  118. data/lib/concurrent/actor/utils.rb +0 -10
  119. data/lib/concurrent/actor/utils/ad_hoc.rb +0 -21
  120. data/lib/concurrent/actor/utils/balancer.rb +0 -42
  121. data/lib/concurrent/actor/utils/broadcast.rb +0 -52
  122. data/lib/concurrent/actor/utils/pool.rb +0 -59
  123. data/lib/concurrent/actress.rb +0 -3
  124. data/lib/concurrent/agent.rb +0 -209
  125. data/lib/concurrent/atomic.rb +0 -92
  126. data/lib/concurrent/atomic/copy_on_notify_observer_set.rb +0 -118
  127. data/lib/concurrent/atomic/copy_on_write_observer_set.rb +0 -117
  128. data/lib/concurrent/atomic/synchronization.rb +0 -51
  129. data/lib/concurrent/channel/buffered_channel.rb +0 -85
  130. data/lib/concurrent/channel/channel.rb +0 -41
  131. data/lib/concurrent/channel/unbuffered_channel.rb +0 -35
  132. data/lib/concurrent/channel/waitable_list.rb +0 -40
  133. data/lib/concurrent/channels.rb +0 -5
  134. data/lib/concurrent/collection/blocking_ring_buffer.rb +0 -71
  135. data/lib/concurrent/collection/ring_buffer.rb +0 -59
  136. data/lib/concurrent/collections.rb +0 -3
  137. data/lib/concurrent/dereferenceable.rb +0 -108
  138. data/lib/concurrent/executor/ruby_thread_pool_worker.rb +0 -73
  139. data/lib/concurrent/logging.rb +0 -20
  140. data/lib/concurrent/obligation.rb +0 -171
  141. data/lib/concurrent/observable.rb +0 -73
  142. data/lib/concurrent/options_parser.rb +0 -52
  143. data/lib/concurrent/utility/processor_count.rb +0 -152
  144. data/lib/extension_helper.rb +0 -37
@@ -1,48 +0,0 @@
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
-
@@ -1,21 +0,0 @@
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
@@ -1,54 +0,0 @@
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
@@ -1,12 +0,0 @@
1
- module Concurrent
2
- module Actor
3
- module Behaviour
4
- # Simply fails when message arrives here. It's usually the last behaviour.
5
- class ErrorsOnUnknownMessage < Abstract
6
- def on_envelope(envelope)
7
- raise UnknownMessage, envelope
8
- end
9
- end
10
- end
11
- end
12
- end
@@ -1,18 +0,0 @@
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
@@ -1,45 +0,0 @@
1
- module Concurrent
2
- module Actor
3
- module Behaviour
4
-
5
- # Links the actor to other actors and sends actor's events to them,
6
- # like: `:terminated`, `:paused`, errors, etc
7
- # TODO example
8
- class Linking < Abstract
9
- def initialize(core, subsequent)
10
- super core, subsequent
11
- @linked = Set.new
12
- end
13
-
14
- def on_envelope(envelope)
15
- case envelope.message
16
- when :link
17
- link envelope.sender
18
- when :unlink
19
- unlink envelope.sender
20
- when :linked?
21
- @linked.include? envelope.sender
22
- else
23
- pass envelope
24
- end
25
- end
26
-
27
- def link(ref)
28
- @linked.add(ref)
29
- true
30
- end
31
-
32
- def unlink(ref)
33
- @linked.delete(ref)
34
- true
35
- end
36
-
37
- def on_event(event)
38
- @linked.each { |a| a << event }
39
- @linked.clear if event == :terminated
40
- super event
41
- end
42
- end
43
- end
44
- end
45
- end
@@ -1,77 +0,0 @@
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.
9
- # TODO example
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
@@ -1,16 +0,0 @@
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
@@ -1,36 +0,0 @@
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
@@ -1,59 +0,0 @@
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. Messages:
7
- # `:pause!, :resume!, :reset!, :restart!` are accepted only from supervisor.
8
- class Supervised < Abstract
9
- attr_reader :supervisor
10
-
11
- def initialize(core, subsequent)
12
- super core, subsequent
13
- @supervisor = nil
14
- end
15
-
16
- def on_envelope(envelope)
17
- case envelope.message
18
- when :supervise
19
- supervise envelope.sender
20
- when :supervisor
21
- supervisor
22
- when :un_supervise
23
- un_supervise envelope.sender
24
- when :pause!, :resume!, :reset!, :restart!
25
- # allow only supervisor to control the actor
26
- if @supervisor == envelope.sender
27
- pass envelope
28
- else
29
- false
30
- end
31
- else
32
- pass envelope
33
- end
34
- end
35
-
36
- def supervise(ref)
37
- @supervisor = ref
38
- behaviour!(Linking).link ref
39
- true
40
- end
41
-
42
- def un_supervise(ref)
43
- if @supervisor == ref
44
- behaviour!(Linking).unlink ref
45
- @supervisor = nil
46
- true
47
- else
48
- false
49
- end
50
- end
51
-
52
- def on_event(event)
53
- @supervisor = nil if event == :terminated
54
- super event
55
- end
56
- end
57
- end
58
- end
59
- end
@@ -1,34 +0,0 @@
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
@@ -1,13 +0,0 @@
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