rx 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (186) hide show
  1. checksums.yaml +7 -0
  2. data/.gitattributes +22 -0
  3. data/.gitignore +173 -0
  4. data/.travis.yml +10 -0
  5. data/Gemfile +4 -0
  6. data/Rakefile +11 -0
  7. data/examples/aggregate.rb +39 -0
  8. data/examples/amb.rb +25 -0
  9. data/examples/ambproto.rb +24 -0
  10. data/examples/and.rb +26 -0
  11. data/examples/as_observable.rb +25 -0
  12. data/examples/average.rb +43 -0
  13. data/examples/buffer_with_count.rb +44 -0
  14. data/examples/buffer_with_time.rb +51 -0
  15. data/examples/case.rb +29 -0
  16. data/examples/catch.rb +20 -0
  17. data/examples/catchproto.rb +39 -0
  18. data/examples/combine_latest.rb +35 -0
  19. data/examples/combine_latestproto.rb +33 -0
  20. data/examples/concat.rb +22 -0
  21. data/examples/concat_all.rb +27 -0
  22. data/examples/concat_map.rb +61 -0
  23. data/examples/concat_map_observer.rb +29 -0
  24. data/examples/concatproto.rb +25 -0
  25. data/examples/connect.rb +41 -0
  26. data/examples/contains.rb +37 -0
  27. data/examples/count.rb +36 -0
  28. data/examples/create.rb +55 -0
  29. data/examples/debounce.rb +35 -0
  30. data/examples/default_if_empty.rb +35 -0
  31. data/examples/defer.rb +20 -0
  32. data/examples/delay.rb +49 -0
  33. data/examples/delay_with_selector.rb +63 -0
  34. data/examples/dematerialize.rb +22 -0
  35. data/examples/disposable.rb +12 -0
  36. data/examples/distinct.rb +43 -0
  37. data/examples/distinct_until_changed.rb +43 -0
  38. data/examples/do.rb +59 -0
  39. data/examples/empty.rb +16 -0
  40. data/examples/for.rb +26 -0
  41. data/examples/fork_join.rb +23 -0
  42. data/examples/from.rb +106 -0
  43. data/examples/from_array.rb +21 -0
  44. data/examples/from_callback.rb +21 -0
  45. data/examples/generate.rb +24 -0
  46. data/examples/group_join.rb +39 -0
  47. data/examples/if.rb +46 -0
  48. data/examples/intervals.rb +26 -0
  49. data/examples/merge.rb +36 -0
  50. data/examples/merge_all.rb +27 -0
  51. data/examples/multicast.rb +32 -0
  52. data/examples/never.rb +15 -0
  53. data/examples/of.rb +19 -0
  54. data/examples/on_error_resume_next.rb +21 -0
  55. data/examples/pairs.rb +26 -0
  56. data/examples/publish.rb +79 -0
  57. data/examples/range.rb +19 -0
  58. data/examples/reduce.rb +18 -0
  59. data/examples/repeat.rb +19 -0
  60. data/examples/return.rb +17 -0
  61. data/examples/scan.rb +41 -0
  62. data/examples/start.rb +29 -0
  63. data/examples/throw.rb +17 -0
  64. data/examples/time_intervals.rb +28 -0
  65. data/examples/timer.rb +26 -0
  66. data/examples/timestamp.rb +28 -0
  67. data/examples/to_a.rb +23 -0
  68. data/examples/to_async.rb +26 -0
  69. data/examples/using.rb +52 -0
  70. data/examples/when.rb +26 -0
  71. data/examples/while.rb +25 -0
  72. data/examples/window_with_time.rb +78 -0
  73. data/examples/zip.rb +27 -0
  74. data/examples/zip_array.rb +25 -0
  75. data/lib/core_ext/enumerable.rb +22 -0
  76. data/lib/rx_ruby.rb +27 -0
  77. data/lib/rx_ruby/concurrency/async_lock.rb +57 -0
  78. data/lib/rx_ruby/concurrency/current_thread_scheduler.rb +75 -0
  79. data/lib/rx_ruby/concurrency/default_scheduler.rb +51 -0
  80. data/lib/rx_ruby/concurrency/historical_scheduler.rb +16 -0
  81. data/lib/rx_ruby/concurrency/immediate_scheduler.rb +68 -0
  82. data/lib/rx_ruby/concurrency/local_scheduler.rb +39 -0
  83. data/lib/rx_ruby/concurrency/periodic_scheduler.rb +74 -0
  84. data/lib/rx_ruby/concurrency/scheduled_item.rb +42 -0
  85. data/lib/rx_ruby/concurrency/scheduler.rb +150 -0
  86. data/lib/rx_ruby/concurrency/virtual_time_scheduler.rb +170 -0
  87. data/lib/rx_ruby/core/async_lock_observer.rb +46 -0
  88. data/lib/rx_ruby/core/auto_detach_observer.rb +59 -0
  89. data/lib/rx_ruby/core/checked_observer.rb +66 -0
  90. data/lib/rx_ruby/core/notification.rb +161 -0
  91. data/lib/rx_ruby/core/observable.rb +104 -0
  92. data/lib/rx_ruby/core/observe_on_observer.rb +50 -0
  93. data/lib/rx_ruby/core/observer.rb +119 -0
  94. data/lib/rx_ruby/core/scheduled_observer.rb +83 -0
  95. data/lib/rx_ruby/core/synchronized_observer.rb +47 -0
  96. data/lib/rx_ruby/core/time_interval.rb +17 -0
  97. data/lib/rx_ruby/internal/priority_queue.rb +122 -0
  98. data/lib/rx_ruby/internal/util.rb +9 -0
  99. data/lib/rx_ruby/joins/active_plan.rb +45 -0
  100. data/lib/rx_ruby/joins/join_observer.rb +51 -0
  101. data/lib/rx_ruby/joins/pattern.rb +14 -0
  102. data/lib/rx_ruby/joins/plan.rb +44 -0
  103. data/lib/rx_ruby/linq/connectable_observable.rb +34 -0
  104. data/lib/rx_ruby/linq/observable/_observable_timer_date_and_period.rb +22 -0
  105. data/lib/rx_ruby/linq/observable/_observable_timer_time_span.rb +14 -0
  106. data/lib/rx_ruby/linq/observable/_observable_timer_time_span_and_period.rb +20 -0
  107. data/lib/rx_ruby/linq/observable/aggregate.rb +7 -0
  108. data/lib/rx_ruby/linq/observable/and.rb +7 -0
  109. data/lib/rx_ruby/linq/observable/case.rb +15 -0
  110. data/lib/rx_ruby/linq/observable/concat_all.rb +7 -0
  111. data/lib/rx_ruby/linq/observable/concat_map.rb +35 -0
  112. data/lib/rx_ruby/linq/observable/concat_map_observer.rb +43 -0
  113. data/lib/rx_ruby/linq/observable/contains.rb +28 -0
  114. data/lib/rx_ruby/linq/observable/debounce.rb +41 -0
  115. data/lib/rx_ruby/linq/observable/delay.rb +81 -0
  116. data/lib/rx_ruby/linq/observable/delay_with_selector.rb +64 -0
  117. data/lib/rx_ruby/linq/observable/do.rb +42 -0
  118. data/lib/rx_ruby/linq/observable/for.rb +13 -0
  119. data/lib/rx_ruby/linq/observable/fork_join.rb +55 -0
  120. data/lib/rx_ruby/linq/observable/from.rb +34 -0
  121. data/lib/rx_ruby/linq/observable/group_join.rb +108 -0
  122. data/lib/rx_ruby/linq/observable/if.rb +17 -0
  123. data/lib/rx_ruby/linq/observable/interval.rb +5 -0
  124. data/lib/rx_ruby/linq/observable/multicast.rb +14 -0
  125. data/lib/rx_ruby/linq/observable/of.rb +11 -0
  126. data/lib/rx_ruby/linq/observable/pairs.rb +7 -0
  127. data/lib/rx_ruby/linq/observable/pluck.rb +7 -0
  128. data/lib/rx_ruby/linq/observable/publish.rb +11 -0
  129. data/lib/rx_ruby/linq/observable/start.rb +7 -0
  130. data/lib/rx_ruby/linq/observable/time_interval.rb +15 -0
  131. data/lib/rx_ruby/linq/observable/timer.rb +26 -0
  132. data/lib/rx_ruby/linq/observable/timestamp.rb +9 -0
  133. data/lib/rx_ruby/linq/observable/to_async.rb +40 -0
  134. data/lib/rx_ruby/linq/observable/when.rb +36 -0
  135. data/lib/rx_ruby/linq/observable/while.rb +41 -0
  136. data/lib/rx_ruby/operators/aggregates.rb +611 -0
  137. data/lib/rx_ruby/operators/creation.rb +220 -0
  138. data/lib/rx_ruby/operators/multiple.rb +735 -0
  139. data/lib/rx_ruby/operators/single.rb +399 -0
  140. data/lib/rx_ruby/operators/standard_query_operators.rb +279 -0
  141. data/lib/rx_ruby/operators/synchronization.rb +47 -0
  142. data/lib/rx_ruby/operators/time.rb +120 -0
  143. data/lib/rx_ruby/subjects/async_subject.rb +161 -0
  144. data/lib/rx_ruby/subjects/behavior_subject.rb +149 -0
  145. data/lib/rx_ruby/subjects/replay_subject.rb +39 -0
  146. data/lib/rx_ruby/subjects/subject.rb +131 -0
  147. data/lib/rx_ruby/subjects/subject_extensions.rb +45 -0
  148. data/lib/rx_ruby/subscriptions/composite_subscription.rb +91 -0
  149. data/lib/rx_ruby/subscriptions/ref_count_subscription.rb +88 -0
  150. data/lib/rx_ruby/subscriptions/scheduled_subscription.rb +32 -0
  151. data/lib/rx_ruby/subscriptions/serial_subscription.rb +60 -0
  152. data/lib/rx_ruby/subscriptions/single_assignment_subscription.rb +64 -0
  153. data/lib/rx_ruby/subscriptions/subscription.rb +56 -0
  154. data/lib/rx_ruby/testing/cold_observable.rb +45 -0
  155. data/lib/rx_ruby/testing/hot_observable.rb +47 -0
  156. data/lib/rx_ruby/testing/mock_observer.rb +33 -0
  157. data/lib/rx_ruby/testing/reactive_test.rb +94 -0
  158. data/lib/rx_ruby/testing/recorded.rb +17 -0
  159. data/lib/rx_ruby/testing/test_scheduler.rb +96 -0
  160. data/lib/rx_ruby/testing/test_subscription.rb +22 -0
  161. data/lib/rx_ruby/version.rb +3 -0
  162. data/license.txt +13 -0
  163. data/readme.md +152 -0
  164. data/rx_ruby.gemspec +22 -0
  165. data/test/rx_ruby/concurrency/helpers/historical_virtual_scheduler_helper.rb +135 -0
  166. data/test/rx_ruby/concurrency/helpers/immediate_local_scheduler_helper.rb +51 -0
  167. data/test/rx_ruby/concurrency/test_async_lock.rb +56 -0
  168. data/test/rx_ruby/concurrency/test_current_thread_scheduler.rb +44 -0
  169. data/test/rx_ruby/concurrency/test_default_scheduler.rb +44 -0
  170. data/test/rx_ruby/concurrency/test_historical_scheduler.rb +18 -0
  171. data/test/rx_ruby/concurrency/test_immediate_scheduler.rb +53 -0
  172. data/test/rx_ruby/concurrency/test_local_scheduler.rb +12 -0
  173. data/test/rx_ruby/concurrency/test_periodic_scheduler.rb +53 -0
  174. data/test/rx_ruby/concurrency/test_scheduled_item.rb +50 -0
  175. data/test/rx_ruby/concurrency/test_scheduler.rb +128 -0
  176. data/test/rx_ruby/concurrency/test_virtual_time_scheduler.rb +14 -0
  177. data/test/rx_ruby/core/test_notification.rb +129 -0
  178. data/test/rx_ruby/core/test_observable_creation.rb +483 -0
  179. data/test/rx_ruby/core/test_observer.rb +634 -0
  180. data/test/rx_ruby/internal/test_priority_queue.rb +71 -0
  181. data/test/rx_ruby/subscriptions/test_composite_subscription.rb +116 -0
  182. data/test/rx_ruby/subscriptions/test_serial_subscription.rb +62 -0
  183. data/test/rx_ruby/subscriptions/test_singleassignment_subscription.rb +61 -0
  184. data/test/rx_ruby/subscriptions/test_subscription.rb +27 -0
  185. data/test/test_helper.rb +11 -0
  186. metadata +291 -0
@@ -0,0 +1,104 @@
1
+ # Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
2
+
3
+ require 'rx_ruby/concurrency/current_thread_scheduler'
4
+ require 'rx_ruby/concurrency/immediate_scheduler'
5
+ require 'rx_ruby/core/observer'
6
+ require 'rx_ruby/core/auto_detach_observer'
7
+ require 'rx_ruby/subscriptions/subscription'
8
+
9
+ module RxRuby
10
+
11
+ module Observable
12
+
13
+ def subscribe(*args)
14
+ case args.size
15
+ when 0
16
+ if block_given?
17
+ _subscribe Observer.configure {|o| o.on_next(&Proc.new) }
18
+ else
19
+ _subscribe Observer.configure
20
+ end
21
+ when 1
22
+ _subscribe args[0]
23
+ when 3
24
+ _subscribe Observer.configure {|o|
25
+ o.on_next(&args[0])
26
+ o.on_error(&args[1])
27
+ o.on_completed(&args[2])
28
+ }
29
+ else
30
+ raise ArgumentError, "wrong number of arguments (#{args.size} for 0..1 or 3)"
31
+ end
32
+ end
33
+
34
+ # Subscribes the given observer to the observable sequence.
35
+ # @param [Observer] observer
36
+ # @return [Subscription]
37
+ def _subscribe(observer)
38
+
39
+ auto_detach_observer = AutoDetachObserver.new observer
40
+
41
+ if CurrentThreadScheduler.schedule_required?
42
+ CurrentThreadScheduler.instance.schedule_with_state auto_detach_observer, method(:schedule_subscribe)
43
+ else
44
+ begin
45
+ auto_detach_observer.subscription = subscribe_core auto_detach_observer
46
+ rescue => e
47
+ raise e unless auto_detach_observer.fail e
48
+ end
49
+ end
50
+
51
+ auto_detach_observer
52
+ end
53
+
54
+ # Subscribes the given block to the on_next action of the observable sequence.
55
+ # @param [Object] block
56
+ # @return [Subscription]
57
+ def subscribe_on_next(&block)
58
+ raise ArgumentError.new 'Block is required' unless block_given?
59
+ subscribe(Observer.configure {|o| o.on_next(&block) })
60
+ end
61
+
62
+ # Subscribes the given block to the on_error action of the observable sequence.
63
+ def subscribe_on_error(&block)
64
+ raise ArgumentError.new 'Block is required' unless block_given?
65
+ subscribe(Observer.configure {|o| o.on_error(&block) })
66
+ end
67
+
68
+ # Subscribes the given block to the on_completed action of the observable sequence.
69
+ def subscribe_on_completed(&block)
70
+ raise ArgumentError.new 'Block is required' unless block_given?
71
+ subscribe(Observer.configure {|o| o.on_completed(&block) })
72
+ end
73
+
74
+ private
75
+
76
+ def schedule_subscribe(_, auto_detach_observer)
77
+ begin
78
+ auto_detach_observer.subscription = subscribe_core auto_detach_observer
79
+ rescue => e
80
+ raise e unless auto_detach_observer.fail e
81
+ end
82
+
83
+ Subscription.empty
84
+ end
85
+
86
+ end
87
+
88
+ class AnonymousObservable
89
+
90
+ include Observable
91
+
92
+ def initialize(&subscribe)
93
+ @subscribe = subscribe
94
+ end
95
+
96
+ protected
97
+
98
+ def subscribe_core(obs)
99
+ @subscribe.call(obs) || Subscription.empty
100
+ end
101
+
102
+ end
103
+
104
+ end
@@ -0,0 +1,50 @@
1
+ # Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
2
+
3
+ require 'thread'
4
+ require 'rx_ruby/core/scheduled_observer'
5
+
6
+ module RxRuby
7
+
8
+ module Observer
9
+ # Schedules the invocation of observer methods on the given scheduler.
10
+ def notify_on(scheduler)
11
+ ObserveOnObserver.new(scheduler, self, nil)
12
+ end
13
+ end
14
+
15
+ class ObserveOnObserver < ScheduledObserver
16
+
17
+ def initialize(scheduler, observer, cancel = nil)
18
+ @cancel = cancel
19
+
20
+ super(scheduler, observer)
21
+ end
22
+
23
+ def on_next_core(value)
24
+ ensure_active
25
+ super(value)
26
+ end
27
+
28
+ def on_error_core(error)
29
+ ensure_active
30
+ super(error)
31
+ end
32
+
33
+ def on_completed_core
34
+ ensure_active
35
+ super
36
+ end
37
+
38
+ def unsubscribe
39
+ super
40
+
41
+ cancel = nil
42
+ Mutex.new.synchronize do
43
+ cancel = @cancel
44
+ @cancel = nil
45
+ end
46
+
47
+ canel.unsubscribe if cancel
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,119 @@
1
+ # Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
2
+
3
+ module RxRuby
4
+
5
+ # Configuration class for storing Observer actions
6
+ class ObserverConfiguration
7
+
8
+ DEFAULT_ON_NEXT = lambda {|x| }
9
+ DEFAULT_ON_ERROR = lambda {|error| raise error }
10
+ DEFAULT_ON_COMPLETED = lambda { }
11
+
12
+ attr_reader :on_next_action, :on_error_action, :on_completed_action
13
+
14
+ def initialize
15
+ @on_next_action = DEFAULT_ON_NEXT
16
+ @on_error_action = DEFAULT_ON_ERROR
17
+ @on_completed_action = DEFAULT_ON_COMPLETED
18
+ end
19
+
20
+ def on_next(&on_next_action)
21
+ @on_next_action = on_next_action
22
+ end
23
+
24
+ def on_error(&on_error_action)
25
+ @on_error_action = on_error_action
26
+ end
27
+
28
+ def on_completed(&on_completed_action)
29
+ @on_completed_action = on_completed_action
30
+ end
31
+ end
32
+
33
+ # Module for all Observers
34
+ module Observer
35
+
36
+ # Hides the identity of an observer.
37
+ def as_observer
38
+ Observer.configure do |o|
39
+ o.on_next(&method(:on_next))
40
+ o.on_error(&method(:on_error))
41
+ o.on_completed(&method(:on_completed))
42
+ end
43
+ end
44
+
45
+ # Creates a notification callback from an observer.
46
+ def to_notifier
47
+ lambda {|n| n.accept self}
48
+ end
49
+
50
+ class << self
51
+
52
+ # Configures a new instance of an Observer
53
+ def configure
54
+ config = ObserverConfiguration.new
55
+ yield config if block_given?
56
+ ObserverBase.new config
57
+ end
58
+
59
+ def create(on_next = nil, on_error = nil, on_completed = nil)
60
+ configure do |o|
61
+ o.on_next(&on_next) if on_next
62
+ o.on_error(&on_error) if on_error
63
+ o.on_completed(&on_completed) if on_completed
64
+ end
65
+ end
66
+ end
67
+
68
+ end
69
+
70
+ # Base class for all Observer implementations
71
+ class ObserverBase
72
+ include Observer
73
+
74
+ def initialize(config)
75
+ @config = config
76
+ @stopped = false
77
+ end
78
+
79
+ # Unsubscribes from the current observer causing it to transition to the stopped state.
80
+ def unsubscribe
81
+ @stopped = true
82
+ end
83
+
84
+ def dispose
85
+ unsubscribe
86
+ end
87
+
88
+ # Notifies the observer of a new element in the sequence.
89
+ def on_next(value)
90
+ @config.on_next_action.call value unless @stopped
91
+ end
92
+
93
+ # Notifies the observer that an exception has occurred.
94
+ def on_error(error)
95
+ raise 'Error cannot be nil' unless error
96
+ unless @stopped
97
+ @stopped = true
98
+ @config.on_error_action.call error
99
+ end
100
+ end
101
+
102
+ # Notifies the observer of the end of the sequence.
103
+ def on_completed
104
+ unless @stopped
105
+ @stopped = true
106
+ @config.on_completed_action.call
107
+ end
108
+ end
109
+
110
+ def fail(error)
111
+ unless @stopped
112
+ @stopped = true
113
+ @config.on_error_action.call error
114
+ return true
115
+ end
116
+ return false
117
+ end
118
+ end
119
+ end
@@ -0,0 +1,83 @@
1
+ # Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
2
+
3
+ require 'monitor'
4
+ require 'rx_ruby/subscriptions/serial_subscription'
5
+ require 'rx_ruby/core/observer'
6
+
7
+ module RxRuby
8
+
9
+ class ScheduledObserver < ObserverBase
10
+
11
+ def initialize(scheduler, observer)
12
+ @scheduler = scheduler
13
+ @observer = observer
14
+ @gate = Monitor.new
15
+ @queue = []
16
+ @subscriber = SerialSubscription.new
17
+ @acquired = false
18
+ @faulted = false
19
+
20
+ config = ObserverConfiguration.new
21
+ config.on_next(&method(:on_next_core))
22
+ config.on_error(&method(:on_error_core))
23
+ config.on_completed(&method(:on_completed_core))
24
+
25
+ super(config)
26
+ end
27
+
28
+ def on_next_core(value)
29
+ @gate.synchronize { @queue.push(lambda { @observer.on_next value }) }
30
+ end
31
+
32
+ def on_error_core(error)
33
+ @gate.synchronize { @queue.push(lambda { @observer.on_error error }) }
34
+ end
35
+
36
+ def on_completed_core
37
+ @gate.synchronize { @queue.push(lambda { @observer.on_completed }) }
38
+ end
39
+
40
+ def ensure_active(n=0)
41
+ owner = false
42
+
43
+ @gate.synchronize do
44
+ if !@faulted && @queue.length > 0
45
+ owner = !@acquired
46
+ @acquired = true
47
+ end
48
+ end
49
+
50
+ @subscriber.subscription = @scheduler.schedule_recursive_with_state(nil, method(:run)) if owner
51
+ end
52
+
53
+ def run(state, recurse)
54
+ work = nil
55
+ @gate.synchronize do
56
+ if @queue.length > 0
57
+ work = @queue.shift
58
+ else
59
+ @acquired = false
60
+ return
61
+ end
62
+ end
63
+
64
+ begin
65
+ work.call
66
+ rescue => e
67
+ @queue = []
68
+ @faulted = true
69
+
70
+ raise e
71
+ end
72
+
73
+ recurse.call state
74
+ end
75
+
76
+ def unsubscribe
77
+ super
78
+ @subscriber.unsubscribe
79
+ end
80
+
81
+ end
82
+
83
+ end
@@ -0,0 +1,47 @@
1
+ # Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
2
+
3
+ require 'monitor'
4
+ require 'rx_ruby/core/observer'
5
+
6
+ module RxRuby
7
+
8
+ module Observer
9
+
10
+ class << self
11
+ # Synchronizes access to the observer such that its callback methods cannot be called concurrently by multiple threads, using the specified gate object for use by a Monitor based lock.
12
+ # This overload is useful when coordinating multiple observers that access shared state by synchronizing on a common gate object if given.
13
+ # Notice reentrant observer callbacks on the same thread are still possible.
14
+ def allow_reentrancy(observer, gate = Monitor.new)
15
+ SynchronizedObserver.new(observer, gate)
16
+ end
17
+ end
18
+ end
19
+
20
+ class SynchronizedObserver < RxRuby::ObserverBase
21
+
22
+ def on_next_core(value)
23
+ @gate.synchronize { @observer.on_next value }
24
+ end
25
+
26
+ def on_error_core(error)
27
+ @gate.synchronize { @observer.on_error error }
28
+ end
29
+
30
+ def on_completed_core
31
+ @gate.synchronize { @observer.on_completed }
32
+ end
33
+
34
+ def initialize(observer, gate)
35
+ @observer = observer
36
+ @gate = gate
37
+
38
+ config = ObserverConfiguration.new
39
+ config.on_next(&method(:on_next_core))
40
+ config.on_error(&method(:on_error_core))
41
+ config.on_completed(&method(:on_completed_core))
42
+
43
+ super(config)
44
+ end
45
+
46
+ end
47
+ end
@@ -0,0 +1,17 @@
1
+ # Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
2
+
3
+ module RxRuby
4
+
5
+ # Record of a value including the virtual time it was produced on.
6
+ class TimeInterval < Struct.new(:interval, :value)
7
+
8
+ def initialize(interval, value)
9
+ super
10
+ end
11
+
12
+ def to_s
13
+ "(#{value})@(#{interval})"
14
+ end
15
+
16
+ end
17
+ end
@@ -0,0 +1,122 @@
1
+ # Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
2
+
3
+ module RxRuby
4
+
5
+ # Priority Queue implemented as a binary heap.
6
+ class PriorityQueue
7
+ def initialize
8
+ @items = []
9
+ @mutex = Mutex.new
10
+ end
11
+
12
+ def peek
13
+ @mutex.synchronize do
14
+ unsafe_peek
15
+ end
16
+ end
17
+
18
+ def shift
19
+ @mutex.synchronize do
20
+ result = unsafe_peek
21
+ delete_at 0
22
+ result
23
+ end
24
+ end
25
+
26
+ def push(item)
27
+ @mutex.synchronize do
28
+ @items.push IndexedItem.new(item)
29
+ percolate length - 1
30
+ end
31
+ end
32
+
33
+ def delete(item)
34
+ @mutex.synchronize do
35
+ index = @items.index {|it| it.value == item }
36
+ if index
37
+ delete_at index
38
+ true
39
+ else
40
+ false
41
+ end
42
+ end
43
+ end
44
+
45
+ def length
46
+ @items.length
47
+ end
48
+
49
+ private
50
+
51
+ def unsafe_peek
52
+ @items.first.value unless @items.empty?
53
+ end
54
+
55
+ def delete_at(index)
56
+ substitute = @items.pop
57
+ if substitute and index < @items.length
58
+ @items[index] = substitute
59
+ heapify index
60
+ end
61
+ end
62
+
63
+ # bubble up an item while it's smaller than parents
64
+ def percolate(index)
65
+ parent = (index - 1) / 2
66
+ return if parent < 0
67
+
68
+ current_value = @items[index]
69
+ parent_value = @items[parent]
70
+
71
+ if current_value < parent_value
72
+ @items[index] = parent_value
73
+ @items[parent] = current_value
74
+ percolate parent
75
+ end
76
+ end
77
+
78
+ # bubble down an item while it's bigger than children
79
+ def heapify(index)
80
+ current_index = index
81
+ left_index = 2 * index + 1
82
+ right_index = 2 * index + 2
83
+
84
+ current_value = @items[index]
85
+ left_value = @items[left_index]
86
+ right_value = @items[right_index]
87
+
88
+ if right_value && right_value < current_value && right_value < left_value
89
+ current_index = right_index
90
+ elsif left_value && left_value < current_value
91
+ current_index = left_index
92
+ end
93
+
94
+ if current_index != index
95
+ @items[index] = @items[current_index]
96
+ @items[current_index] = current_value
97
+ heapify current_index
98
+ end
99
+ end
100
+
101
+ class IndexedItem
102
+ include Comparable
103
+ attr_reader :id , :value
104
+
105
+ @@length = 0
106
+
107
+ def initialize(value)
108
+ @id = @@length += 1
109
+ @value = value
110
+ end
111
+
112
+ def <=>(other)
113
+ if @value == other.value
114
+ @id <=> other.id
115
+ else
116
+ @value <=> other.value
117
+ end
118
+ end
119
+ end
120
+
121
+ end
122
+ end