concurrent-ruby-edge 0.2.1 → 0.2.2
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 +4 -4
- data/lib/concurrent/edge/future.rb +88 -73
- metadata +5 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 20739acc38b2038d536762dc5655b68b0cde737c
|
4
|
+
data.tar.gz: 5c133ef27aedb2505479213aeb3beae3eb3a7f68
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 30ad063a0289862764c7ae0ca71318b606ee8f09a8537d0362f17cf35adf1d47eef5dce46950895bb5def9286f3e52133ecc4c4fea1f03a5626c6281b0f44123
|
7
|
+
data.tar.gz: 5e3e8a5c3e700878ad6c457ef5d90c557a608762a7a2a1eeb8105c032505d4210586d7424aa78a1566119dbea6531ebfd5044abad86155b4468ba43d7c664ff3
|
@@ -66,7 +66,7 @@ module Concurrent
|
|
66
66
|
# requested by calling `#wait`, `#value`, `#value!`, etc. on it or on any of the chained futures.
|
67
67
|
# @return [Future]
|
68
68
|
def delay(default_executor = :io, &task)
|
69
|
-
|
69
|
+
DelayPromise.new(default_executor).future.then(&task)
|
70
70
|
end
|
71
71
|
|
72
72
|
# Schedules the block to be executed on executor in given intended_time.
|
@@ -98,8 +98,18 @@ module Concurrent
|
|
98
98
|
# Constructs new {Future} which is completed after first of the futures is complete.
|
99
99
|
# @param [Event] futures
|
100
100
|
# @return [Future]
|
101
|
-
def
|
102
|
-
|
101
|
+
def any_complete(*futures)
|
102
|
+
AnyCompletePromise.new(futures, :io).future
|
103
|
+
end
|
104
|
+
|
105
|
+
alias_method :any, :any_complete
|
106
|
+
|
107
|
+
# Constructs new {Future} which becomes succeeded after first of the futures succeedes or
|
108
|
+
# failed if all futures fail (reason is last error).
|
109
|
+
# @param [Event] futures
|
110
|
+
# @return [Future]
|
111
|
+
def any_successful(*futures)
|
112
|
+
AnySuccessfulPromise.new(futures, :io).future
|
103
113
|
end
|
104
114
|
|
105
115
|
# only proof of concept
|
@@ -137,13 +147,11 @@ module Concurrent
|
|
137
147
|
# TODO allow to to have a zip point for many futures and process them in batches by 10
|
138
148
|
end
|
139
149
|
|
140
|
-
extend FutureShortcuts
|
141
|
-
include FutureShortcuts
|
142
|
-
|
143
150
|
# Represents an event which will happen in future (will be completed). It has to always happen.
|
144
|
-
class Event < Synchronization::
|
151
|
+
class Event < Synchronization::Object
|
145
152
|
safe_initialization!
|
146
153
|
private(*attr_atomic(:internal_state))
|
154
|
+
# @!visibility private
|
147
155
|
public :internal_state
|
148
156
|
include Concern::Deprecation
|
149
157
|
include Concern::Logging
|
@@ -188,13 +196,13 @@ module Concurrent
|
|
188
196
|
|
189
197
|
def initialize(promise, default_executor)
|
190
198
|
super()
|
199
|
+
@Lock = Mutex.new
|
200
|
+
@Condition = ConditionVariable.new
|
191
201
|
@Promise = promise
|
192
202
|
@DefaultExecutor = default_executor
|
193
|
-
@Touched = AtomicBoolean.new
|
203
|
+
@Touched = AtomicBoolean.new false
|
194
204
|
@Callbacks = LockFreeStack.new
|
195
|
-
|
196
|
-
# TODO (pitr 12-Sep-2015): look at java.util.concurrent solution
|
197
|
-
@Waiters = LockFreeStack.new
|
205
|
+
@Waiters = AtomicFixnum.new 0
|
198
206
|
self.internal_state = PENDING
|
199
207
|
end
|
200
208
|
|
@@ -276,7 +284,7 @@ module Concurrent
|
|
276
284
|
# Inserts delay into the chain of Futures making rest of it lazy evaluated.
|
277
285
|
# @return [Event]
|
278
286
|
def delay
|
279
|
-
ZipEventEventPromise.new(self,
|
287
|
+
ZipEventEventPromise.new(self, DelayPromise.new(@DefaultExecutor).event, @DefaultExecutor).event
|
280
288
|
end
|
281
289
|
|
282
290
|
# # Schedules rest of the chain for execution with specified time or on specified time
|
@@ -298,13 +306,13 @@ module Concurrent
|
|
298
306
|
# @yield [success, value, reason] executed async on `executor` when completed
|
299
307
|
# @return self
|
300
308
|
def on_completion(executor = nil, &callback)
|
301
|
-
add_callback :
|
309
|
+
add_callback :async_callback_on_completion, executor || @DefaultExecutor, callback
|
302
310
|
end
|
303
311
|
|
304
312
|
# @yield [success, value, reason] executed sync when completed
|
305
313
|
# @return self
|
306
314
|
def on_completion!(&callback)
|
307
|
-
add_callback :
|
315
|
+
add_callback :callback_on_completion, callback
|
308
316
|
end
|
309
317
|
|
310
318
|
# Changes default executor for rest of the chain
|
@@ -329,9 +337,8 @@ module Concurrent
|
|
329
337
|
# @!visibility private
|
330
338
|
def complete_with(state, raise_on_reassign = true)
|
331
339
|
if compare_and_set_internal_state(PENDING, state)
|
332
|
-
#(state)
|
333
340
|
# go to synchronized block only if there were waiting threads
|
334
|
-
synchronize {
|
341
|
+
@Lock.synchronize { @Condition.broadcast } unless @Waiters.value == 0
|
335
342
|
call_callbacks
|
336
343
|
else
|
337
344
|
Concurrent::MultipleAssignmentError.new('Event can be completed only once') if raise_on_reassign
|
@@ -388,32 +395,31 @@ module Concurrent
|
|
388
395
|
|
389
396
|
# @return [true, false]
|
390
397
|
def wait_until_complete(timeout)
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
# ok only if completing thread did not start signaling
|
398
|
-
next unless @Waiters.compare_and_push last_waiter, Thread.current
|
399
|
-
return ns_wait_until(timeout) { completed? }
|
398
|
+
return true if completed?
|
399
|
+
|
400
|
+
@Lock.synchronize do
|
401
|
+
@Waiters.increment
|
402
|
+
unless completed?
|
403
|
+
@Condition.wait @Lock, timeout
|
400
404
|
end
|
405
|
+
@Waiters.decrement
|
401
406
|
end
|
407
|
+
completed?
|
402
408
|
end
|
403
409
|
|
404
|
-
def
|
410
|
+
def with_async(executor, *args, &block)
|
405
411
|
Concurrent.post_on(executor, *args, &block)
|
406
412
|
end
|
407
413
|
|
408
|
-
def
|
409
|
-
|
414
|
+
def async_callback_on_completion(executor, callback)
|
415
|
+
with_async(executor) { callback_on_completion callback }
|
410
416
|
end
|
411
417
|
|
412
|
-
def
|
418
|
+
def callback_on_completion(callback)
|
413
419
|
callback.call
|
414
420
|
end
|
415
421
|
|
416
|
-
def
|
422
|
+
def callback_notify_blocked(promise)
|
417
423
|
promise.on_done self
|
418
424
|
end
|
419
425
|
|
@@ -660,13 +666,13 @@ module Concurrent
|
|
660
666
|
|
661
667
|
# @return [Future] which has first completed value from futures
|
662
668
|
def any(*futures)
|
663
|
-
|
669
|
+
AnyCompletePromise.new([self, *futures], @DefaultExecutor).future
|
664
670
|
end
|
665
671
|
|
666
672
|
# Inserts delay into the chain of Futures making rest of it lazy evaluated.
|
667
673
|
# @return [Future]
|
668
674
|
def delay
|
669
|
-
ZipFutureEventPromise.new(self,
|
675
|
+
ZipFutureEventPromise.new(self, DelayPromise.new(@DefaultExecutor).future, @DefaultExecutor).future
|
670
676
|
end
|
671
677
|
|
672
678
|
# Schedules rest of the chain for execution with specified time or on specified time
|
@@ -714,32 +720,32 @@ module Concurrent
|
|
714
720
|
# @yield [value] executed async on `executor` when success
|
715
721
|
# @return self
|
716
722
|
def on_success(executor = nil, &callback)
|
717
|
-
add_callback :
|
723
|
+
add_callback :async_callback_on_success, executor || @DefaultExecutor, callback
|
718
724
|
end
|
719
725
|
|
720
726
|
# @yield [reason] executed async on `executor` when failed?
|
721
727
|
# @return self
|
722
728
|
def on_failure(executor = nil, &callback)
|
723
|
-
add_callback :
|
729
|
+
add_callback :async_callback_on_failure, executor || @DefaultExecutor, callback
|
724
730
|
end
|
725
731
|
|
726
732
|
# @yield [value] executed sync when success
|
727
733
|
# @return self
|
728
734
|
def on_success!(&callback)
|
729
|
-
add_callback :
|
735
|
+
add_callback :callback_on_success, callback
|
730
736
|
end
|
731
737
|
|
732
738
|
# @yield [reason] executed sync when failed?
|
733
739
|
# @return self
|
734
740
|
def on_failure!(&callback)
|
735
|
-
add_callback :
|
741
|
+
add_callback :callback_on_failure, callback
|
736
742
|
end
|
737
743
|
|
738
744
|
# @!visibility private
|
739
745
|
def complete_with(state, raise_on_reassign = true)
|
740
746
|
if compare_and_set_internal_state(PENDING, state)
|
741
|
-
|
742
|
-
synchronize {
|
747
|
+
# go to synchronized block only if there were waiting threads
|
748
|
+
@Lock.synchronize { @Condition.broadcast } unless @Waiters.value == 0
|
743
749
|
call_callbacks state
|
744
750
|
else
|
745
751
|
if raise_on_reassign
|
@@ -792,37 +798,37 @@ module Concurrent
|
|
792
798
|
self.send method, state, *args
|
793
799
|
end
|
794
800
|
|
795
|
-
def
|
796
|
-
|
797
|
-
|
801
|
+
def async_callback_on_success(state, executor, callback)
|
802
|
+
with_async(executor, state, callback) do |st, cb|
|
803
|
+
callback_on_success st, cb
|
798
804
|
end
|
799
805
|
end
|
800
806
|
|
801
|
-
def
|
802
|
-
|
803
|
-
|
807
|
+
def async_callback_on_failure(state, executor, callback)
|
808
|
+
with_async(executor, state, callback) do |st, cb|
|
809
|
+
callback_on_failure st, cb
|
804
810
|
end
|
805
811
|
end
|
806
812
|
|
807
|
-
def
|
813
|
+
def callback_on_success(state, callback)
|
808
814
|
state.apply callback if state.success?
|
809
815
|
end
|
810
816
|
|
811
|
-
def
|
817
|
+
def callback_on_failure(state, callback)
|
812
818
|
state.apply callback unless state.success?
|
813
819
|
end
|
814
820
|
|
815
|
-
def
|
821
|
+
def callback_on_completion(state, callback)
|
816
822
|
callback.call state.result
|
817
823
|
end
|
818
824
|
|
819
|
-
def
|
825
|
+
def callback_notify_blocked(state, promise)
|
820
826
|
super(promise)
|
821
827
|
end
|
822
828
|
|
823
|
-
def
|
824
|
-
|
825
|
-
|
829
|
+
def async_callback_on_completion(state, executor, callback)
|
830
|
+
with_async(executor, state, callback) do |st, cb|
|
831
|
+
callback_on_completion st, cb
|
826
832
|
end
|
827
833
|
end
|
828
834
|
|
@@ -1001,7 +1007,7 @@ module Concurrent
|
|
1001
1007
|
class BlockedPromise < InnerPromise
|
1002
1008
|
def self.new(*args, &block)
|
1003
1009
|
promise = super(*args, &block)
|
1004
|
-
promise.blocked_by.each { |f| f.add_callback :
|
1010
|
+
promise.blocked_by.each { |f| f.add_callback :callback_notify_blocked, promise }
|
1005
1011
|
promise
|
1006
1012
|
end
|
1007
1013
|
|
@@ -1014,7 +1020,7 @@ module Concurrent
|
|
1014
1020
|
# @api private
|
1015
1021
|
def on_done(future)
|
1016
1022
|
countdown = process_on_done(future)
|
1017
|
-
completable = completable?(countdown)
|
1023
|
+
completable = completable?(countdown, future)
|
1018
1024
|
|
1019
1025
|
if completable
|
1020
1026
|
on_completable(future)
|
@@ -1051,7 +1057,7 @@ module Concurrent
|
|
1051
1057
|
end
|
1052
1058
|
|
1053
1059
|
# @return [true,false] if completable
|
1054
|
-
def completable?(countdown)
|
1060
|
+
def completable?(countdown, future)
|
1055
1061
|
countdown.zero?
|
1056
1062
|
end
|
1057
1063
|
|
@@ -1171,7 +1177,7 @@ module Concurrent
|
|
1171
1177
|
case value
|
1172
1178
|
when Future
|
1173
1179
|
@BlockedBy.push value
|
1174
|
-
value.add_callback :
|
1180
|
+
value.add_callback :callback_notify_blocked, self
|
1175
1181
|
@Countdown.value
|
1176
1182
|
when Event
|
1177
1183
|
evaluate_to(lambda { raise TypeError, 'cannot flatten to Event' })
|
@@ -1200,8 +1206,8 @@ module Concurrent
|
|
1200
1206
|
nil
|
1201
1207
|
end
|
1202
1208
|
|
1203
|
-
def completable?(countdown)
|
1204
|
-
!@Future.internal_state.completed? && super(countdown)
|
1209
|
+
def completable?(countdown, future)
|
1210
|
+
!@Future.internal_state.completed? && super(countdown, future)
|
1205
1211
|
end
|
1206
1212
|
end
|
1207
1213
|
|
@@ -1321,7 +1327,7 @@ module Concurrent
|
|
1321
1327
|
end
|
1322
1328
|
|
1323
1329
|
# @!visibility private
|
1324
|
-
class
|
1330
|
+
class AnyCompletePromise < BlockedPromise
|
1325
1331
|
|
1326
1332
|
private
|
1327
1333
|
|
@@ -1331,7 +1337,7 @@ module Concurrent
|
|
1331
1337
|
super(Future.new(self, default_executor), blocked_by_futures, blocked_by_futures.size)
|
1332
1338
|
end
|
1333
1339
|
|
1334
|
-
def completable?(countdown)
|
1340
|
+
def completable?(countdown, future)
|
1335
1341
|
true
|
1336
1342
|
end
|
1337
1343
|
|
@@ -1341,29 +1347,35 @@ module Concurrent
|
|
1341
1347
|
end
|
1342
1348
|
|
1343
1349
|
# @!visibility private
|
1344
|
-
class
|
1345
|
-
def touch
|
1346
|
-
@Future.complete_with Event::COMPLETED
|
1347
|
-
end
|
1350
|
+
class AnySuccessfulPromise < BlockedPromise
|
1348
1351
|
|
1349
1352
|
private
|
1350
1353
|
|
1351
|
-
def initialize(default_executor)
|
1352
|
-
|
1354
|
+
def initialize(blocked_by_futures, default_executor)
|
1355
|
+
blocked_by_futures.all? { |f| f.is_a? Future } or
|
1356
|
+
raise ArgumentError, 'accepts only Futures not Events'
|
1357
|
+
super(Future.new(self, default_executor), blocked_by_futures, blocked_by_futures.size)
|
1358
|
+
end
|
1359
|
+
|
1360
|
+
def completable?(countdown, future)
|
1361
|
+
future.success? || super(countdown, future)
|
1362
|
+
end
|
1363
|
+
|
1364
|
+
def on_completable(done_future)
|
1365
|
+
complete_with done_future.internal_state, false
|
1353
1366
|
end
|
1354
1367
|
end
|
1355
1368
|
|
1356
1369
|
# @!visibility private
|
1357
|
-
class
|
1370
|
+
class DelayPromise < InnerPromise
|
1358
1371
|
def touch
|
1359
|
-
@Future.complete_with
|
1372
|
+
@Future.complete_with Event::COMPLETED
|
1360
1373
|
end
|
1361
1374
|
|
1362
1375
|
private
|
1363
1376
|
|
1364
|
-
def initialize(default_executor
|
1365
|
-
super
|
1366
|
-
@Value = value
|
1377
|
+
def initialize(default_executor)
|
1378
|
+
super Event.new(self, default_executor)
|
1367
1379
|
end
|
1368
1380
|
end
|
1369
1381
|
|
@@ -1401,7 +1413,10 @@ module Concurrent
|
|
1401
1413
|
end
|
1402
1414
|
end
|
1403
1415
|
end
|
1404
|
-
|
1405
|
-
extend Edge::FutureShortcuts
|
1406
|
-
include Edge::FutureShortcuts
|
1407
1416
|
end
|
1417
|
+
|
1418
|
+
Concurrent::Edge.send :extend, Concurrent::Edge::FutureShortcuts
|
1419
|
+
Concurrent::Edge.send :include, Concurrent::Edge::FutureShortcuts
|
1420
|
+
|
1421
|
+
Concurrent.send :extend, Concurrent::Edge::FutureShortcuts
|
1422
|
+
Concurrent.send :include, Concurrent::Edge::FutureShortcuts
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: concurrent-ruby-edge
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jerry D'Antonio
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2016-02
|
13
|
+
date: 2016-05-02 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: concurrent-ruby
|
@@ -18,14 +18,14 @@ dependencies:
|
|
18
18
|
requirements:
|
19
19
|
- - "~>"
|
20
20
|
- !ruby/object:Gem::Version
|
21
|
-
version: 1.0.
|
21
|
+
version: 1.0.2
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
24
|
version_requirements: !ruby/object:Gem::Requirement
|
25
25
|
requirements:
|
26
26
|
- - "~>"
|
27
27
|
- !ruby/object:Gem::Version
|
28
|
-
version: 1.0.
|
28
|
+
version: 1.0.2
|
29
29
|
description: |
|
30
30
|
These features are under active development and may change frequently. They are expected not to
|
31
31
|
keep backward compatibility (there may also lack tests and documentation). Semantic versions will
|
@@ -113,7 +113,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
113
113
|
version: '0'
|
114
114
|
requirements: []
|
115
115
|
rubyforge_project:
|
116
|
-
rubygems_version: 2.6.
|
116
|
+
rubygems_version: 2.6.4
|
117
117
|
signing_key:
|
118
118
|
specification_version: 4
|
119
119
|
summary: Edge features and additions to the concurrent-ruby gem.
|