concurrent-ruby-edge 0.3.1 → 0.7.0
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.
- checksums.yaml +5 -5
- data/CHANGELOG.md +552 -0
- data/LICENSE.txt +18 -18
- data/README.md +261 -103
- data/lib/{concurrent → concurrent-ruby-edge/concurrent}/actor/behaviour/abstract.rb +2 -0
- data/lib/{concurrent → concurrent-ruby-edge/concurrent}/actor/behaviour/awaits.rb +2 -0
- data/lib/{concurrent → concurrent-ruby-edge/concurrent}/actor/behaviour/buffer.rb +2 -0
- data/lib/{concurrent → concurrent-ruby-edge/concurrent}/actor/behaviour/errors_on_unknown_message.rb +2 -0
- data/lib/{concurrent → concurrent-ruby-edge/concurrent}/actor/behaviour/executes_context.rb +2 -0
- data/lib/{concurrent → concurrent-ruby-edge/concurrent}/actor/behaviour/linking.rb +2 -0
- data/lib/{concurrent → concurrent-ruby-edge/concurrent}/actor/behaviour/pausing.rb +2 -0
- data/lib/{concurrent → concurrent-ruby-edge/concurrent}/actor/behaviour/removes_child.rb +2 -0
- data/lib/{concurrent → concurrent-ruby-edge/concurrent}/actor/behaviour/sets_results.rb +2 -0
- data/lib/{concurrent → concurrent-ruby-edge/concurrent}/actor/behaviour/supervising.rb +2 -0
- data/lib/{concurrent → concurrent-ruby-edge/concurrent}/actor/behaviour/termination.rb +3 -1
- data/lib/{concurrent → concurrent-ruby-edge/concurrent}/actor/behaviour.rb +1 -1
- data/lib/{concurrent → concurrent-ruby-edge/concurrent}/actor/context.rb +3 -1
- data/lib/{concurrent → concurrent-ruby-edge/concurrent}/actor/core.rb +5 -4
- data/lib/{concurrent → concurrent-ruby-edge/concurrent}/actor/default_dead_letter_handler.rb +2 -0
- data/lib/{concurrent → concurrent-ruby-edge/concurrent}/actor/envelope.rb +2 -0
- data/lib/{concurrent → concurrent-ruby-edge/concurrent}/actor/errors.rb +2 -0
- data/lib/{concurrent → concurrent-ruby-edge/concurrent}/actor/internal_delegations.rb +3 -0
- data/lib/{concurrent → concurrent-ruby-edge/concurrent}/actor/reference.rb +9 -8
- data/lib/{concurrent → concurrent-ruby-edge/concurrent}/actor/root.rb +3 -0
- data/lib/{concurrent → concurrent-ruby-edge/concurrent}/actor/utils/ad_hoc.rb +2 -0
- data/lib/{concurrent → concurrent-ruby-edge/concurrent}/actor/utils/balancer.rb +2 -0
- data/lib/{concurrent → concurrent-ruby-edge/concurrent}/actor/utils/broadcast.rb +1 -0
- data/lib/{concurrent → concurrent-ruby-edge/concurrent}/actor/utils/pool.rb +1 -0
- data/lib/{concurrent → concurrent-ruby-edge/concurrent}/actor.rb +11 -6
- data/lib/{concurrent → concurrent-ruby-edge/concurrent}/channel/buffer/base.rb +14 -14
- data/lib/{concurrent → concurrent-ruby-edge/concurrent}/channel/buffer/dropping.rb +1 -0
- data/lib/{concurrent → concurrent-ruby-edge/concurrent}/channel/buffer/sliding.rb +1 -0
- data/lib/{concurrent → concurrent-ruby-edge/concurrent}/channel/buffer/unbuffered.rb +1 -1
- data/lib/{concurrent → concurrent-ruby-edge/concurrent}/channel/tick.rb +1 -1
- data/lib/{concurrent → concurrent-ruby-edge/concurrent}/channel.rb +3 -2
- data/lib/concurrent-ruby-edge/concurrent/edge/cancellation.rb +107 -0
- data/lib/concurrent-ruby-edge/concurrent/edge/channel.rb +453 -0
- data/lib/concurrent-ruby-edge/concurrent/edge/erlang_actor.rb +1549 -0
- data/lib/{concurrent → concurrent-ruby-edge/concurrent}/edge/lock_free_linked_set/node.rb +2 -2
- data/lib/{concurrent → concurrent-ruby-edge/concurrent}/edge/lock_free_linked_set.rb +8 -7
- data/lib/{concurrent → concurrent-ruby-edge/concurrent}/edge/lock_free_queue.rb +2 -0
- data/lib/{concurrent → concurrent-ruby-edge/concurrent}/edge/old_channel_integration.rb +2 -0
- data/lib/concurrent-ruby-edge/concurrent/edge/processing_actor.rb +184 -0
- data/lib/concurrent-ruby-edge/concurrent/edge/promises.rb +174 -0
- data/lib/concurrent-ruby-edge/concurrent/edge/throttle.rb +229 -0
- data/lib/concurrent-ruby-edge/concurrent/edge/version.rb +3 -0
- data/lib/concurrent-ruby-edge/concurrent/edge.rb +21 -0
- data/lib/concurrent-ruby-edge/concurrent/executor/wrapping_executor.rb +50 -0
- data/lib/concurrent-ruby-edge/concurrent/lazy_register.rb +83 -0
- data/lib/{concurrent-edge.rb → concurrent-ruby-edge/concurrent-edge.rb} +5 -4
- metadata +71 -67
- data/lib/concurrent/edge/atomic_markable_reference.rb +0 -184
- data/lib/concurrent/edge/cancellation.rb +0 -138
- data/lib/concurrent/edge/lock_free_stack.rb +0 -126
- data/lib/concurrent/edge/processing_actor.rb +0 -161
- data/lib/concurrent/edge/promises.rb +0 -2111
- data/lib/concurrent/edge/throttle.rb +0 -192
- /data/lib/{concurrent → concurrent-ruby-edge/concurrent}/actor/public_delegations.rb +0 -0
- /data/lib/{concurrent → concurrent-ruby-edge/concurrent}/actor/type_check.rb +0 -0
- /data/lib/{concurrent → concurrent-ruby-edge/concurrent}/actor/utils.rb +0 -0
- /data/lib/{concurrent → concurrent-ruby-edge/concurrent}/channel/buffer/buffered.rb +0 -0
- /data/lib/{concurrent → concurrent-ruby-edge/concurrent}/channel/buffer/ticker.rb +0 -0
- /data/lib/{concurrent → concurrent-ruby-edge/concurrent}/channel/buffer/timer.rb +0 -0
- /data/lib/{concurrent → concurrent-ruby-edge/concurrent}/channel/buffer.rb +0 -0
- /data/lib/{concurrent → concurrent-ruby-edge/concurrent}/channel/selector/after_clause.rb +0 -0
- /data/lib/{concurrent → concurrent-ruby-edge/concurrent}/channel/selector/default_clause.rb +0 -0
- /data/lib/{concurrent → concurrent-ruby-edge/concurrent}/channel/selector/error_clause.rb +0 -0
- /data/lib/{concurrent → concurrent-ruby-edge/concurrent}/channel/selector/put_clause.rb +0 -0
- /data/lib/{concurrent → concurrent-ruby-edge/concurrent}/channel/selector/take_clause.rb +0 -0
- /data/lib/{concurrent → concurrent-ruby-edge/concurrent}/channel/selector.rb +0 -0
- /data/lib/{concurrent → concurrent-ruby-edge/concurrent}/edge/lock_free_linked_set/window.rb +0 -0
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
require 'concurrent/actor/type_check'
|
|
2
|
+
require 'concurrent/actor/public_delegations'
|
|
3
|
+
|
|
1
4
|
module Concurrent
|
|
2
5
|
module Actor
|
|
3
6
|
|
|
@@ -35,12 +38,7 @@ module Concurrent
|
|
|
35
38
|
|
|
36
39
|
alias_method :<<, :tell
|
|
37
40
|
|
|
38
|
-
# @note it's a good practice to use tell whenever possible.
|
|
39
|
-
# testing and when it returns very shortly. It can lead to deadlock if all threads in
|
|
40
|
-
# global_io_executor will block on while asking. It's fine to use it form outside of actors and
|
|
41
|
-
# global_io_executor.
|
|
42
|
-
#
|
|
43
|
-
# @note it's a good practice to use {#tell} whenever possible. Results can be send back with other messages.
|
|
41
|
+
# @note it's a good practice to use {#tell} whenever possible. Results can be sent back with other messages.
|
|
44
42
|
# Ask should be used only for testing and when it returns very shortly. It can lead to deadlock if all threads in
|
|
45
43
|
# global_io_executor will block on while asking. It's fine to use it form outside of actors and
|
|
46
44
|
# global_io_executor.
|
|
@@ -55,10 +53,13 @@ module Concurrent
|
|
|
55
53
|
message message, future
|
|
56
54
|
end
|
|
57
55
|
|
|
56
|
+
# @!visibility privated
|
|
57
|
+
alias_method :ask_op, :ask
|
|
58
|
+
|
|
58
59
|
# Sends the message synchronously and blocks until the message
|
|
59
60
|
# is processed. Raises on error.
|
|
60
61
|
#
|
|
61
|
-
# @note it's a good practice to use {#tell} whenever possible. Results can be
|
|
62
|
+
# @note it's a good practice to use {#tell} whenever possible. Results can be sent back with other messages.
|
|
62
63
|
# Ask should be used only for testing and when it returns very shortly. It can lead to deadlock if all threads in
|
|
63
64
|
# global_io_executor will block on while asking. It's fine to use it form outside of actors and
|
|
64
65
|
# global_io_executor.
|
|
@@ -89,7 +90,7 @@ module Concurrent
|
|
|
89
90
|
end
|
|
90
91
|
|
|
91
92
|
def to_s
|
|
92
|
-
|
|
93
|
+
format '%s %s (%s)>', super[0..-2], path, actor_class
|
|
93
94
|
end
|
|
94
95
|
|
|
95
96
|
alias_method :inspect, :to_s
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
# NOTE: finer grained than require 'concurrent/actor' not supported
|
|
2
|
+
|
|
1
3
|
require 'concurrent/configuration'
|
|
2
4
|
require 'concurrent/executor/serialized_execution'
|
|
3
|
-
require 'concurrent/synchronization'
|
|
4
5
|
require 'concurrent/edge/promises'
|
|
5
6
|
|
|
6
7
|
module Concurrent
|
|
@@ -10,9 +11,9 @@ module Concurrent
|
|
|
10
11
|
# TODO supervision tree, pause children on error in parent, pause may need higher priority
|
|
11
12
|
# TODO more effective executor
|
|
12
13
|
|
|
13
|
-
# {include:file:
|
|
14
|
+
# {include:file:docs-source/actor/main.md}
|
|
14
15
|
# @api Actor
|
|
15
|
-
# @!macro
|
|
16
|
+
# @!macro warn.edge
|
|
16
17
|
module Actor
|
|
17
18
|
|
|
18
19
|
require 'concurrent/actor/type_check'
|
|
@@ -35,9 +36,13 @@ module Concurrent
|
|
|
35
36
|
end
|
|
36
37
|
|
|
37
38
|
@root = Concurrent::Promises.delay do
|
|
38
|
-
Core.
|
|
39
|
-
|
|
40
|
-
|
|
39
|
+
Core.
|
|
40
|
+
new(parent: nil,
|
|
41
|
+
name: '/',
|
|
42
|
+
class: Root,
|
|
43
|
+
initialized: future = Concurrent::Promises.resolvable_future).
|
|
44
|
+
reference.
|
|
45
|
+
tap { future.wait! }
|
|
41
46
|
end
|
|
42
47
|
|
|
43
48
|
# A root actor, a default parent of all actors spawned outside an actor
|
|
@@ -15,13 +15,13 @@ module Concurrent
|
|
|
15
15
|
# used as a channel buffer should extend this class.
|
|
16
16
|
class Base < Synchronization::LockableObject
|
|
17
17
|
|
|
18
|
-
# @!macro
|
|
18
|
+
# @!macro channel_buffer_capacity_reader
|
|
19
19
|
#
|
|
20
20
|
# The maximum number of values which can be {#put} onto the buffer
|
|
21
21
|
# it becomes full.
|
|
22
22
|
attr_reader :capacity
|
|
23
23
|
|
|
24
|
-
# @!macro
|
|
24
|
+
# @!macro channel_buffer_initialize
|
|
25
25
|
#
|
|
26
26
|
# Creates a new buffer.
|
|
27
27
|
def initialize(*args)
|
|
@@ -35,7 +35,7 @@ module Concurrent
|
|
|
35
35
|
end
|
|
36
36
|
end
|
|
37
37
|
|
|
38
|
-
# @!macro
|
|
38
|
+
# @!macro channel_buffer_blocking_question
|
|
39
39
|
#
|
|
40
40
|
# Predicate indicating if this buffer will block {#put} operations
|
|
41
41
|
# once it reaches its maximum capacity.
|
|
@@ -45,14 +45,14 @@ module Concurrent
|
|
|
45
45
|
true
|
|
46
46
|
end
|
|
47
47
|
|
|
48
|
-
# @!macro
|
|
48
|
+
# @!macro channel_buffer_size_reader
|
|
49
49
|
#
|
|
50
50
|
# The number of items currently in the buffer.
|
|
51
51
|
def size
|
|
52
52
|
synchronize { ns_size }
|
|
53
53
|
end
|
|
54
54
|
|
|
55
|
-
# @!macro
|
|
55
|
+
# @!macro channel_buffer_empty_question
|
|
56
56
|
#
|
|
57
57
|
# Predicate indicating if the buffer is empty.
|
|
58
58
|
#
|
|
@@ -63,7 +63,7 @@ module Concurrent
|
|
|
63
63
|
synchronize { ns_empty? }
|
|
64
64
|
end
|
|
65
65
|
|
|
66
|
-
# @!macro
|
|
66
|
+
# @!macro channel_buffer_full_question
|
|
67
67
|
#
|
|
68
68
|
# Predicate indicating if the buffer is full.
|
|
69
69
|
#
|
|
@@ -74,7 +74,7 @@ module Concurrent
|
|
|
74
74
|
synchronize { ns_full? }
|
|
75
75
|
end
|
|
76
76
|
|
|
77
|
-
# @!macro
|
|
77
|
+
# @!macro channel_buffer_put
|
|
78
78
|
#
|
|
79
79
|
# Put an item onto the buffer if possible. If the buffer is open
|
|
80
80
|
# but not able to accept the item the calling thread will block
|
|
@@ -89,9 +89,9 @@ module Concurrent
|
|
|
89
89
|
raise NotImplementedError
|
|
90
90
|
end
|
|
91
91
|
|
|
92
|
-
# @!macro
|
|
92
|
+
# @!macro channel_buffer_offer
|
|
93
93
|
#
|
|
94
|
-
# Put an item onto the buffer
|
|
94
|
+
# Put an item onto the buffer if possible. If the buffer is open but
|
|
95
95
|
# unable to add an item, probably due to being full, the method will
|
|
96
96
|
# return immediately. Similarly, the method will return immediately
|
|
97
97
|
# when the buffer is closed. A return value of `false` does not
|
|
@@ -107,7 +107,7 @@ module Concurrent
|
|
|
107
107
|
raise NotImplementedError
|
|
108
108
|
end
|
|
109
109
|
|
|
110
|
-
# @!macro
|
|
110
|
+
# @!macro channel_buffer_take
|
|
111
111
|
#
|
|
112
112
|
# Take an item from the buffer if one is available. If the buffer
|
|
113
113
|
# is open and no item is available the calling thread will block
|
|
@@ -123,7 +123,7 @@ module Concurrent
|
|
|
123
123
|
raise NotImplementedError
|
|
124
124
|
end
|
|
125
125
|
|
|
126
|
-
# @!macro
|
|
126
|
+
# @!macro channel_buffer_next
|
|
127
127
|
#
|
|
128
128
|
# Take the next "item" from the buffer and also return a boolean
|
|
129
129
|
# indicating if "more" items can be taken. Used for iterating
|
|
@@ -152,7 +152,7 @@ module Concurrent
|
|
|
152
152
|
raise NotImplementedError
|
|
153
153
|
end
|
|
154
154
|
|
|
155
|
-
# @!macro
|
|
155
|
+
# @!macro channel_buffer_poll
|
|
156
156
|
#
|
|
157
157
|
# Take the next item from the buffer if one is available else return
|
|
158
158
|
# immediately. Failing to return a value does not necessarily
|
|
@@ -166,7 +166,7 @@ module Concurrent
|
|
|
166
166
|
raise NotImplementedError
|
|
167
167
|
end
|
|
168
168
|
|
|
169
|
-
# @!macro
|
|
169
|
+
# @!macro channel_buffer_close
|
|
170
170
|
#
|
|
171
171
|
# Close the buffer, preventing new items from being added. Once a
|
|
172
172
|
# buffer is closed it cannot be opened again.
|
|
@@ -179,7 +179,7 @@ module Concurrent
|
|
|
179
179
|
end
|
|
180
180
|
end
|
|
181
181
|
|
|
182
|
-
# @!macro
|
|
182
|
+
# @!macro channel_buffer_closed_question
|
|
183
183
|
#
|
|
184
184
|
# Predicate indicating is this buffer closed.
|
|
185
185
|
#
|
|
@@ -8,13 +8,14 @@ require 'concurrent/executor/cached_thread_pool'
|
|
|
8
8
|
|
|
9
9
|
module Concurrent
|
|
10
10
|
|
|
11
|
-
# {include:file:
|
|
11
|
+
# {include:file:docs-source/channel.md}
|
|
12
|
+
# @!macro warn.edge
|
|
12
13
|
class Channel
|
|
13
14
|
extend Forwardable
|
|
14
15
|
include Enumerable
|
|
15
16
|
|
|
16
17
|
# NOTE: Move to global IO pool once stable
|
|
17
|
-
GOROUTINES = Concurrent::CachedThreadPool.new
|
|
18
|
+
GOROUTINES = Concurrent::CachedThreadPool.new
|
|
18
19
|
private_constant :GOROUTINES
|
|
19
20
|
|
|
20
21
|
BUFFER_TYPES = {
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
require 'concurrent/concern/deprecation'
|
|
2
|
+
require 'concurrent/synchronization/object'
|
|
3
|
+
require 'concurrent/promises'
|
|
4
|
+
|
|
5
|
+
module Concurrent
|
|
6
|
+
|
|
7
|
+
# TODO (pitr-ch 27-Mar-2016): cooperation with mutex, condition, select etc?
|
|
8
|
+
# TODO (pitr-ch 10-Dec-2018): integrate with enumerator?
|
|
9
|
+
# token.cancelable(array.each_with_index).each do |v, i|
|
|
10
|
+
# # stops iterating when cancelled
|
|
11
|
+
# end
|
|
12
|
+
# token.cancelable(array).each_with_index do |v, i|
|
|
13
|
+
# # stops iterating when cancelled
|
|
14
|
+
# end
|
|
15
|
+
|
|
16
|
+
# The Cancellation abstraction provides cooperative cancellation.
|
|
17
|
+
#
|
|
18
|
+
# The standard methods `Thread#raise` of `Thread#kill` available in Ruby
|
|
19
|
+
# are very dangerous (see linked the blog posts bellow).
|
|
20
|
+
# Therefore concurrent-ruby provides an alternative.
|
|
21
|
+
# * <https://jvns.ca/blog/2015/11/27/why-rubys-timeout-is-dangerous-and-thread-dot-raise-is-terrifying/>
|
|
22
|
+
# * <http://www.mikeperham.com/2015/05/08/timeout-rubys-most-dangerous-api/>
|
|
23
|
+
# * <http://blog.headius.com/2008/02/rubys-threadraise-threadkill-timeoutrb.html>
|
|
24
|
+
#
|
|
25
|
+
# It provides an object which represents a task which can be executed,
|
|
26
|
+
# the task has to get the reference to the object and periodically cooperatively check that it is not cancelled.
|
|
27
|
+
# Good practices to make tasks cancellable:
|
|
28
|
+
# * check cancellation every cycle of a loop which does significant work,
|
|
29
|
+
# * do all blocking actions in a loop with a timeout then on timeout check cancellation
|
|
30
|
+
# and if ok block again with the timeout
|
|
31
|
+
#
|
|
32
|
+
# The idea was inspired by <https://msdn.microsoft.com/en-us/library/dd537607(v=vs.110).aspx>
|
|
33
|
+
# @!macro warn.edge
|
|
34
|
+
#
|
|
35
|
+
# {include:file:docs-source/cancellation.out.md}
|
|
36
|
+
class Cancellation < Synchronization::Object
|
|
37
|
+
safe_initialization!
|
|
38
|
+
|
|
39
|
+
# Create Cancellation which will cancel itself in given time
|
|
40
|
+
#
|
|
41
|
+
# @!macro promises.param.intended_time
|
|
42
|
+
# @return [Cancellation]
|
|
43
|
+
def self.timeout(intended_time)
|
|
44
|
+
new Concurrent::Promises.schedule(intended_time)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Creates the cancellation object.
|
|
48
|
+
#
|
|
49
|
+
# @param [Promises::Future, Promises::Event] origin of the cancellation.
|
|
50
|
+
# When it is resolved the cancellation is canceled.
|
|
51
|
+
# @example
|
|
52
|
+
# cancellation, origin = Concurrent::Cancellation.new
|
|
53
|
+
# @see #to_ary
|
|
54
|
+
def initialize(origin = Promises.resolvable_event)
|
|
55
|
+
super()
|
|
56
|
+
@Origin = origin
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# Allow to multi-assign the Cancellation object
|
|
60
|
+
# @return [Array(Cancellation, Promises::Future), Array(Cancellation, Promises::Event)]
|
|
61
|
+
# @example
|
|
62
|
+
# cancellation = Concurrent::Cancellation.new
|
|
63
|
+
# cancellation, origin = Concurrent::Cancellation.new
|
|
64
|
+
def to_ary
|
|
65
|
+
[self, @Origin]
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# The event or future which is the origin of the cancellation
|
|
69
|
+
# @return [Promises::Future, Promises::Event]
|
|
70
|
+
def origin
|
|
71
|
+
@Origin
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# Is the cancellation cancelled?
|
|
75
|
+
# Respective, was the origin of the cancellation resolved.
|
|
76
|
+
# @return [true, false]
|
|
77
|
+
def canceled?
|
|
78
|
+
@Origin.resolved?
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# Raise error when cancelled
|
|
82
|
+
# @param [#exception] error to be risen
|
|
83
|
+
# @raise the error
|
|
84
|
+
# @return [self]
|
|
85
|
+
def check!(error = CancelledOperationError)
|
|
86
|
+
raise error if canceled?
|
|
87
|
+
self
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
# Creates a new Cancellation which is cancelled when first
|
|
91
|
+
# of the supplied cancellations or self is cancelled.
|
|
92
|
+
#
|
|
93
|
+
# @param [Cancellation] cancellations to combine
|
|
94
|
+
# @return [Cancellation] new cancellation
|
|
95
|
+
def join(*cancellations)
|
|
96
|
+
Cancellation.new Promises.any_event(*[@Origin, *cancellations.map(&:origin)])
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
# Short string representation.
|
|
100
|
+
# @return [String]
|
|
101
|
+
def to_s
|
|
102
|
+
format '%s %s>', super[0..-2], canceled? ? 'canceled' : 'pending'
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
alias_method :inspect, :to_s
|
|
106
|
+
end
|
|
107
|
+
end
|