@@ -727,7 +727,18 @@ def waiting_threads
727
727
@Waiters . each . to_a
728
728
end
729
729
730
+ # # @!visibility private
731
+ def add_callback_notify_blocked ( promise , index )
732
+ add_callback :callback_notify_blocked , promise , index
733
+ end
734
+
730
735
# @!visibility private
736
+ def add_callback_clear_delayed_node ( node )
737
+ add_callback ( :callback_clear_delayed_node , node )
738
+ end
739
+
740
+ private
741
+
731
742
def add_callback ( method , *args )
732
743
state = internal_state
733
744
if resolved? ( state )
@@ -741,7 +752,9 @@ def add_callback(method, *args)
741
752
self
742
753
end
743
754
744
- private
755
+ def callback_clear_delayed_node ( state , node )
756
+ node . value = nil
757
+ end
745
758
746
759
# @return [Boolean]
747
760
def wait_until_resolved ( timeout )
@@ -1202,7 +1215,7 @@ def callback_on_rejection(state, args, callback)
1202
1215
end
1203
1216
1204
1217
def callback_on_resolution ( state , args , callback )
1205
- callback . call state . result , *args
1218
+ callback . call * state . result , *args
1206
1219
end
1207
1220
1208
1221
end
@@ -1326,7 +1339,7 @@ def touch
1326
1339
1327
1340
alias_method :inspect , :to_s
1328
1341
1329
- def delayed
1342
+ def delayed_because
1330
1343
nil
1331
1344
end
1332
1345
@@ -1381,55 +1394,45 @@ class BlockedPromise < InnerPromise
1381
1394
private_class_method :new
1382
1395
1383
1396
def self . new_blocked_by1 ( blocker , *args , &block )
1384
- blocker_delayed = blocker . promise . delayed
1385
- delayed = blocker_delayed ? LockFreeStack . new . push ( blocker_delayed ) : nil
1386
- promise = new ( delayed , 1 , *args , &block )
1387
- blocker . add_callback :callback_notify_blocked , promise , 0
1397
+ blocker_delayed = blocker . promise . delayed_because
1398
+ promise = new ( blocker_delayed , 1 , *args , &block )
1399
+ blocker . add_callback_notify_blocked promise , 0
1388
1400
promise
1389
1401
end
1390
1402
1391
1403
def self . new_blocked_by2 ( blocker1 , blocker2 , *args , &block )
1392
- blocker_delayed1 = blocker1 . promise . delayed
1393
- blocker_delayed2 = blocker2 . promise . delayed
1394
- # TODO (pitr-ch 23-Dec-2016): use arrays when we know it will not grow (only flat adds delay)
1395
- delayed = if blocker_delayed1
1396
- if blocker_delayed2
1397
- LockFreeStack . of2 ( blocker_delayed1 , blocker_delayed2 )
1398
- else
1399
- LockFreeStack . of1 ( blocker_delayed1 )
1400
- end
1404
+ blocker_delayed1 = blocker1 . promise . delayed_because
1405
+ blocker_delayed2 = blocker2 . promise . delayed_because
1406
+ delayed = if blocker_delayed1 && blocker_delayed2
1407
+ # TODO (pitr-ch 23-Dec-2016): use arrays when we know it will not grow (only flat adds delay)
1408
+ LockFreeStack . of2 ( blocker_delayed1 , blocker_delayed2 )
1401
1409
else
1402
- blocker_delayed2 ? LockFreeStack . of1 ( blocker_delayed2 ) : nil
1410
+ blocker_delayed1 || blocker_delayed2
1403
1411
end
1404
1412
promise = new ( delayed , 2 , *args , &block )
1405
- blocker1 . add_callback :callback_notify_blocked , promise , 0
1406
- blocker2 . add_callback :callback_notify_blocked , promise , 1
1413
+ blocker1 . add_callback_notify_blocked promise , 0
1414
+ blocker2 . add_callback_notify_blocked promise , 1
1407
1415
promise
1408
1416
end
1409
1417
1410
1418
def self . new_blocked_by ( blockers , *args , &block )
1411
- delayed = blockers . reduce ( nil , & method ( : add_delayed) )
1419
+ delayed = blockers . reduce ( nil ) { | d , f | add_delayed d , f . promise . delayed_because }
1412
1420
promise = new ( delayed , blockers . size , *args , &block )
1413
- blockers . each_with_index { |f , i | f . add_callback :callback_notify_blocked , promise , i }
1421
+ blockers . each_with_index { |f , i | f . add_callback_notify_blocked promise , i }
1414
1422
promise
1415
1423
end
1416
1424
1417
- def self . add_delayed ( delayed , blocker )
1418
- blocker_delayed = blocker . promise . delayed
1419
- if blocker_delayed
1420
- delayed = unless delayed
1421
- LockFreeStack . of1 ( blocker_delayed )
1422
- else
1423
- delayed . push ( blocker_delayed )
1424
- end
1425
+ def self . add_delayed ( delayed1 , delayed2 )
1426
+ if delayed1 && delayed2
1427
+ delayed1 . push delayed2
1428
+ delayed1
1429
+ else
1430
+ delayed1 || delayed2
1425
1431
end
1426
- delayed
1427
1432
end
1428
1433
1429
1434
def initialize ( delayed , blockers_count , future )
1430
1435
super ( future )
1431
- # noinspection RubyArgCount
1432
- @Touched = AtomicBoolean . new false
1433
1436
@Delayed = delayed
1434
1437
# noinspection RubyArgCount
1435
1438
@Countdown = AtomicFixnum . new blockers_count
@@ -1442,16 +1445,12 @@ def on_blocker_resolution(future, index)
1442
1445
on_resolvable ( future , index ) if resolvable
1443
1446
end
1444
1447
1445
- def delayed
1448
+ def delayed_because
1446
1449
@Delayed
1447
1450
end
1448
1451
1449
1452
def touch
1450
- clear_propagate_touch if @Touched . make_true
1451
- end
1452
-
1453
- def touched?
1454
- @Touched . value
1453
+ clear_and_propagate_touch
1455
1454
end
1456
1455
1457
1456
# for inspection only
@@ -1463,13 +1462,11 @@ def blocked_by
1463
1462
1464
1463
private
1465
1464
1466
- def clear_propagate_touch
1467
- @Delayed . clear_each { |o | propagate_touch o } if @Delayed
1468
- end
1465
+ def clear_and_propagate_touch ( stack_or_element = @Delayed )
1466
+ return if stack_or_element . nil?
1469
1467
1470
- def propagate_touch ( stack_or_element = @Delayed )
1471
1468
if stack_or_element . is_a? LockFreeStack
1472
- stack_or_element . each { |element | propagate_touch element }
1469
+ stack_or_element . clear_each { |element | clear_and_propagate_touch element }
1473
1470
else
1474
1471
stack_or_element . touch unless stack_or_element . nil? # if still present
1475
1472
end
@@ -1572,8 +1569,28 @@ def initialize(default_executor, fulfilled, value, reason)
1572
1569
1573
1570
class AbstractFlatPromise < BlockedPromise
1574
1571
1572
+ def initialize ( delayed_because , blockers_count , event_or_future )
1573
+ delayed = LockFreeStack . of1 ( self )
1574
+ super ( delayed , blockers_count , event_or_future )
1575
+ # noinspection RubyArgCount
1576
+ @Touched = AtomicBoolean . new false
1577
+ @DelayedBecause = delayed_because || LockFreeStack . new
1578
+
1579
+ event_or_future . add_callback_clear_delayed_node delayed . peek
1580
+ end
1581
+
1582
+ def touch
1583
+ if @Touched . make_true
1584
+ clear_and_propagate_touch @DelayedBecause
1585
+ end
1586
+ end
1587
+
1575
1588
private
1576
1589
1590
+ def touched?
1591
+ @Touched . value
1592
+ end
1593
+
1577
1594
def on_resolvable ( resolved_future , index )
1578
1595
resolve_with resolved_future . internal_state
1579
1596
end
@@ -1583,11 +1600,12 @@ def resolvable?(countdown, future, index)
1583
1600
end
1584
1601
1585
1602
def add_delayed_of ( future )
1603
+ delayed = future . promise . delayed_because
1586
1604
if touched?
1587
- propagate_touch future . promise . delayed
1605
+ clear_and_propagate_touch delayed
1588
1606
else
1589
- BlockedPromise . add_delayed @Delayed , future
1590
- clear_propagate_touch if touched?
1607
+ BlockedPromise . add_delayed @DelayedBecause , delayed
1608
+ clear_and_propagate_touch @DelayedBecause if touched?
1591
1609
end
1592
1610
end
1593
1611
@@ -1615,7 +1633,7 @@ def process_on_blocker_resolution(future, index)
1615
1633
case value
1616
1634
when Future , Event
1617
1635
add_delayed_of value
1618
- value . add_callback :callback_notify_blocked , self , nil
1636
+ value . add_callback_notify_blocked self , nil
1619
1637
countdown
1620
1638
else
1621
1639
resolve_with RESOLVED
@@ -1651,7 +1669,7 @@ def process_on_blocker_resolution(future, index)
1651
1669
case value
1652
1670
when Future
1653
1671
add_delayed_of value
1654
- value . add_callback :callback_notify_blocked , self , nil
1672
+ value . add_callback_notify_blocked self , nil
1655
1673
countdown
1656
1674
when Event
1657
1675
evaluate_to ( lambda { raise TypeError , 'cannot flatten to Event' } )
@@ -1684,7 +1702,7 @@ def process_on_blocker_resolution(future, index)
1684
1702
case value
1685
1703
when Future
1686
1704
add_delayed_of value
1687
- value . add_callback :callback_notify_blocked , self , nil
1705
+ value . add_callback_notify_blocked self , nil
1688
1706
else
1689
1707
resolve_with internal_state
1690
1708
end
@@ -1851,17 +1869,17 @@ def resolvable?(countdown, future, index)
1851
1869
class DelayPromise < InnerPromise
1852
1870
1853
1871
def initialize ( default_executor )
1854
- super event = Event . new ( self , default_executor )
1855
- @Delayed = LockFreeStack . new . push self
1856
- # TODO (pitr-ch 20-Dec-2016): implement directly without callback?
1857
- event . on_resolution! ( @Delayed . peek ) { | stack_node | stack_node . value = nil }
1872
+ event = Event . new ( self , default_executor )
1873
+ @Delayed = LockFreeStack . of1 ( self )
1874
+ super event
1875
+ event . add_callback_clear_delayed_node @Delayed . peek
1858
1876
end
1859
1877
1860
1878
def touch
1861
1879
@Future . resolve_with RESOLVED
1862
1880
end
1863
1881
1864
- def delayed
1882
+ def delayed_because
1865
1883
@Delayed
1866
1884
end
1867
1885
0 commit comments