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,192 +0,0 @@
|
|
|
1
|
-
module Concurrent
|
|
2
|
-
# @!macro [new] throttle.example.throttled_block
|
|
3
|
-
# @example
|
|
4
|
-
# max_two = Throttle.new 2
|
|
5
|
-
# 10.times.map do
|
|
6
|
-
# Thread.new do
|
|
7
|
-
# max_two.throttled_block do
|
|
8
|
-
# # Only 2 at the same time
|
|
9
|
-
# do_stuff
|
|
10
|
-
# end
|
|
11
|
-
# end
|
|
12
|
-
# end
|
|
13
|
-
# @!macro [new] throttle.example.throttled_future
|
|
14
|
-
# @example
|
|
15
|
-
# throttle.throttled_future(1) do |arg|
|
|
16
|
-
# arg.succ
|
|
17
|
-
# end
|
|
18
|
-
# @!macro [new] throttle.example.throttled_future_chain
|
|
19
|
-
# @example
|
|
20
|
-
# throttle.throttled_future_chain do |trigger|
|
|
21
|
-
# trigger.
|
|
22
|
-
# # 2 throttled promises
|
|
23
|
-
# chain { 1 }.
|
|
24
|
-
# then(&:succ)
|
|
25
|
-
# end
|
|
26
|
-
# @!macro [new] throttle.example.then_throttled_by
|
|
27
|
-
# @example
|
|
28
|
-
# data = (1..5).to_a
|
|
29
|
-
# db = data.reduce({}) { |h, v| h.update v => v.to_s }
|
|
30
|
-
# max_two = Throttle.new 2
|
|
31
|
-
#
|
|
32
|
-
# futures = data.map do |data|
|
|
33
|
-
# Promises.future(data) do |data|
|
|
34
|
-
# # un-throttled, concurrency level equal data.size
|
|
35
|
-
# data + 1
|
|
36
|
-
# end.then_throttled_by(max_two, db) do |v, db|
|
|
37
|
-
# # throttled, only 2 tasks executed at the same time
|
|
38
|
-
# # e.g. limiting access to db
|
|
39
|
-
# db[v]
|
|
40
|
-
# end
|
|
41
|
-
# end
|
|
42
|
-
#
|
|
43
|
-
# futures.map(&:value!) # => [2, 3, 4, 5, nil]
|
|
44
|
-
|
|
45
|
-
# A tool manage concurrency level of future tasks.
|
|
46
|
-
#
|
|
47
|
-
# @!macro throttle.example.then_throttled_by
|
|
48
|
-
# @!macro throttle.example.throttled_future
|
|
49
|
-
# @!macro throttle.example.throttled_future_chain
|
|
50
|
-
# @!macro throttle.example.throttled_block
|
|
51
|
-
class Throttle < Synchronization::Object
|
|
52
|
-
# TODO (pitr-ch 21-Dec-2016): consider using sized channel for implementation instead when available
|
|
53
|
-
|
|
54
|
-
safe_initialization!
|
|
55
|
-
private *attr_atomic(:can_run)
|
|
56
|
-
|
|
57
|
-
# New throttle.
|
|
58
|
-
# @param [Integer] limit
|
|
59
|
-
def initialize(limit)
|
|
60
|
-
super()
|
|
61
|
-
@Limit = limit
|
|
62
|
-
self.can_run = limit
|
|
63
|
-
@Queue = LockFreeQueue.new
|
|
64
|
-
end
|
|
65
|
-
|
|
66
|
-
# @return [Integer] The limit.
|
|
67
|
-
def limit
|
|
68
|
-
@Limit
|
|
69
|
-
end
|
|
70
|
-
|
|
71
|
-
# New event which will be resolved when depending tasks can execute.
|
|
72
|
-
# Has to be used and after the critical work is done {#release} must be called exactly once.
|
|
73
|
-
# @return [Promises::Event]
|
|
74
|
-
# @see #release
|
|
75
|
-
def trigger
|
|
76
|
-
while true
|
|
77
|
-
current_can_run = can_run
|
|
78
|
-
if compare_and_set_can_run current_can_run, current_can_run - 1
|
|
79
|
-
if current_can_run > 0
|
|
80
|
-
return Promises.resolved_event
|
|
81
|
-
else
|
|
82
|
-
event = Promises.resolvable_event
|
|
83
|
-
@Queue.push event
|
|
84
|
-
return event
|
|
85
|
-
end
|
|
86
|
-
end
|
|
87
|
-
end
|
|
88
|
-
end
|
|
89
|
-
|
|
90
|
-
# Has to be called once for each trigger after it is ok to execute another throttled task.
|
|
91
|
-
# @return [self]
|
|
92
|
-
# @see #trigger
|
|
93
|
-
def release
|
|
94
|
-
while true
|
|
95
|
-
current_can_run = can_run
|
|
96
|
-
if compare_and_set_can_run current_can_run, current_can_run + 1
|
|
97
|
-
if current_can_run < 0
|
|
98
|
-
Thread.pass until (trigger = @Queue.pop)
|
|
99
|
-
trigger.resolve
|
|
100
|
-
end
|
|
101
|
-
return self
|
|
102
|
-
end
|
|
103
|
-
end
|
|
104
|
-
end
|
|
105
|
-
|
|
106
|
-
# Blocks current thread until the block can be executed.
|
|
107
|
-
# @yield to throttled block
|
|
108
|
-
# @yieldreturn [Object] is used as a result of the method
|
|
109
|
-
# @return [Object] the result of the block
|
|
110
|
-
# @!macro throttle.example.throttled_block
|
|
111
|
-
def throttled_block(&block)
|
|
112
|
-
trigger.wait
|
|
113
|
-
block.call
|
|
114
|
-
ensure
|
|
115
|
-
release
|
|
116
|
-
end
|
|
117
|
-
|
|
118
|
-
# @return [String] Short string representation.
|
|
119
|
-
def to_s
|
|
120
|
-
format '<#%s:0x%x limit:%s can_run:%d>', self.class, object_id << 1, @Limit, can_run
|
|
121
|
-
end
|
|
122
|
-
|
|
123
|
-
alias_method :inspect, :to_s
|
|
124
|
-
|
|
125
|
-
module PromisesIntegration
|
|
126
|
-
|
|
127
|
-
# Allows to throttle a chain of promises.
|
|
128
|
-
# @yield [trigger] a trigger which has to be used to build up a chain of promises, the last one is result
|
|
129
|
-
# of the block. When the last one resolves, {Throttle#release} is called on the throttle.
|
|
130
|
-
# @yieldparam [Promises::Event, Promises::Future] trigger
|
|
131
|
-
# @yieldreturn [Promises::Event, Promises::Future] The final future of the throttled chain.
|
|
132
|
-
# @return [Promises::Event, Promises::Future] The final future of the throttled chain.
|
|
133
|
-
# @!macro throttle.example.throttled_future_chain
|
|
134
|
-
def throttled_future_chain(&throttled_futures)
|
|
135
|
-
throttled_futures.call(trigger).on_resolution! { release }
|
|
136
|
-
end
|
|
137
|
-
|
|
138
|
-
# Behaves as {Promises::FactoryMethods#future} but the future is throttled.
|
|
139
|
-
# @return [Promises::Future]
|
|
140
|
-
# @see Promises::FactoryMethods#future
|
|
141
|
-
# @!macro throttle.example.throttled_future
|
|
142
|
-
def throttled_future(*args, &task)
|
|
143
|
-
trigger.chain(*args, &task).on_resolution! { release }
|
|
144
|
-
end
|
|
145
|
-
end
|
|
146
|
-
|
|
147
|
-
include PromisesIntegration
|
|
148
|
-
end
|
|
149
|
-
|
|
150
|
-
module Promises
|
|
151
|
-
|
|
152
|
-
class AbstractEventFuture < Synchronization::Object
|
|
153
|
-
module ThrottleIntegration
|
|
154
|
-
def throttled_by(throttle, &throttled_futures)
|
|
155
|
-
a_trigger = self & self.chain { throttle.trigger }.flat_event
|
|
156
|
-
throttled_futures.call(a_trigger).on_resolution! { throttle.release }
|
|
157
|
-
end
|
|
158
|
-
|
|
159
|
-
# Behaves as {Promises::AbstractEventFuture#chain} but the it is throttled.
|
|
160
|
-
# @return [Promises::Future, Promises::Event]
|
|
161
|
-
# @see Promises::AbstractEventFuture#chain
|
|
162
|
-
def chain_throttled_by(throttle, *args, &block)
|
|
163
|
-
throttled_by(throttle) { |trigger| trigger.chain(*args, &block) }
|
|
164
|
-
end
|
|
165
|
-
end
|
|
166
|
-
|
|
167
|
-
include ThrottleIntegration
|
|
168
|
-
end
|
|
169
|
-
|
|
170
|
-
class Future < AbstractEventFuture
|
|
171
|
-
module ThrottleIntegration
|
|
172
|
-
|
|
173
|
-
# Behaves as {Promises::Future#then} but the it is throttled.
|
|
174
|
-
# @return [Promises::Future]
|
|
175
|
-
# @see Promises::Future#then
|
|
176
|
-
# @!macro throttle.example.then_throttled_by
|
|
177
|
-
def then_throttled_by(throttle, *args, &block)
|
|
178
|
-
throttled_by(throttle) { |trigger| trigger.then(*args, &block) }
|
|
179
|
-
end
|
|
180
|
-
|
|
181
|
-
# Behaves as {Promises::Future#rescue} but the it is throttled.
|
|
182
|
-
# @return [Promises::Future]
|
|
183
|
-
# @see Promises::Future#rescue
|
|
184
|
-
def rescue_throttled_by(throttle, *args, &block)
|
|
185
|
-
throttled_by(throttle) { |trigger| trigger.rescue(*args, &block) }
|
|
186
|
-
end
|
|
187
|
-
end
|
|
188
|
-
|
|
189
|
-
include ThrottleIntegration
|
|
190
|
-
end
|
|
191
|
-
end
|
|
192
|
-
end
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
/data/lib/{concurrent → concurrent-ruby-edge/concurrent}/edge/lock_free_linked_set/window.rb
RENAMED
|
File without changes
|