rx_ruby 0.0.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.
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