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,9 @@
1
+ module RxRuby
2
+ module Observable
3
+ def add_ref(r)
4
+ AnonymousObservable.new do |observer|
5
+ CompositeSubscription.new [r.subscription, self.subscribe(observer)]
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,45 @@
1
+ module RxRuby
2
+ class ActivePlan
3
+ def initialize(join_observer_array, on_next, on_completed)
4
+ @join_observer_array = join_observer_array
5
+ @on_next = on_next
6
+ @on_completed = on_completed
7
+ @join_observers = {}
8
+ @join_observer_array.each {|x|
9
+ @join_observers[x] = x
10
+ }
11
+ end
12
+
13
+ def dequeue
14
+ @join_observers.each {|_, v| v.queue.shift }
15
+ end
16
+
17
+ def match
18
+ has_values = true
19
+ @join_observer_array.each {|v|
20
+ if v.queue.length == 0
21
+ has_values = false
22
+ break
23
+ end
24
+ }
25
+ if has_values
26
+ first_values = []
27
+ is_completed = false
28
+ @join_observer_array.each {|v|
29
+ first_values.push v.queue[0]
30
+ is_completed = true if v.queue[0].on_completed?
31
+ }
32
+ if is_completed
33
+ @on_completed.call
34
+ else
35
+ dequeue
36
+ values = []
37
+ first_values.each {|v|
38
+ values.push v.value
39
+ }
40
+ @on_next.call(*values)
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,51 @@
1
+ module RxRuby
2
+ class JoinObserver < ObserverBase
3
+
4
+ attr_reader :queue
5
+ def initialize(source, on_error)
6
+ super Observer.configure {|o|
7
+ o.on_next {|notification|
8
+ if !@is_disposed
9
+ if notification.on_error?
10
+ @on_error.call(notification.exception)
11
+ next
12
+ end
13
+ @queue.push notification
14
+ @active_plans.dup.each {|v|
15
+ v.match
16
+ }
17
+ end
18
+ }
19
+ }
20
+ @source = source
21
+ @on_error = on_error
22
+ @queue = []
23
+ @active_plans = []
24
+ @subscription = SingleAssignmentSubscription.new
25
+ @is_disposed = false
26
+ end
27
+
28
+ def add_active_plan(active_plan)
29
+ @active_plans.push active_plan
30
+ end
31
+
32
+ def subscribe
33
+ @subscription.subscription = @source.materialize.subscribe(@config)
34
+ end
35
+
36
+ def remove_active_plan(active_plan)
37
+ if idx = @active_plans.index(active_plan)
38
+ @active_plans.delete_at idx
39
+ end
40
+ self.unsubscribe if @active_plans.length == 0
41
+ end
42
+
43
+ def unsubscribe
44
+ super
45
+ if !@is_disposed
46
+ @is_disposed = true
47
+ @subscription.unsubscribe
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,14 @@
1
+ module RxRuby
2
+ class Pattern
3
+ attr_reader :patterns
4
+ def initialize(patterns)
5
+ @patterns = patterns
6
+ end
7
+ def and(other)
8
+ Pattern.new(@patterns.concat(other))
9
+ end
10
+ def then_do(selector = Proc.new)
11
+ Plan.new(self, selector)
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,44 @@
1
+ module RxRuby
2
+ class Plan
3
+ def initialize(expression, selector)
4
+ @expression = expression
5
+ @selector = selector
6
+ end
7
+
8
+ def activate(external_subscriptions, observer, deactivate)
9
+ join_observers = []
10
+ @expression.patterns.each {|pat|
11
+ join_observers.push plan_create_observer(external_subscriptions, pat, observer.method(:on_error))
12
+ }
13
+
14
+ active_plan = ActivePlan.new(join_observers, lambda {|*args|
15
+ begin
16
+ result = @selector.call(*args)
17
+ rescue => e
18
+ observer.on_error e
19
+ end
20
+ observer.on_next result
21
+ },
22
+ lambda {
23
+ join_observers.each {|v|
24
+ v.remove_active_plan(active_plan)
25
+ }
26
+ deactivate.call(active_plan)
27
+ })
28
+ join_observers.each {|v|
29
+ v.add_active_plan(active_plan)
30
+ }
31
+ return active_plan
32
+ end
33
+
34
+ def plan_create_observer(external_subscriptions, observable, on_error)
35
+ entry = external_subscriptions[observable]
36
+ if !entry
37
+ observer = JoinObserver.new(observable, on_error)
38
+ external_subscriptions[observable] = observer
39
+ return observer
40
+ end
41
+ entry
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,34 @@
1
+ module RxRuby
2
+ class ConnectableObservable < AnonymousObservable
3
+ def initialize(source, subject)
4
+ @has_subscription = false
5
+ @subscription = nil
6
+ @source_observable = source.as_observable
7
+ @subject = subject
8
+
9
+ super(&subject.method(:subscribe))
10
+ end
11
+
12
+ def connect
13
+ unless @has_subscription
14
+ @has_subscription = true
15
+ @subscription = CompositeSubscription.new [@source_observable.subscribe(@subject), Subscription.create { @has_subscription = false }]
16
+ end
17
+ @subscription
18
+ end
19
+
20
+ def ref_count
21
+ count = 0
22
+ AnonymousObservable.new do |observer|
23
+ count += 1
24
+ should_connect = true if count == 1
25
+ connectable_subscription = self.connect if should_connect
26
+ Subscription.create {
27
+ @subscription.unsubscribe
28
+ count -= 1
29
+ connectable_subscription.unsubscribe if count == 0
30
+ }
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,22 @@
1
+ module RxRuby
2
+ class << Observable
3
+ private
4
+ def observable_timer_date_and_period(due_time, period, scheduler)
5
+ AnonymousObservable.new do |observer|
6
+ count = 0
7
+ d = due_time
8
+ p = Scheduler.normalize(period)
9
+ scheduler.schedule_recursive_absolute(d, lambda {|this|
10
+ if p > 0
11
+ now = scheduler.now()
12
+ d = d + p
13
+ d <= now && (d = now + p)
14
+ end
15
+ observer.on_next(count)
16
+ count += 1
17
+ this.call(d)
18
+ })
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,14 @@
1
+ module RxRuby
2
+ class << Observable
3
+ private
4
+ def observable_timer_time_span(due_time, scheduler)
5
+ AnonymousObservable.new do |observer|
6
+ scheduler.schedule_relative(Scheduler.normalize(due_time),
7
+ lambda {
8
+ observer.on_next(0)
9
+ observer.on_completed
10
+ })
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,20 @@
1
+ module RxRuby
2
+ class << Observable
3
+ private
4
+ def observable_timer_time_span_and_period(due_time, period, scheduler)
5
+ if due_time == period
6
+ AnonymousObservable.new do |observer|
7
+ scheduler.schedule_periodic_with_state(0, period,
8
+ lambda {|count|
9
+ observer.on_next(count)
10
+ count + 1
11
+ })
12
+ end
13
+ else
14
+ Observable.defer {
15
+ observable_timer_date_and_period(scheduler.now() + due_time, period, scheduler)
16
+ }
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,7 @@
1
+ require 'rx_ruby/operators/aggregates.rb'
2
+
3
+ module RxRuby
4
+ module Observable
5
+ alias :aggregate :reduce
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ module RxRuby
2
+ module Observable
3
+ def and(right)
4
+ Pattern.new([self, right]);
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,15 @@
1
+ module RxRuby
2
+ class << Observable
3
+ def case(selector, sources, defaultSourceOrScheduler = Observable.empty)
4
+ defer {
5
+ if Scheduler === defaultSourceOrScheduler
6
+ defaultSourceOrScheduler = Observable.empty(defaultSourceOrScheduler)
7
+ end
8
+
9
+ result = sources[selector.call]
10
+ result || defaultSourceOrScheduler
11
+ }
12
+ end
13
+ alias :switchCase :case
14
+ end
15
+ end
@@ -0,0 +1,7 @@
1
+ module RxRuby
2
+ module Observable
3
+ def concat_all
4
+ merge_concurrent(1)
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,35 @@
1
+ module RxRuby
2
+ module Observable
3
+ def concat_map(selector, result_selector = nil)
4
+ if Proc === result_selector
5
+ return concat_map(lambda {|x, i|
6
+ selector_result = selector.call(x, i)
7
+ if selector_result.respond_to?(:each)
8
+ selector_result = Observable.from(selector_result)
9
+ end
10
+ selector_result.map_with_index {|y, i2|
11
+ result_selector.call(x, y, i, i2)
12
+ }
13
+ })
14
+ end
15
+
16
+ if Proc === selector
17
+ _concat_map(selector)
18
+ else
19
+ _concat_map(lambda {|*_| selector })
20
+ end
21
+ end
22
+
23
+ private
24
+
25
+ def _concat_map(selector)
26
+ map_with_index {|x, i|
27
+ result = selector.call(x, i)
28
+ if result.respond_to?(:each)
29
+ result = Observable.from(result)
30
+ end
31
+ result
32
+ }.concat_all
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,43 @@
1
+ module RxRuby
2
+ module Observable
3
+ def concat_map_observer(on_next, on_error, on_completed)
4
+ AnonymousObservable.new do |observer|
5
+ index = 0
6
+
7
+ subscribe(
8
+ lambda {|x|
9
+ begin
10
+ result = on_next.call(x, index)
11
+ index += 1
12
+ rescue => e
13
+ observer.on_error e
14
+ return
15
+ end
16
+ observer.on_next result
17
+ },
18
+ lambda {|err|
19
+ begin
20
+ result = on_error.call(err)
21
+ rescue => e
22
+ observer.on_error e
23
+ return
24
+ end
25
+
26
+ observer.on_next result
27
+ observer.on_completed
28
+ },
29
+ lambda {
30
+ begin
31
+ result = on_completed.call
32
+ rescue => e
33
+ observer.on_error e
34
+ return
35
+ end
36
+
37
+ observer.on_next result
38
+ observer.on_completed
39
+ })
40
+ end.concat_all
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,28 @@
1
+ module RxRuby
2
+ module Observable
3
+ def contains(search_element, from_index = 0)
4
+ AnonymousObservable.new do |observer|
5
+ i = 0
6
+ n = from_index
7
+ if n < 0
8
+ observer.on_next false
9
+ observer.on_completed
10
+ return Subscription.empty
11
+ end
12
+
13
+ subscribe(
14
+ lambda {|x|
15
+ if i.tap { i += 1 } >= n && x == search_element
16
+ observer.on_next true
17
+ observer.on_completed
18
+ end
19
+ },
20
+ observer.method(:on_error),
21
+ lambda {
22
+ observer.on_next false
23
+ observer.on_completed
24
+ })
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,41 @@
1
+ module RxRuby
2
+ module Observable
3
+ def debounce(due_time, scheduler = DefaultScheduler.instance)
4
+ AnonymousObservable.new do |observer|
5
+ cancelable = SerialSubscription.new
6
+ hasvalue = false
7
+ value = nil
8
+ id = 0
9
+
10
+ subscription = subscribe(
11
+ lambda {|x|
12
+ hasvalue = true
13
+ value = x
14
+ id += 1
15
+ current_id = id
16
+ d = SingleAssignmentSubscription.new
17
+ cancelable.subscription = d
18
+ d.subscription = scheduler.schedule_relative(due_time, lambda {
19
+ observer.on_next value if hasvalue && id == current_id
20
+ hasvalue = false
21
+ })
22
+ },
23
+ lambda {|e|
24
+ cancelable.dispose
25
+ observer.on_error e
26
+ hasvalue = false
27
+ id += 1
28
+ },
29
+ lambda {
30
+ cancelable.dispose
31
+ observer.on_next value if hasvalue
32
+ observer.on_completed
33
+ hasvalue = false
34
+ id += 1
35
+ })
36
+
37
+ CompositeSubscription.new [subscription, cancelable]
38
+ end
39
+ end
40
+ end
41
+ end