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.
- checksums.yaml +7 -0
- data/.gitattributes +22 -0
- data/.gitignore +173 -0
- data/.travis.yml +10 -0
- data/Gemfile +4 -0
- data/Rakefile +11 -0
- data/examples/aggregate.rb +39 -0
- data/examples/amb.rb +25 -0
- data/examples/ambproto.rb +24 -0
- data/examples/and.rb +26 -0
- data/examples/as_observable.rb +25 -0
- data/examples/average.rb +43 -0
- data/examples/buffer_with_count.rb +44 -0
- data/examples/buffer_with_time.rb +51 -0
- data/examples/case.rb +29 -0
- data/examples/catch.rb +20 -0
- data/examples/catchproto.rb +39 -0
- data/examples/combine_latest.rb +35 -0
- data/examples/combine_latestproto.rb +33 -0
- data/examples/concat.rb +22 -0
- data/examples/concat_all.rb +27 -0
- data/examples/concat_map.rb +61 -0
- data/examples/concat_map_observer.rb +29 -0
- data/examples/concatproto.rb +25 -0
- data/examples/connect.rb +41 -0
- data/examples/contains.rb +37 -0
- data/examples/count.rb +36 -0
- data/examples/create.rb +55 -0
- data/examples/debounce.rb +35 -0
- data/examples/default_if_empty.rb +35 -0
- data/examples/defer.rb +20 -0
- data/examples/delay.rb +49 -0
- data/examples/delay_with_selector.rb +63 -0
- data/examples/dematerialize.rb +22 -0
- data/examples/disposable.rb +12 -0
- data/examples/distinct.rb +43 -0
- data/examples/distinct_until_changed.rb +43 -0
- data/examples/do.rb +59 -0
- data/examples/empty.rb +16 -0
- data/examples/for.rb +26 -0
- data/examples/fork_join.rb +23 -0
- data/examples/from.rb +106 -0
- data/examples/from_array.rb +21 -0
- data/examples/from_callback.rb +21 -0
- data/examples/generate.rb +24 -0
- data/examples/group_join.rb +39 -0
- data/examples/if.rb +46 -0
- data/examples/intervals.rb +26 -0
- data/examples/merge.rb +36 -0
- data/examples/merge_all.rb +27 -0
- data/examples/multicast.rb +32 -0
- data/examples/never.rb +15 -0
- data/examples/of.rb +19 -0
- data/examples/on_error_resume_next.rb +21 -0
- data/examples/pairs.rb +26 -0
- data/examples/publish.rb +79 -0
- data/examples/range.rb +19 -0
- data/examples/reduce.rb +18 -0
- data/examples/repeat.rb +19 -0
- data/examples/return.rb +17 -0
- data/examples/scan.rb +41 -0
- data/examples/start.rb +29 -0
- data/examples/throw.rb +17 -0
- data/examples/time_intervals.rb +28 -0
- data/examples/timer.rb +26 -0
- data/examples/timestamp.rb +28 -0
- data/examples/to_a.rb +23 -0
- data/examples/to_async.rb +26 -0
- data/examples/using.rb +52 -0
- data/examples/when.rb +26 -0
- data/examples/while.rb +25 -0
- data/examples/window_with_time.rb +78 -0
- data/examples/zip.rb +27 -0
- data/examples/zip_array.rb +25 -0
- data/lib/core_ext/enumerable.rb +22 -0
- data/lib/rx_ruby.rb +27 -0
- data/lib/rx_ruby/concurrency/async_lock.rb +57 -0
- data/lib/rx_ruby/concurrency/current_thread_scheduler.rb +75 -0
- data/lib/rx_ruby/concurrency/default_scheduler.rb +51 -0
- data/lib/rx_ruby/concurrency/historical_scheduler.rb +16 -0
- data/lib/rx_ruby/concurrency/immediate_scheduler.rb +68 -0
- data/lib/rx_ruby/concurrency/local_scheduler.rb +39 -0
- data/lib/rx_ruby/concurrency/periodic_scheduler.rb +74 -0
- data/lib/rx_ruby/concurrency/scheduled_item.rb +42 -0
- data/lib/rx_ruby/concurrency/scheduler.rb +150 -0
- data/lib/rx_ruby/concurrency/virtual_time_scheduler.rb +170 -0
- data/lib/rx_ruby/core/async_lock_observer.rb +46 -0
- data/lib/rx_ruby/core/auto_detach_observer.rb +59 -0
- data/lib/rx_ruby/core/checked_observer.rb +66 -0
- data/lib/rx_ruby/core/notification.rb +161 -0
- data/lib/rx_ruby/core/observable.rb +104 -0
- data/lib/rx_ruby/core/observe_on_observer.rb +50 -0
- data/lib/rx_ruby/core/observer.rb +119 -0
- data/lib/rx_ruby/core/scheduled_observer.rb +83 -0
- data/lib/rx_ruby/core/synchronized_observer.rb +47 -0
- data/lib/rx_ruby/core/time_interval.rb +17 -0
- data/lib/rx_ruby/internal/priority_queue.rb +122 -0
- data/lib/rx_ruby/internal/util.rb +9 -0
- data/lib/rx_ruby/joins/active_plan.rb +45 -0
- data/lib/rx_ruby/joins/join_observer.rb +51 -0
- data/lib/rx_ruby/joins/pattern.rb +14 -0
- data/lib/rx_ruby/joins/plan.rb +44 -0
- data/lib/rx_ruby/linq/connectable_observable.rb +34 -0
- data/lib/rx_ruby/linq/observable/_observable_timer_date_and_period.rb +22 -0
- data/lib/rx_ruby/linq/observable/_observable_timer_time_span.rb +14 -0
- data/lib/rx_ruby/linq/observable/_observable_timer_time_span_and_period.rb +20 -0
- data/lib/rx_ruby/linq/observable/aggregate.rb +7 -0
- data/lib/rx_ruby/linq/observable/and.rb +7 -0
- data/lib/rx_ruby/linq/observable/case.rb +15 -0
- data/lib/rx_ruby/linq/observable/concat_all.rb +7 -0
- data/lib/rx_ruby/linq/observable/concat_map.rb +35 -0
- data/lib/rx_ruby/linq/observable/concat_map_observer.rb +43 -0
- data/lib/rx_ruby/linq/observable/contains.rb +28 -0
- data/lib/rx_ruby/linq/observable/debounce.rb +41 -0
- data/lib/rx_ruby/linq/observable/delay.rb +81 -0
- data/lib/rx_ruby/linq/observable/delay_with_selector.rb +64 -0
- data/lib/rx_ruby/linq/observable/do.rb +42 -0
- data/lib/rx_ruby/linq/observable/for.rb +13 -0
- data/lib/rx_ruby/linq/observable/fork_join.rb +55 -0
- data/lib/rx_ruby/linq/observable/from.rb +34 -0
- data/lib/rx_ruby/linq/observable/group_join.rb +108 -0
- data/lib/rx_ruby/linq/observable/if.rb +17 -0
- data/lib/rx_ruby/linq/observable/interval.rb +5 -0
- data/lib/rx_ruby/linq/observable/multicast.rb +14 -0
- data/lib/rx_ruby/linq/observable/of.rb +11 -0
- data/lib/rx_ruby/linq/observable/pairs.rb +7 -0
- data/lib/rx_ruby/linq/observable/pluck.rb +7 -0
- data/lib/rx_ruby/linq/observable/publish.rb +11 -0
- data/lib/rx_ruby/linq/observable/start.rb +7 -0
- data/lib/rx_ruby/linq/observable/time_interval.rb +15 -0
- data/lib/rx_ruby/linq/observable/timer.rb +26 -0
- data/lib/rx_ruby/linq/observable/timestamp.rb +9 -0
- data/lib/rx_ruby/linq/observable/to_async.rb +40 -0
- data/lib/rx_ruby/linq/observable/when.rb +36 -0
- data/lib/rx_ruby/linq/observable/while.rb +41 -0
- data/lib/rx_ruby/operators/aggregates.rb +611 -0
- data/lib/rx_ruby/operators/creation.rb +220 -0
- data/lib/rx_ruby/operators/multiple.rb +735 -0
- data/lib/rx_ruby/operators/single.rb +399 -0
- data/lib/rx_ruby/operators/standard_query_operators.rb +279 -0
- data/lib/rx_ruby/operators/synchronization.rb +47 -0
- data/lib/rx_ruby/operators/time.rb +120 -0
- data/lib/rx_ruby/subjects/async_subject.rb +161 -0
- data/lib/rx_ruby/subjects/behavior_subject.rb +149 -0
- data/lib/rx_ruby/subjects/replay_subject.rb +39 -0
- data/lib/rx_ruby/subjects/subject.rb +131 -0
- data/lib/rx_ruby/subjects/subject_extensions.rb +45 -0
- data/lib/rx_ruby/subscriptions/composite_subscription.rb +91 -0
- data/lib/rx_ruby/subscriptions/ref_count_subscription.rb +88 -0
- data/lib/rx_ruby/subscriptions/scheduled_subscription.rb +32 -0
- data/lib/rx_ruby/subscriptions/serial_subscription.rb +60 -0
- data/lib/rx_ruby/subscriptions/single_assignment_subscription.rb +64 -0
- data/lib/rx_ruby/subscriptions/subscription.rb +56 -0
- data/lib/rx_ruby/testing/cold_observable.rb +45 -0
- data/lib/rx_ruby/testing/hot_observable.rb +47 -0
- data/lib/rx_ruby/testing/mock_observer.rb +33 -0
- data/lib/rx_ruby/testing/reactive_test.rb +94 -0
- data/lib/rx_ruby/testing/recorded.rb +17 -0
- data/lib/rx_ruby/testing/test_scheduler.rb +96 -0
- data/lib/rx_ruby/testing/test_subscription.rb +22 -0
- data/lib/rx_ruby/version.rb +3 -0
- data/license.txt +13 -0
- data/readme.md +152 -0
- data/rx_ruby.gemspec +22 -0
- data/test/rx_ruby/concurrency/helpers/historical_virtual_scheduler_helper.rb +135 -0
- data/test/rx_ruby/concurrency/helpers/immediate_local_scheduler_helper.rb +51 -0
- data/test/rx_ruby/concurrency/test_async_lock.rb +56 -0
- data/test/rx_ruby/concurrency/test_current_thread_scheduler.rb +44 -0
- data/test/rx_ruby/concurrency/test_default_scheduler.rb +44 -0
- data/test/rx_ruby/concurrency/test_historical_scheduler.rb +18 -0
- data/test/rx_ruby/concurrency/test_immediate_scheduler.rb +53 -0
- data/test/rx_ruby/concurrency/test_local_scheduler.rb +12 -0
- data/test/rx_ruby/concurrency/test_periodic_scheduler.rb +53 -0
- data/test/rx_ruby/concurrency/test_scheduled_item.rb +50 -0
- data/test/rx_ruby/concurrency/test_scheduler.rb +128 -0
- data/test/rx_ruby/concurrency/test_virtual_time_scheduler.rb +14 -0
- data/test/rx_ruby/core/test_notification.rb +129 -0
- data/test/rx_ruby/core/test_observable_creation.rb +483 -0
- data/test/rx_ruby/core/test_observer.rb +634 -0
- data/test/rx_ruby/internal/test_priority_queue.rb +71 -0
- data/test/rx_ruby/subscriptions/test_composite_subscription.rb +116 -0
- data/test/rx_ruby/subscriptions/test_serial_subscription.rb +62 -0
- data/test/rx_ruby/subscriptions/test_singleassignment_subscription.rb +61 -0
- data/test/rx_ruby/subscriptions/test_subscription.rb +27 -0
- data/test/test_helper.rb +11 -0
- metadata +291 -0
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'rx_ruby'
|
2
|
+
|
3
|
+
func = RxRuby::Observable.to_async(lambda {|x, y|
|
4
|
+
return x + y
|
5
|
+
})
|
6
|
+
|
7
|
+
# Execute function with 3 and 4
|
8
|
+
source = func.call(3, 4)
|
9
|
+
|
10
|
+
subscription = source.subscribe(
|
11
|
+
lambda {|x|
|
12
|
+
puts 'Next: ' + x.to_s
|
13
|
+
},
|
14
|
+
lambda {|err|
|
15
|
+
puts 'Error: ' + err.to_s
|
16
|
+
},
|
17
|
+
lambda {
|
18
|
+
puts 'Completed'
|
19
|
+
})
|
20
|
+
|
21
|
+
# => Next: 7
|
22
|
+
# => Completed
|
23
|
+
|
24
|
+
while Thread.list.size > 1
|
25
|
+
(Thread.list - [Thread.current]).each &:join
|
26
|
+
end
|
data/examples/using.rb
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'rx_ruby'
|
2
|
+
|
3
|
+
# Using an AsyncSubject as a resource which supports the .dispose method
|
4
|
+
class DisposableResource
|
5
|
+
def initialize(value, disposed = false)
|
6
|
+
@value = value
|
7
|
+
@disposed = disposed
|
8
|
+
end
|
9
|
+
|
10
|
+
def value
|
11
|
+
if @disposed
|
12
|
+
throw Exception.new('Object is disposed')
|
13
|
+
end
|
14
|
+
@value
|
15
|
+
end
|
16
|
+
|
17
|
+
def unsubscribe
|
18
|
+
unless @disposed
|
19
|
+
@disposed = true
|
20
|
+
@value = nil
|
21
|
+
end
|
22
|
+
puts 'Disposed'
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
source = RxRuby::Observable.using(
|
27
|
+
lambda { return DisposableResource.new(42) },
|
28
|
+
lambda {|resource|
|
29
|
+
subject = RxRuby::AsyncSubject.new
|
30
|
+
subject.on_next(resource.value)
|
31
|
+
subject.on_completed
|
32
|
+
return subject
|
33
|
+
}
|
34
|
+
)
|
35
|
+
|
36
|
+
subscription = source.subscribe(
|
37
|
+
lambda {|x|
|
38
|
+
puts 'Next: ' + x.to_s
|
39
|
+
},
|
40
|
+
lambda {|err|
|
41
|
+
puts 'Error: ' + err.to_s
|
42
|
+
},
|
43
|
+
lambda {
|
44
|
+
puts 'Completed'
|
45
|
+
})
|
46
|
+
|
47
|
+
# => Next: 42
|
48
|
+
# => Completed
|
49
|
+
|
50
|
+
subscription.dispose
|
51
|
+
|
52
|
+
# => Disposed
|
data/examples/when.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'rx_ruby'
|
2
|
+
|
3
|
+
# Fire each plan when both are ready
|
4
|
+
source = RxRuby::Observable.when(
|
5
|
+
RxRuby::Observable.timer(0.1).and(RxRuby::Observable.timer(0.5)).then_do(lambda {|x, y| return 'first' }),
|
6
|
+
RxRuby::Observable.timer(0.4).and(RxRuby::Observable.timer(0.3)).then_do {|x, y| 'second' }
|
7
|
+
)
|
8
|
+
|
9
|
+
subscription = source.subscribe(
|
10
|
+
lambda {|x|
|
11
|
+
puts 'Next: ' + x.to_s
|
12
|
+
},
|
13
|
+
lambda {|err|
|
14
|
+
puts 'Error: ' + err.to_s
|
15
|
+
},
|
16
|
+
lambda {
|
17
|
+
puts 'Completed'
|
18
|
+
})
|
19
|
+
|
20
|
+
# => Next: second
|
21
|
+
# => Next: first
|
22
|
+
# => Completed
|
23
|
+
|
24
|
+
while Thread.list.size > 1
|
25
|
+
(Thread.list - [Thread.current]).each &:join
|
26
|
+
end
|
data/examples/while.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'rx_ruby'
|
2
|
+
|
3
|
+
i = 0
|
4
|
+
|
5
|
+
# Repeat until condition no longer holds
|
6
|
+
source = RxRuby::Observable.while(
|
7
|
+
lambda { i += 1; i <= 3 },
|
8
|
+
RxRuby::Observable.return(42)
|
9
|
+
)
|
10
|
+
|
11
|
+
subscription = source.subscribe(
|
12
|
+
lambda {|x|
|
13
|
+
puts 'Next: ' + x.to_s
|
14
|
+
},
|
15
|
+
lambda {|err|
|
16
|
+
puts 'Error: ' + err.to_s
|
17
|
+
},
|
18
|
+
lambda {
|
19
|
+
puts 'Completed'
|
20
|
+
})
|
21
|
+
|
22
|
+
# => Next: 42
|
23
|
+
# => Next: 42
|
24
|
+
# => Next: 42
|
25
|
+
# => Completed
|
@@ -0,0 +1,78 @@
|
|
1
|
+
require 'rx_ruby'
|
2
|
+
|
3
|
+
# Without a skip
|
4
|
+
source = RxRuby::Observable.interval(0.1)
|
5
|
+
.window_with_time(0.5)
|
6
|
+
.take(3)
|
7
|
+
|
8
|
+
subscription = source.subscribe(
|
9
|
+
lambda {|child|
|
10
|
+
child.to_a.subscribe(
|
11
|
+
lambda {|x|
|
12
|
+
puts 'Child Next: ' + x.to_s
|
13
|
+
},
|
14
|
+
lambda {|err|
|
15
|
+
puts 'Child Error: ' + err.to_s
|
16
|
+
},
|
17
|
+
lambda {
|
18
|
+
puts 'Child Completed'
|
19
|
+
}
|
20
|
+
)
|
21
|
+
},
|
22
|
+
lambda {|err|
|
23
|
+
puts 'Error: ' + err.to_s
|
24
|
+
},
|
25
|
+
lambda {
|
26
|
+
puts 'Completed'
|
27
|
+
})
|
28
|
+
|
29
|
+
# => Child Next: [0, 1, 2, 3]
|
30
|
+
# => Child Completed
|
31
|
+
# => Completed
|
32
|
+
# => Child Next: [4, 5, 6, 7, 8]
|
33
|
+
# => Child Completed
|
34
|
+
# => Child Next: [9, 10, 11, 12, 13]
|
35
|
+
# => Child Completed
|
36
|
+
|
37
|
+
while Thread.list.size > 1
|
38
|
+
(Thread.list - [Thread.current]).each &:join
|
39
|
+
end
|
40
|
+
|
41
|
+
# Using a skip
|
42
|
+
source = RxRuby::Observable.interval(0.1)
|
43
|
+
.window_with_time(0.5, 0.1)
|
44
|
+
.take(3)
|
45
|
+
|
46
|
+
subscription = source.subscribe(
|
47
|
+
lambda {|child|
|
48
|
+
|
49
|
+
child.to_a.subscribe(
|
50
|
+
lambda {|x|
|
51
|
+
puts 'Child Next: ' + x.to_s
|
52
|
+
},
|
53
|
+
lambda {|err|
|
54
|
+
puts 'Child Error: ' + err.to_s
|
55
|
+
},
|
56
|
+
lambda {
|
57
|
+
puts 'Child Completed'
|
58
|
+
}
|
59
|
+
)
|
60
|
+
},
|
61
|
+
lambda {|err|
|
62
|
+
puts 'Error: ' + err.to_s
|
63
|
+
},
|
64
|
+
lambda {
|
65
|
+
puts 'Completed'
|
66
|
+
})
|
67
|
+
|
68
|
+
# => Completed
|
69
|
+
# => Child Next: [0, 1, 2, 3, 4]
|
70
|
+
# => Child Completed
|
71
|
+
# => Child Next: [1, 2, 3, 4, 5]
|
72
|
+
# => Child Completed
|
73
|
+
# => Child Next: [2, 3, 4, 5, 6]
|
74
|
+
# => Child Completed
|
75
|
+
|
76
|
+
while Thread.list.size > 1
|
77
|
+
(Thread.list - [Thread.current]).each &:join
|
78
|
+
end
|
data/examples/zip.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'rx_ruby'
|
2
|
+
|
3
|
+
# Using arguments
|
4
|
+
range = RxRuby::Observable.range(0, 5)
|
5
|
+
|
6
|
+
source = RxRuby::Observable.zip(
|
7
|
+
range,
|
8
|
+
range.skip(1),
|
9
|
+
range.skip(2)) {|s1, s2, s3|
|
10
|
+
s1.to_s + ':' + s2.to_s + ':' + s3.to_s
|
11
|
+
}
|
12
|
+
|
13
|
+
subscription = source.subscribe(
|
14
|
+
lambda {|x|
|
15
|
+
puts 'Next: ' + x.to_s
|
16
|
+
},
|
17
|
+
lambda {|err|
|
18
|
+
puts 'Error: ' + err.to_s
|
19
|
+
},
|
20
|
+
lambda {
|
21
|
+
puts 'Completed'
|
22
|
+
})
|
23
|
+
|
24
|
+
# => Next: 0:1:2
|
25
|
+
# => Next: 1:2:3
|
26
|
+
# => Next: 2:3:4
|
27
|
+
# => Completed
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'rx_ruby'
|
2
|
+
|
3
|
+
range = RxRuby::Observable.range(0, 5)
|
4
|
+
|
5
|
+
source = RxRuby::Observable.zip(
|
6
|
+
range,
|
7
|
+
range.skip(1),
|
8
|
+
range.skip(2)
|
9
|
+
)
|
10
|
+
|
11
|
+
subscription = source.subscribe(
|
12
|
+
lambda {|x|
|
13
|
+
puts 'Next: ' + x.to_s
|
14
|
+
},
|
15
|
+
lambda {|err|
|
16
|
+
puts 'Error: ' + err.to_s
|
17
|
+
},
|
18
|
+
lambda {
|
19
|
+
puts 'Completed'
|
20
|
+
})
|
21
|
+
|
22
|
+
# => Next: [0, 1, 2]
|
23
|
+
# => Next: [1, 2, 3]
|
24
|
+
# => Next: [2, 3, 4]
|
25
|
+
# => Completed
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Enumerable
|
2
|
+
def subscribe(observer, scheduler = RxRuby::ImmediateScheduler.instance)
|
3
|
+
begin
|
4
|
+
self.each do |e|
|
5
|
+
scheduler.schedule lambda {
|
6
|
+
observer.on_next(e)
|
7
|
+
}
|
8
|
+
end
|
9
|
+
rescue => ex
|
10
|
+
observer.on_error(ex)
|
11
|
+
return
|
12
|
+
end
|
13
|
+
|
14
|
+
observer.on_completed
|
15
|
+
end
|
16
|
+
|
17
|
+
def to_observable(scheduler = RxRuby::ImmediateScheduler.instance)
|
18
|
+
RxRuby::AnonymousObservable.new do |observer|
|
19
|
+
self.subscribe(observer, scheduler)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
data/lib/rx_ruby.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
2
|
+
|
3
|
+
$:.unshift File.dirname(__FILE__) # For use/testing when no gem is installed
|
4
|
+
|
5
|
+
# Require all of the Ruby files in the given directory.
|
6
|
+
#
|
7
|
+
# path - The String relative path from here to the directory.
|
8
|
+
#
|
9
|
+
# Returns nothing.
|
10
|
+
def require_all(path)
|
11
|
+
glob = File.join(File.dirname(__FILE__), path, '*.rb')
|
12
|
+
Dir[glob].sort.each do |f|
|
13
|
+
require f
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
require_all 'rx_ruby/internal/'
|
18
|
+
require_all 'rx_ruby/concurrency/'
|
19
|
+
require_all 'rx_ruby/subscriptions/'
|
20
|
+
require_all 'rx_ruby/core/'
|
21
|
+
require_all 'rx_ruby/linq/'
|
22
|
+
require_all 'rx_ruby/linq/observable/'
|
23
|
+
require_all 'rx_ruby/operators/'
|
24
|
+
require_all 'rx_ruby/subjects/'
|
25
|
+
require_all 'rx_ruby/testing/'
|
26
|
+
require_all 'rx_ruby/joins/'
|
27
|
+
require_all 'rx_ruby/'
|
@@ -0,0 +1,57 @@
|
|
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
|
+
|
5
|
+
module RxRuby
|
6
|
+
# Asynchronous lock.
|
7
|
+
class AsyncLock
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
@queue = []
|
11
|
+
@is_acquired = false
|
12
|
+
@has_faulted = false
|
13
|
+
@gate = Mutex.new
|
14
|
+
end
|
15
|
+
|
16
|
+
def wait(&action)
|
17
|
+
@gate.synchronize do
|
18
|
+
@queue.push action unless @has_faulted
|
19
|
+
|
20
|
+
if @is_acquired or @has_faulted
|
21
|
+
return
|
22
|
+
else
|
23
|
+
@is_acquired = true
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
loop do
|
28
|
+
work = nil
|
29
|
+
|
30
|
+
@gate.synchronize do
|
31
|
+
work = @queue.shift
|
32
|
+
|
33
|
+
unless work
|
34
|
+
@is_acquired = false
|
35
|
+
return
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
begin
|
40
|
+
work.call
|
41
|
+
rescue
|
42
|
+
clear
|
43
|
+
raise
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# Clears the work items in the queue and drops further work being queued.
|
49
|
+
def clear
|
50
|
+
@gate.synchronize do
|
51
|
+
@queue = []
|
52
|
+
@has_faulted = true
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
# Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
2
|
+
|
3
|
+
require 'singleton'
|
4
|
+
require 'thread'
|
5
|
+
require 'rx_ruby/internal/priority_queue'
|
6
|
+
require 'rx_ruby/concurrency/local_scheduler'
|
7
|
+
require 'rx_ruby/concurrency/scheduled_item'
|
8
|
+
require 'rx_ruby/subscriptions/subscription'
|
9
|
+
|
10
|
+
module RxRuby
|
11
|
+
|
12
|
+
# Represents an object that schedules units of work on the platform's default scheduler.
|
13
|
+
class CurrentThreadScheduler < RxRuby::LocalScheduler
|
14
|
+
|
15
|
+
include Singleton
|
16
|
+
|
17
|
+
@@thread_local_queue = nil
|
18
|
+
|
19
|
+
# Gets a value that indicates whether the caller must call a Schedule method.
|
20
|
+
def self.schedule_required?
|
21
|
+
@@thread_local_queue.nil?
|
22
|
+
end
|
23
|
+
|
24
|
+
# Schedules an action to be executed after dueTime.
|
25
|
+
def schedule_relative_with_state(state, due_time, action)
|
26
|
+
raise 'action cannot be nil' unless action
|
27
|
+
|
28
|
+
dt = self.now.to_i + Scheduler.normalize(due_time)
|
29
|
+
si = ScheduledItem.new self, state, dt, &action
|
30
|
+
|
31
|
+
local_queue = self.class.queue
|
32
|
+
|
33
|
+
unless local_queue
|
34
|
+
local_queue = PriorityQueue.new
|
35
|
+
local_queue.push si
|
36
|
+
|
37
|
+
self.class.queue = local_queue
|
38
|
+
|
39
|
+
begin
|
40
|
+
self.class.run_trampoline local_queue
|
41
|
+
ensure
|
42
|
+
self.class.queue = nil
|
43
|
+
end
|
44
|
+
else
|
45
|
+
local_queue.push si
|
46
|
+
end
|
47
|
+
|
48
|
+
Subscription.create { si.cancel }
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
class << self
|
54
|
+
def queue
|
55
|
+
@@thread_local_queue
|
56
|
+
end
|
57
|
+
|
58
|
+
def queue=(new_queue)
|
59
|
+
@@thread_local_queue = new_queue
|
60
|
+
end
|
61
|
+
|
62
|
+
def run_trampoline(queue)
|
63
|
+
while item = queue.shift
|
64
|
+
unless item.cancelled?
|
65
|
+
wait = item.due_time - Scheduler.now.to_i
|
66
|
+
sleep wait if wait > 0
|
67
|
+
item.invoke unless item.cancelled?
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
end
|