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,170 @@
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/scheduler'
4
+ require 'rx_ruby/internal/priority_queue'
5
+ require 'rx_ruby/subscriptions/subscription'
6
+
7
+ module RxRuby
8
+
9
+ # Base class for virtual time schedulers using a priority queue for scheduled items.
10
+ class VirtualTimeScheduler
11
+
12
+ include Scheduler
13
+
14
+ attr_reader :clock
15
+
16
+ def initialize(initial_clock)
17
+ @clock = initial_clock.to_i
18
+ @queue = PriorityQueue.new
19
+ @enabled = false
20
+ end
21
+
22
+ # Gets the scheduler's notion of current time.
23
+ def now
24
+ clock
25
+ end
26
+
27
+ # Gets whether the scheduler is enabled to run work.
28
+ def enabled?
29
+ @enabled
30
+ end
31
+
32
+ # Starts the virtual time scheduler.
33
+ def start
34
+ unless @enabled
35
+ @enabled = true
36
+
37
+ begin
38
+ next_item = self.get_next
39
+
40
+ unless next_item.nil?
41
+ @clock = next_item.due_time if next_item.due_time > @clock
42
+ next_item.invoke
43
+ else
44
+ @enabled = false
45
+ end
46
+
47
+ end while @enabled
48
+ end
49
+ end
50
+
51
+ # Stops the virtual time scheduler.
52
+ def stop
53
+ @enabled = false
54
+ end
55
+
56
+ # Schedules an action to be executed.
57
+ def schedule_with_state(state, action)
58
+ raise 'action cannot be nil' unless action
59
+ schedule_at_absolute_with_state(state, clock, action)
60
+ end
61
+
62
+ # Schedules an action to be executed at due_time.
63
+ def schedule_at_relative(due_time, action)
64
+ raise 'action cannot be nil' unless action
65
+
66
+ schedule_at_relative_with_state(action, due_time, method(:invoke))
67
+ end
68
+
69
+ # Schedules an action to be executed at due_time.
70
+ def schedule_at_relative_with_state(state, due_time, action)
71
+ raise 'action cannot be nil' unless action
72
+
73
+ schedule_at_absolute_with_state(state, @clock + due_time, action)
74
+ end
75
+ alias_method :schedule_relative_with_state, :schedule_at_relative_with_state
76
+
77
+ # Schedules an action to be executed at due_time.
78
+ def schedule_at_absolute(due_time, action)
79
+ raise 'action cannot be nil' unless action
80
+
81
+ schedule_at_absolute_with_state(action, due_time, method(:invoke))
82
+ end
83
+
84
+ # Schedules an action to be executed at due_time.
85
+ def schedule_at_absolute_with_state(state, due_time, action)
86
+ raise 'action cannot be nil' unless action
87
+
88
+ si = nil
89
+ run = lambda {|scheduler, state1|
90
+ @queue.delete si
91
+ action.call(scheduler, state1)
92
+ }
93
+
94
+ si = ScheduledItem.new(self, state, due_time, &run)
95
+ @queue.push si
96
+
97
+ Subscription.create { si.cancel }
98
+ end
99
+ alias_method :schedule_absolute_with_state, :schedule_at_absolute_with_state
100
+
101
+ # Advances the scheduler's clock to the specified time, running all work till that point.
102
+ def advance_to(time)
103
+ due_to_clock = time<=>clock
104
+ raise 'Time is out of range' if due_to_clock < 0
105
+
106
+ return if due_to_clock == 0
107
+
108
+ unless @enabled
109
+ @enabled = true
110
+
111
+ begin
112
+ next_item = self.get_next
113
+ if !next_item.nil? && next_item.due_time <= time
114
+ @clock = next_item.due_time if next_item.due_time > @clock
115
+ next_item.invoke
116
+ else
117
+ @enabled = false
118
+ end
119
+
120
+ end while @enabled
121
+
122
+ @clock = time
123
+ else
124
+ raise 'Cannot advance while running'
125
+ end
126
+
127
+ end
128
+
129
+ # Advances the scheduler's clock by the specified relative time, running all work scheduled for that timespan.
130
+ def advance_by(time)
131
+ dt = @clock + time
132
+
133
+ due_to_clock = dt<=>clock
134
+ raise 'Time is out of range' if due_to_clock < 0
135
+
136
+ return if due_to_clock == 0
137
+ raise 'Cannot advance while running' if @enabled
138
+
139
+ self.advance_to dt
140
+ end
141
+
142
+ # Advances the scheduler's clock by the specified relative time.
143
+ def sleep(time)
144
+ dt = @clock + time
145
+
146
+ due_to_clock = dt<=>@clock
147
+ raise 'Time is out of range' if due_to_clock < 0
148
+
149
+ @clock = dt
150
+ end
151
+
152
+ # Gets the next scheduled item to be executed
153
+ def get_next
154
+ while next_item = @queue.peek
155
+ if next_item.cancelled?
156
+ @queue.shift
157
+ else
158
+ return next_item
159
+ end
160
+ end
161
+
162
+ return nil
163
+ end
164
+
165
+ def invoke(scheduler, action)
166
+ action.call
167
+ Subscription.empty
168
+ end
169
+ end
170
+ end
@@ -0,0 +1,46 @@
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/async_lock'
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, using the specified asynchronous lock to protect against concurrent and reentrant access.
12
+ # This overload is useful when coordinating multiple observers that access shared state by synchronizing on a common asynchronous lock.
13
+ def prevent_reentrancy(observer, gate = AsyncLock.new)
14
+ AsyncLockObserver.new(observer, gate)
15
+ end
16
+ end
17
+ end
18
+
19
+ class AsyncLockObserver < RxRuby::ObserverBase
20
+
21
+ def on_next_core(value)
22
+ @gate.wait { @observer.on_next value }
23
+ end
24
+
25
+ def on_error_core(error)
26
+ @gate.wait { @observer.on_error error }
27
+ end
28
+
29
+ def on_completed_core
30
+ @gate.wait { @observer.on_completed }
31
+ end
32
+
33
+ def initialize(observer, gate)
34
+ @observer = observer
35
+ @gate = gate
36
+
37
+ config = ObserverConfiguration.new
38
+ config.on_next(&method(:on_next_core))
39
+ config.on_error(&method(:on_error_core))
40
+ config.on_completed(&method(:on_completed_core))
41
+
42
+ super(config)
43
+ end
44
+
45
+ end
46
+ end
@@ -0,0 +1,59 @@
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/core/observer'
4
+ require 'rx_ruby/subscriptions/single_assignment_subscription'
5
+
6
+ module RxRuby
7
+
8
+ class AutoDetachObserver < RxRuby::ObserverBase
9
+
10
+ def on_next_core(value)
11
+ no_error = false
12
+ begin
13
+ @observer.on_next(value)
14
+ no_error = true
15
+ ensure
16
+ unsubscribe unless no_error
17
+ end
18
+ end
19
+
20
+ def on_error_core(error)
21
+ begin
22
+ @observer.on_error(error)
23
+ ensure
24
+ unsubscribe
25
+ end
26
+ end
27
+
28
+ def on_completed_core
29
+ begin
30
+ @observer.on_completed
31
+ ensure
32
+ unsubscribe
33
+ end
34
+ end
35
+
36
+ def initialize(observer)
37
+ @observer = observer
38
+ @m = SingleAssignmentSubscription.new
39
+
40
+ config = ObserverConfiguration.new
41
+ config.on_next(&method(:on_next_core))
42
+ config.on_error(&method(:on_error_core))
43
+ config.on_completed(&method(:on_completed_core))
44
+
45
+ super(config)
46
+ end
47
+
48
+ def subscription=(new_subscription)
49
+ @m.subscription = new_subscription
50
+ end
51
+
52
+ def unsubscribe
53
+ super
54
+ @m.unsubscribe
55
+ end
56
+
57
+ end
58
+ end
59
+
@@ -0,0 +1,66 @@
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/observer'
5
+
6
+ module RxRuby
7
+
8
+ module Observer
9
+ # Checks access to the observer for grammar violations. This includes checking for multiple on_error or on_completed calls, as well as reentrancy in any of the observer methods.
10
+ # If a violation is detected, an error is thrown from the offending observer method call.
11
+ def checked
12
+ CheckedObserver.new(self)
13
+ end
14
+ end
15
+
16
+ class CheckedObserver
17
+ include Observer
18
+
19
+ def initialize(observer)
20
+ @observer = observer
21
+ @state = :idle
22
+ end
23
+
24
+ def on_next(value)
25
+ check_access
26
+ begin
27
+ @observer.on_next value
28
+ ensure
29
+ Mutex.new.synchronize { @state = :idle }
30
+ end
31
+ end
32
+
33
+ def on_error(error)
34
+ check_access
35
+ begin
36
+ @observer.on_error error
37
+ ensure
38
+ Mutex.new.synchronize { @state = :done }
39
+ end
40
+ end
41
+
42
+ def on_completed
43
+ check_access
44
+ begin
45
+ @observer.on_completed
46
+ ensure
47
+ Mutex.new.synchronize { @state = :done }
48
+ end
49
+ end
50
+
51
+ private
52
+
53
+ def check_access
54
+ Mutex.new.synchronize do
55
+ old = @state
56
+ @state = :busy if @state == :idle
57
+ case old
58
+ when :busy
59
+ raise 'Re-entrancy detected'
60
+ when :done
61
+ raise 'Observer terminated'
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,161 @@
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/immediate_scheduler'
4
+ require 'rx_ruby/core/observable'
5
+
6
+ module RxRuby
7
+
8
+ module Observer
9
+
10
+ class << self
11
+ # Creates an observer from a notification callback.
12
+ def from_notifier
13
+ raise ArgumentError.new 'Block required' unless block_given?
14
+
15
+ configure do |o|
16
+ o.on_next {|x| yield Notification.create_on_next(x) }
17
+ o.on_error {|err| yield Notification.create_on_error(err) }
18
+ o.on_completed { yield Notification.create_on_completed }
19
+ end
20
+ end
21
+ end
22
+ end
23
+
24
+ # Represents a notification to an observer.
25
+ module Notification
26
+
27
+ class << self
28
+
29
+ # Creates an object that represents an on_next notification to an observer.
30
+ def create_on_next(value)
31
+ OnNextNotification.new value
32
+ end
33
+
34
+ # Creates an object that represents an on_error notification to an observer.
35
+ def create_on_error(error)
36
+ OnErrorNotification.new error
37
+ end
38
+
39
+ # Creates an object that represents an on_completed notification to an observer.
40
+ def create_on_completed
41
+ OnCompletedNotification.new
42
+ end
43
+
44
+ end
45
+
46
+ # Determines whether this is an on_next notification.
47
+ def on_next?
48
+ @kind == :on_next
49
+ end
50
+
51
+ # Determines whether this is an on_error notification.
52
+ def on_error?
53
+ @kind == :on_error
54
+ end
55
+
56
+ # Determines whether this is an on_completed notification.
57
+ def on_completed?
58
+ @kind == :on_completed
59
+ end
60
+
61
+ # Determines whether this notification has a value.
62
+ def has_value?
63
+ false
64
+ end
65
+
66
+ # Returns an observable sequence with a single notification.
67
+ def to_observable(scheduler = ImmediateScheduler.instance)
68
+ AnonymousObservable.new do |observer|
69
+ scheduler.schedule lambda {
70
+ accept observer
71
+ observer.on_completed if on_next?
72
+ }
73
+ end
74
+ end
75
+
76
+ end
77
+
78
+ # Represents an on_next notification to an observer.
79
+ class OnNextNotification
80
+ include Notification
81
+
82
+ attr_reader :value
83
+
84
+ def initialize(value)
85
+ @value = value
86
+ @kind = :on_next
87
+ end
88
+
89
+ # Determines whether this notification has a value.
90
+ def has_value?
91
+ true
92
+ end
93
+
94
+ def ==(other)
95
+ other.class == self.class && other.on_next? && value == other.value
96
+ end
97
+ alias_method :eql?, :==
98
+
99
+ def to_s
100
+ "on_next(#{value})"
101
+ end
102
+
103
+ # Invokes the observer's method corresponding to the notification.
104
+ def accept(observer)
105
+ observer.on_next value
106
+ end
107
+
108
+ end
109
+
110
+ # Represents an on_error notification to an observer.
111
+ class OnErrorNotification
112
+ include Notification
113
+
114
+ attr_reader :error
115
+
116
+ def initialize(error)
117
+ @error = error
118
+ @kind = :on_error
119
+ end
120
+
121
+ def ==(other)
122
+ other.class == self.class && other.on_error? && error == other.error
123
+ end
124
+ alias_method :eql?, :==
125
+
126
+ def to_s
127
+ "on_error(#{error})"
128
+ end
129
+
130
+ # Invokes the observer's method corresponding to the notification.
131
+ def accept(observer)
132
+ observer.on_error error
133
+ end
134
+
135
+ end
136
+
137
+ # Represents an on_completed notification to an observer.
138
+ class OnCompletedNotification
139
+ include Notification
140
+
141
+ def initialize
142
+ @kind = :on_completed
143
+ end
144
+
145
+ def ==(other)
146
+ other.class == self.class && other.on_completed?
147
+ end
148
+ alias_method :eql?, :==
149
+
150
+ def to_s
151
+ "on_completed()"
152
+ end
153
+
154
+ # Invokes the observer's method corresponding to the notification.
155
+ def accept(observer)
156
+ observer.on_completed
157
+ end
158
+
159
+ end
160
+
161
+ end