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,81 @@
1
+ module RxRuby
2
+ module Observable
3
+ def delay(due_time, scheduler = DefaultScheduler.instance)
4
+ if Time === due_time
5
+ delay_date(due_time, scheduler)
6
+ else
7
+ delay_time_span(due_time, scheduler)
8
+ end
9
+ end
10
+
11
+ private
12
+
13
+ def delay_time_span(due_time, scheduler)
14
+ AnonymousObservable.new do |observer|
15
+ active = false
16
+ cancelable = SerialSubscription.new
17
+ exception = nil
18
+ q = []
19
+ running = false
20
+ subscription = materialize.timestamp(scheduler).subscribe do |notification|
21
+ if notification[:value].on_error?
22
+ q = []
23
+ q.push notification
24
+ exception = notification[:value].error
25
+ should_run = !running
26
+ else
27
+ q.push({ value: notification[:value], timestamp: notification[:timestamp] + due_time })
28
+ should_run = !active
29
+ active = true
30
+ end
31
+
32
+ if should_run
33
+ if exception != nil
34
+ observer.on_error exception
35
+ else
36
+ d = SingleAssignmentSubscription.new
37
+ cancelable.subscription = d
38
+
39
+ d.subscription = scheduler.schedule_recursive_relative(due_time, lambda {|this|
40
+ return if exception != nil
41
+
42
+ running = true
43
+ begin
44
+ result = nil
45
+ if q.length > 0 && q[0][:timestamp] - scheduler.now <= 0
46
+ result = q.shift[:value]
47
+ end
48
+ if result != nil
49
+ result.accept observer
50
+ end
51
+ end while result != nil
52
+
53
+ should_recurse = false
54
+ recurse_due_time = 0
55
+ if q.length > 0
56
+ should_recurse = true
57
+ recurse_due_time = [0, q[0][:timestamp] - scheduler.now].max
58
+ else
59
+ active = false
60
+ end
61
+ e = exception
62
+ running = false
63
+ if e != nil
64
+ observer.on_error e
65
+ elsif should_recurse
66
+ this.call recurse_due_time
67
+ end
68
+ })
69
+ end
70
+ end
71
+ end
72
+
73
+ CompositeSubscription.new [subscription, cancelable]
74
+ end
75
+ end
76
+
77
+ def delay_date(due_time, scheduler)
78
+ delay_time_span(due_time - scheduler.now, scheduler)
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,64 @@
1
+ module RxRuby
2
+ module Observable
3
+ def delay_with_selector(subscription_delay, delay_duration_selector = nil)
4
+ if Proc === subscription_delay
5
+ selector = subscription_delay
6
+ else
7
+ sub_delay = subscription_delay
8
+ selector = delay_duration_selector
9
+ end
10
+
11
+ AnonymousObservable.new do |observer|
12
+ delays = CompositeSubscription.new
13
+ at_end = false
14
+ done = lambda {
15
+ if at_end && delays.length == 0
16
+ observer.on_completed
17
+ end
18
+ }
19
+ subscription = SerialSubscription.new
20
+ start = lambda {|*_|
21
+ subscription.subscription = subscribe(
22
+ lambda {|x|
23
+ begin
24
+ delay = selector.call(x)
25
+ rescue => error
26
+ observer.on_error error
27
+ return
28
+ end
29
+ d = SingleAssignmentSubscription.new
30
+ delays.push(d)
31
+ d.subscription = delay.subscribe(
32
+ lambda {|_|
33
+ observer.on_next x
34
+ delays.delete(d)
35
+ done.call
36
+ },
37
+ observer.method(:on_error),
38
+ lambda {
39
+ observer.on_next x
40
+ delays.delete(d)
41
+ done.call
42
+ })
43
+ },
44
+ observer.method(:on_error),
45
+ lambda {
46
+ at_end = true
47
+ subscription.dispose
48
+ done.call
49
+ })
50
+ }
51
+
52
+ if !sub_delay
53
+ start.call
54
+ else
55
+ subscription.subscription = sub_delay.subscribe(
56
+ start,
57
+ observer.method(:on_error),
58
+ start)
59
+ end
60
+ CompositeSubscription.new [subscription, delays]
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,42 @@
1
+ module RxRuby
2
+ module Observable
3
+ def do(observer_or_on_next = nil, on_error_func = nil, on_completed_func = nil)
4
+ if block_given?
5
+ on_next_func = Proc.new
6
+ elsif Proc === observer_or_on_next
7
+ on_next_func = observer_or_on_next
8
+ else
9
+ on_next_func = observer_or_on_next.method(:on_next)
10
+ on_error_func = observer_or_on_next.method(:on_error)
11
+ on_completed_func = observer_or_on_next.method(:on_completed)
12
+ end
13
+ AnonymousObservable.new do |observer|
14
+ subscribe(
15
+ lambda {|x|
16
+ begin
17
+ on_next_func.call x
18
+ rescue => e
19
+ observer.on_error e
20
+ end
21
+ observer.on_next x
22
+ },
23
+ lambda {|err|
24
+ begin
25
+ on_error_func && on_error_func.call(x)
26
+ rescue => e
27
+ observer.on_error e
28
+ end
29
+ observer.on_error err
30
+ },
31
+ lambda {
32
+ begin
33
+ on_completed_func && on_completed_func.call
34
+ rescue => e
35
+ observer.on_error e
36
+ end
37
+ observer.on_completed
38
+ })
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,13 @@
1
+ module RxRuby
2
+ class << Observable
3
+ def for(sources, result_selector = nil)
4
+ result_selector ||= lambda {|*args| args}
5
+ enum = Enumerator.new {|y|
6
+ sources.each {|v|
7
+ y << result_selector.call(v)
8
+ }
9
+ }
10
+ Observable.concat(enum)
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,55 @@
1
+ module RxRuby
2
+ class << Observable
3
+ def fork_join(*all_sources)
4
+ AnonymousObservable.new {|subscriber|
5
+ count = all_sources.length
6
+ if count == 0
7
+ subscriber.on_completed
8
+ Subscription.empty
9
+ end
10
+ group = CompositeSubscription.new
11
+ finished = false
12
+ has_results = Array.new(count)
13
+ has_completed = Array.new(count)
14
+ results = Array.new(count)
15
+
16
+ count.times {|i|
17
+ source = all_sources[i]
18
+ group.push(
19
+ source.subscribe(
20
+ lambda {|value|
21
+ if !finished
22
+ has_results[i] = true
23
+ results[i] = value
24
+ end
25
+ },
26
+ lambda {|e|
27
+ finished = true
28
+ subscriber.on_error e
29
+ group.dispose
30
+ },
31
+ lambda {
32
+ if !finished
33
+ if !has_results[i]
34
+ subscriber.on_completed
35
+ return
36
+ end
37
+ has_completed[i] = true
38
+ count.times {|ix|
39
+ if !has_completed[ix]
40
+ return
41
+ end
42
+ }
43
+ finished = true
44
+ subscriber.on_next results
45
+ subscriber.on_completed
46
+ end
47
+ }
48
+ )
49
+ )
50
+ }
51
+ group
52
+ }
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,34 @@
1
+ module RxRuby
2
+ class << Observable
3
+ def from(iterable, map_fn = nil, scheduler = CurrentThreadScheduler.instance)
4
+ it = iterable.to_enum
5
+ AnonymousObservable.new {|observer|
6
+ i = 0
7
+ scheduler.schedule_recursive lambda {|this|
8
+ begin
9
+ result = it.next
10
+ rescue StopIteration => e
11
+ observer.on_completed
12
+ return
13
+ rescue => e
14
+ observer.on_error e
15
+ return
16
+ end
17
+
18
+ if Proc === map_fn
19
+ begin
20
+ result = map_fn.call(result, i)
21
+ rescue => e
22
+ observer.on_error e
23
+ return
24
+ end
25
+ end
26
+
27
+ observer.on_next result
28
+ i += 1
29
+ this.call
30
+ }
31
+ }
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,108 @@
1
+ module RxRuby
2
+ module Observable
3
+ def group_join(right, left_duration_selector, right_duration_selector, result_selector)
4
+ AnonymousObservable.new do |observer|
5
+ group = CompositeSubscription.new
6
+ r = RefCountSubscription.new(group)
7
+ left_map = {}
8
+ right_map = {}
9
+ left_id = 0
10
+ right_id = 0
11
+
12
+ left_obs = Observer.configure do |o|
13
+ o.on_next {|value|
14
+ s = Subject.new
15
+ id = left_id
16
+ left_id += 1
17
+ left_map[id] = s
18
+
19
+ begin
20
+ result = result_selector.call(value, s.add_ref(r))
21
+ rescue => err
22
+ left_map.values.each {|v| v.on_error(err) }
23
+ observer.on_error(err)
24
+ next
25
+ end
26
+ observer.on_next(result)
27
+
28
+ right_map.values.each {|v| s.on_next(v) }
29
+
30
+ md = SingleAssignmentSubscription.new
31
+ group.push md
32
+
33
+ expire = lambda {
34
+ if left_map.delete(id)
35
+ s.on_completed
36
+ end
37
+ group.delete(md)
38
+ }
39
+
40
+ begin
41
+ duration = left_duration_selector.call(value)
42
+ rescue => err
43
+ left_map.values.each {|v| v.on_error(err) }
44
+ observer.on_error(err)
45
+ next
46
+ end
47
+
48
+ md.subscription = duration.take(1).subscribe(
49
+ lambda {|_| },
50
+ lambda {|e|
51
+ left_map.values.each {|v| v.on_error(e) }
52
+ observer.on_error(e)
53
+ },
54
+ expire)
55
+ }
56
+
57
+ o.on_error {|e|
58
+ left_map.values.each {|v| v.on_error(e) }
59
+ observer.on_error(e)
60
+ }
61
+
62
+ o.on_completed(&observer.method(:on_completed))
63
+ end
64
+ group.push self.subscribe(left_obs)
65
+
66
+ right_obs = Observer.configure do |o|
67
+ o.on_next {|value|
68
+ id = right_id
69
+ right_id += 1
70
+ right_map[id] = value
71
+
72
+ md = SingleAssignmentSubscription.new
73
+ group.push md
74
+
75
+ expire = lambda {
76
+ right_map.delete(id)
77
+ group.delete(md)
78
+ }
79
+
80
+ begin
81
+ duration = right_duration_selector.call(value)
82
+ rescue => err
83
+ right_map.values.each {|v| v.on_error(err) }
84
+ observer.on_error(err)
85
+ next
86
+ end
87
+
88
+ md.subscription = duration.take(1).subscribe(
89
+ lambda {|_| },
90
+ lambda {|e|
91
+ left_map.values.each {|v| v.on_error(e) }
92
+ observer.on_error(e)
93
+ },
94
+ expire)
95
+ }
96
+
97
+ o.on_error {|e|
98
+ left_map.values.each {|v| v.on_error(e) }
99
+ observer.on_error(e)
100
+ }
101
+ end
102
+ group.push right.subscribe(right_obs)
103
+
104
+ r
105
+ end
106
+ end
107
+ end
108
+ end
@@ -0,0 +1,17 @@
1
+ module RxRuby
2
+ class << Observable
3
+ def if(condition, then_source, else_source_or_scheduler = nil)
4
+ case else_source_or_scheduler
5
+ when Scheduler
6
+ scheduler = else_source_or_scheduler
7
+ else_source = Observable.empty(scheduler)
8
+ when Observable
9
+ else_source = else_source_or_scheduler
10
+ when nil
11
+ else_source = Observable.empty
12
+ end
13
+
14
+ return condition.call ? then_source : else_source
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,5 @@
1
+ module RxRuby::Observable
2
+ def self.interval(period, scheduler = RxRuby::DefaultScheduler.instance)
3
+ observable_timer_time_span_and_period(period, period, scheduler)
4
+ end
5
+ end
@@ -0,0 +1,14 @@
1
+ module RxRuby
2
+ module Observable
3
+ def multicast(subject_or_subject_selector, selector = nil)
4
+ if Proc === subject_or_subject_selector
5
+ AnonymousObservable.new do |observer|
6
+ connectable = self.multicast(subject_or_subject_selector.call)
7
+ CompositeSubscription.new [selector.call(connectable).subscribe(observer), self]
8
+ end
9
+ else
10
+ ConnectableObservable.new(self, subject_or_subject_selector)
11
+ end
12
+ end
13
+ end
14
+ end