rosarium 0.1.5 → 0.1.6
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 +5 -5
- data/Gemfile +3 -0
- data/Gemfile.lock +34 -13
- data/lib/rosarium.rb +2 -1
- data/lib/rosarium/deferred.rb +3 -5
- data/lib/rosarium/fixed_thread_executor.rb +9 -11
- data/lib/rosarium/promise.rb +165 -18
- data/spec/promise_static_spec.rb +0 -5
- metadata +21 -9
- data/lib/rosarium/simple_promise.rb +0 -164
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 7953c9f3adbdebbd4299ddef80c064fe76f32fe74e8bd8abafd160d0f9b6d816
|
4
|
+
data.tar.gz: 80b937b9e1e8750f1bbac9a9913a0e129b5dc80048d97b3ea360774b02eb1e2e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 22821d81eaccb0357841982eb2095c57e58f786d535834600b5903719c180d91af364b9e8778ac1256236d19db95835262fd77b8c313bedafdf60ae0e04a7579
|
7
|
+
data.tar.gz: 34ac659ece6ea48a111db7dab0ea89f8c0adcf90cfcf0802aaecba89eec49b1e8831fb9d55147691c4b686e51c1e68e38164fcd6dd27b4464fd5363ca802bcc9
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,25 +1,46 @@
|
|
1
1
|
GEM
|
2
2
|
specs:
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
3
|
+
ast (2.4.1)
|
4
|
+
diff-lcs (1.4.4)
|
5
|
+
parallel (1.20.1)
|
6
|
+
parser (3.0.0.0)
|
7
|
+
ast (~> 2.4.1)
|
8
|
+
rainbow (3.0.0)
|
9
|
+
regexp_parser (1.8.2)
|
10
|
+
rexml (3.2.4)
|
11
|
+
rspec (3.9.0)
|
12
|
+
rspec-core (~> 3.9.0)
|
13
|
+
rspec-expectations (~> 3.9.0)
|
14
|
+
rspec-mocks (~> 3.9.0)
|
15
|
+
rspec-core (3.9.2)
|
16
|
+
rspec-support (~> 3.9.3)
|
17
|
+
rspec-expectations (3.9.2)
|
11
18
|
diff-lcs (>= 1.2.0, < 2.0)
|
12
|
-
rspec-support (~> 3.
|
13
|
-
rspec-mocks (3.
|
19
|
+
rspec-support (~> 3.9.0)
|
20
|
+
rspec-mocks (3.9.1)
|
14
21
|
diff-lcs (>= 1.2.0, < 2.0)
|
15
|
-
rspec-support (~> 3.
|
16
|
-
rspec-support (3.
|
22
|
+
rspec-support (~> 3.9.0)
|
23
|
+
rspec-support (3.9.3)
|
24
|
+
rubocop (1.2.0)
|
25
|
+
parallel (~> 1.10)
|
26
|
+
parser (>= 2.7.1.5)
|
27
|
+
rainbow (>= 2.2.2, < 4.0)
|
28
|
+
regexp_parser (>= 1.8)
|
29
|
+
rexml
|
30
|
+
rubocop-ast (>= 1.0.1)
|
31
|
+
ruby-progressbar (~> 1.7)
|
32
|
+
unicode-display_width (>= 1.4.0, < 2.0)
|
33
|
+
rubocop-ast (1.4.0)
|
34
|
+
parser (>= 2.7.1.5)
|
35
|
+
ruby-progressbar (1.11.0)
|
36
|
+
unicode-display_width (1.7.0)
|
17
37
|
|
18
38
|
PLATFORMS
|
19
39
|
ruby
|
20
40
|
|
21
41
|
DEPENDENCIES
|
22
42
|
rspec (~> 3.4)
|
43
|
+
rubocop (~> 1.2)
|
23
44
|
|
24
45
|
BUNDLED WITH
|
25
|
-
1.
|
46
|
+
1.17.3
|
data/lib/rosarium.rb
CHANGED
data/lib/rosarium/deferred.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
+
module Rosarium
|
3
4
|
class Deferred
|
4
5
|
|
5
6
|
def initialize(promise, resolver, rejecter)
|
@@ -8,9 +9,7 @@ module Rosarium
|
|
8
9
|
@rejecter = rejecter
|
9
10
|
end
|
10
11
|
|
11
|
-
|
12
|
-
@promise
|
13
|
-
end
|
12
|
+
attr_reader :promise
|
14
13
|
|
15
14
|
def resolve(value)
|
16
15
|
@resolver.call(value)
|
@@ -21,5 +20,4 @@ module Rosarium
|
|
21
20
|
end
|
22
21
|
|
23
22
|
end
|
24
|
-
|
25
23
|
end
|
@@ -1,5 +1,6 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
+
module Rosarium
|
3
4
|
class FixedThreadExecutor
|
4
5
|
|
5
6
|
def initialize(max = 1)
|
@@ -14,7 +15,7 @@ module Rosarium
|
|
14
15
|
@mutex.synchronize do
|
15
16
|
@waiting << block
|
16
17
|
if @executing < @max
|
17
|
-
@executing
|
18
|
+
@executing += 1
|
18
19
|
t = Thread.new { execute_and_count_down }
|
19
20
|
@threads.push t
|
20
21
|
end
|
@@ -36,26 +37,23 @@ module Rosarium
|
|
36
37
|
private
|
37
38
|
|
38
39
|
def execute_and_count_down
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
@
|
43
|
-
@executing = @executing - 1
|
44
|
-
end
|
40
|
+
execute
|
41
|
+
ensure
|
42
|
+
@mutex.synchronize do
|
43
|
+
@executing -= 1
|
45
44
|
end
|
46
45
|
end
|
47
46
|
|
48
47
|
def execute
|
49
|
-
|
48
|
+
loop do
|
50
49
|
block = @mutex.synchronize { @waiting.shift }
|
51
50
|
block or break
|
52
51
|
begin
|
53
52
|
block.call
|
54
|
-
rescue Exception
|
53
|
+
rescue Exception
|
55
54
|
end
|
56
55
|
end
|
57
56
|
end
|
58
57
|
|
59
58
|
end
|
60
|
-
|
61
59
|
end
|
data/lib/rosarium/promise.rb
CHANGED
@@ -1,15 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Rosarium
|
4
|
+
class Promise
|
2
5
|
|
3
|
-
|
6
|
+
DEFAULT_ON_FULFILL = proc { |value| value }
|
7
|
+
DEFAULT_ON_REJECT = proc { |reason| raise reason }
|
4
8
|
|
5
|
-
|
6
|
-
DEFAULT_ON_REJECT = Proc.new {|reason| raise reason}
|
9
|
+
private_class_method :new
|
7
10
|
|
8
|
-
def self.
|
9
|
-
|
10
|
-
|
11
|
+
def self.defer
|
12
|
+
promise = new
|
13
|
+
|
14
|
+
resolver = ->(value) { promise.send(:try_settle, value, nil) }
|
15
|
+
|
16
|
+
rejecter = lambda do |reason|
|
17
|
+
raise "reason must be an Exception" unless reason.is_a?(Exception)
|
18
|
+
|
19
|
+
promise.send(:try_settle, nil, reason)
|
11
20
|
end
|
12
21
|
|
22
|
+
Deferred.new(promise, resolver, rejecter)
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.resolve(value)
|
26
|
+
return value if value.is_a? Promise
|
27
|
+
|
13
28
|
deferred = defer
|
14
29
|
deferred.resolve(value)
|
15
30
|
deferred.promise
|
@@ -21,9 +36,8 @@ module Rosarium
|
|
21
36
|
deferred.promise
|
22
37
|
end
|
23
38
|
|
24
|
-
@@resolved = resolve(nil)
|
25
39
|
def self.execute(&block)
|
26
|
-
|
40
|
+
@resolved.then(&block)
|
27
41
|
end
|
28
42
|
|
29
43
|
def self.all_settled(promises)
|
@@ -35,7 +49,7 @@ module Rosarium
|
|
35
49
|
waiting_for = promises.count
|
36
50
|
mutex = Mutex.new
|
37
51
|
|
38
|
-
check =
|
52
|
+
check = proc do
|
39
53
|
# Includes both fulfilled and rejected, so always hits zero eventually
|
40
54
|
if mutex.synchronize { (waiting_for -= 1) == 0 }
|
41
55
|
deferred.resolve promises
|
@@ -43,7 +57,7 @@ module Rosarium
|
|
43
57
|
end
|
44
58
|
|
45
59
|
promises.each do |promise|
|
46
|
-
promise.then(check
|
60
|
+
promise.then(check, &check)
|
47
61
|
end
|
48
62
|
|
49
63
|
deferred.promise
|
@@ -58,16 +72,16 @@ module Rosarium
|
|
58
72
|
waiting_for = promises.count
|
59
73
|
mutex = Mutex.new
|
60
74
|
|
61
|
-
do_reject =
|
62
|
-
do_fulfill =
|
75
|
+
do_reject = ->(reason) { deferred.reject(reason) }
|
76
|
+
do_fulfill = proc do
|
63
77
|
# Only fulfilled (not rejected), so hits zero iff all promises were fulfilled
|
64
78
|
if mutex.synchronize { (waiting_for -= 1) == 0 }
|
65
|
-
deferred.resolve(promises.map
|
79
|
+
deferred.resolve(promises.map(&:value))
|
66
80
|
end
|
67
81
|
end
|
68
82
|
|
69
83
|
promises.each do |promise|
|
70
|
-
promise.then(do_reject
|
84
|
+
promise.then(do_reject, &do_fulfill)
|
71
85
|
end
|
72
86
|
|
73
87
|
deferred.promise
|
@@ -79,7 +93,7 @@ module Rosarium
|
|
79
93
|
on_fulfilled ||= DEFAULT_ON_FULFILL
|
80
94
|
on_rejected ||= DEFAULT_ON_REJECT
|
81
95
|
|
82
|
-
|
96
|
+
when_settled do
|
83
97
|
EXECUTOR.submit do
|
84
98
|
begin
|
85
99
|
deferred.resolve(
|
@@ -104,9 +118,142 @@ module Rosarium
|
|
104
118
|
self.then(block)
|
105
119
|
end
|
106
120
|
|
107
|
-
|
108
|
-
|
121
|
+
alias catch rescue
|
122
|
+
alias on_error rescue
|
109
123
|
|
110
|
-
|
124
|
+
public
|
125
|
+
|
126
|
+
def initialize
|
127
|
+
@state = :pending
|
128
|
+
@resolving = false
|
129
|
+
@mutex = Mutex.new
|
130
|
+
@condition = ConditionVariable.new
|
131
|
+
@when_settled = []
|
132
|
+
end
|
133
|
+
|
134
|
+
def state
|
135
|
+
synchronize { @state }
|
136
|
+
end
|
137
|
+
|
138
|
+
def value
|
139
|
+
wait
|
140
|
+
synchronize { @value }
|
141
|
+
end
|
142
|
+
|
143
|
+
def reason
|
144
|
+
wait
|
145
|
+
synchronize { @reason }
|
146
|
+
end
|
147
|
+
|
148
|
+
def inspect
|
149
|
+
synchronize do
|
150
|
+
r = { state: @state }
|
151
|
+
r[:value] = @value if @state == :fulfilled
|
152
|
+
r[:reason] = @reason if @state == :rejected
|
153
|
+
r
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
def fulfilled?
|
158
|
+
state == :fulfilled
|
159
|
+
end
|
160
|
+
|
161
|
+
def rejected?
|
162
|
+
state == :rejected
|
163
|
+
end
|
164
|
+
|
165
|
+
def value!
|
166
|
+
wait
|
167
|
+
synchronize do
|
168
|
+
raise @reason if @state == :rejected
|
169
|
+
@value
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
private
|
174
|
+
|
175
|
+
def wait
|
176
|
+
when_settled do
|
177
|
+
synchronize { @condition.broadcast }
|
178
|
+
end
|
179
|
+
|
180
|
+
synchronize do
|
181
|
+
loop do
|
182
|
+
return if @state == :fulfilled || @state == :rejected
|
183
|
+
@condition.wait @mutex
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
def synchronize(&block)
|
189
|
+
@mutex.synchronize(&block)
|
190
|
+
end
|
191
|
+
|
192
|
+
def try_settle(value, reason)
|
193
|
+
callbacks = []
|
194
|
+
add_when_settled = false
|
195
|
+
|
196
|
+
synchronize do
|
197
|
+
if @state == :pending && !@resolving
|
198
|
+
if value.is_a? Promise
|
199
|
+
@resolving = true
|
200
|
+
add_when_settled = true
|
201
|
+
elsif reason.nil?
|
202
|
+
@value = value
|
203
|
+
@state = :fulfilled
|
204
|
+
callbacks.concat @when_settled
|
205
|
+
@when_settled.clear
|
206
|
+
else
|
207
|
+
@reason = reason
|
208
|
+
@state = :rejected
|
209
|
+
callbacks.concat @when_settled
|
210
|
+
@when_settled.clear
|
211
|
+
end
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
# rubocop:disable Style/IfUnlessModifier
|
216
|
+
if add_when_settled
|
217
|
+
value.when_settled { copy_settlement_from value }
|
218
|
+
end
|
219
|
+
# rubocop:enable Style/IfUnlessModifier
|
220
|
+
|
221
|
+
callbacks.each { |c| EXECUTOR.submit(&c) }
|
222
|
+
end
|
223
|
+
|
224
|
+
def copy_settlement_from(other)
|
225
|
+
callbacks = []
|
226
|
+
|
227
|
+
synchronize do
|
228
|
+
@value = other.value
|
229
|
+
@reason = other.reason
|
230
|
+
@state = other.state
|
231
|
+
@resolving = false
|
232
|
+
callbacks.concat @when_settled
|
233
|
+
@when_settled.clear
|
234
|
+
end
|
111
235
|
|
236
|
+
callbacks.each { |c| EXECUTOR.submit(&c) }
|
237
|
+
end
|
238
|
+
|
239
|
+
protected
|
240
|
+
|
241
|
+
def when_settled(&block)
|
242
|
+
immediate = synchronize do
|
243
|
+
if @state == :fulfilled || @state == :rejected
|
244
|
+
true
|
245
|
+
else
|
246
|
+
@when_settled << block
|
247
|
+
false
|
248
|
+
end
|
249
|
+
end
|
250
|
+
|
251
|
+
block.call if immediate
|
252
|
+
|
253
|
+
nil
|
254
|
+
end
|
255
|
+
|
256
|
+
@resolved = resolve(nil)
|
257
|
+
|
258
|
+
end
|
112
259
|
end
|
data/spec/promise_static_spec.rb
CHANGED
@@ -14,16 +14,11 @@ describe "instantly-resolved promises" do
|
|
14
14
|
it "creates a fulfilled promise" do
|
15
15
|
t = Rosarium::Promise.resolve 7
|
16
16
|
check_fulfilled t, 7
|
17
|
-
expect(t).not_to respond_to(:fulfill)
|
18
|
-
expect(t).not_to respond_to(:reject)
|
19
17
|
end
|
20
18
|
|
21
19
|
it "creates a rejected promise" do
|
22
|
-
e = an_error
|
23
20
|
t = Rosarium::Promise.reject an_error
|
24
21
|
check_rejected t, an_error
|
25
|
-
expect(t).not_to respond_to(:fulfill)
|
26
|
-
expect(t).not_to respond_to(:reject)
|
27
22
|
end
|
28
23
|
|
29
24
|
it "creates an immediately-executable promise" do
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rosarium
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Rachel Evans
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-02-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec
|
@@ -24,6 +24,20 @@ dependencies:
|
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '3.4'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rubocop
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.2'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.2'
|
27
41
|
description: |2
|
28
42
|
Rosarium implements something that's a bit like Promises,
|
29
43
|
inspired by the stability and ease of use of Q
|
@@ -41,7 +55,6 @@ files:
|
|
41
55
|
- lib/rosarium/deferred.rb
|
42
56
|
- lib/rosarium/fixed_thread_executor.rb
|
43
57
|
- lib/rosarium/promise.rb
|
44
|
-
- lib/rosarium/simple_promise.rb
|
45
58
|
- spec/deferred_spec.rb
|
46
59
|
- spec/fixed_thread_executor_spec.rb
|
47
60
|
- spec/promise_methods_spec.rb
|
@@ -51,7 +64,7 @@ homepage: http://rve.org.uk/gems/rosarium
|
|
51
64
|
licenses:
|
52
65
|
- Apache-2.0
|
53
66
|
metadata: {}
|
54
|
-
post_install_message:
|
67
|
+
post_install_message:
|
55
68
|
rdoc_options: []
|
56
69
|
require_paths:
|
57
70
|
- lib
|
@@ -59,16 +72,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
59
72
|
requirements:
|
60
73
|
- - ">="
|
61
74
|
- !ruby/object:Gem::Version
|
62
|
-
version: '
|
75
|
+
version: '2.4'
|
63
76
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
64
77
|
requirements:
|
65
78
|
- - ">="
|
66
79
|
- !ruby/object:Gem::Version
|
67
80
|
version: '0'
|
68
81
|
requirements: []
|
69
|
-
|
70
|
-
|
71
|
-
signing_key:
|
82
|
+
rubygems_version: 3.0.8
|
83
|
+
signing_key:
|
72
84
|
specification_version: 4
|
73
85
|
summary: Promises, or something like them
|
74
86
|
test_files: []
|
@@ -1,164 +0,0 @@
|
|
1
|
-
module Rosarium
|
2
|
-
|
3
|
-
class SimplePromise
|
4
|
-
|
5
|
-
def self.defer
|
6
|
-
promise = new
|
7
|
-
resolver = promise.method :resolve
|
8
|
-
rejecter = promise.method :reject
|
9
|
-
|
10
|
-
class <<promise
|
11
|
-
undef :resolve
|
12
|
-
undef :reject
|
13
|
-
end
|
14
|
-
|
15
|
-
Deferred.new(promise, resolver, rejecter)
|
16
|
-
end
|
17
|
-
|
18
|
-
def initialize
|
19
|
-
@state = :pending
|
20
|
-
@resolving = false
|
21
|
-
@mutex = Mutex.new
|
22
|
-
@condition = ConditionVariable.new
|
23
|
-
@on_resolution = []
|
24
|
-
end
|
25
|
-
|
26
|
-
def state
|
27
|
-
synchronize { @state }
|
28
|
-
end
|
29
|
-
|
30
|
-
def value
|
31
|
-
wait
|
32
|
-
synchronize { @value }
|
33
|
-
end
|
34
|
-
|
35
|
-
def reason
|
36
|
-
wait
|
37
|
-
synchronize { @reason }
|
38
|
-
end
|
39
|
-
|
40
|
-
def inspect
|
41
|
-
synchronize do
|
42
|
-
r = { state: @state }
|
43
|
-
r[:value] = @value if @state == :fulfilled
|
44
|
-
r[:reason] = @reason if @state == :rejected
|
45
|
-
r
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
def fulfilled?
|
50
|
-
state == :fulfilled
|
51
|
-
end
|
52
|
-
|
53
|
-
def rejected?
|
54
|
-
state == :rejected
|
55
|
-
end
|
56
|
-
|
57
|
-
def value!
|
58
|
-
wait
|
59
|
-
synchronize do
|
60
|
-
if @state == :rejected
|
61
|
-
raise @reason
|
62
|
-
else
|
63
|
-
@value
|
64
|
-
end
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
private
|
69
|
-
|
70
|
-
def wait
|
71
|
-
on_resolution do
|
72
|
-
synchronize { @condition.broadcast }
|
73
|
-
end
|
74
|
-
|
75
|
-
synchronize do
|
76
|
-
loop do
|
77
|
-
return if @state == :fulfilled or @state == :rejected
|
78
|
-
@condition.wait @mutex
|
79
|
-
end
|
80
|
-
end
|
81
|
-
end
|
82
|
-
|
83
|
-
def synchronize
|
84
|
-
@mutex.synchronize { yield }
|
85
|
-
end
|
86
|
-
|
87
|
-
public
|
88
|
-
|
89
|
-
def resolve(value)
|
90
|
-
_resolve(value, nil)
|
91
|
-
end
|
92
|
-
|
93
|
-
def reject(reason)
|
94
|
-
raise "reason must be an Exception" unless reason.kind_of? Exception
|
95
|
-
_resolve(nil, reason)
|
96
|
-
end
|
97
|
-
|
98
|
-
private
|
99
|
-
|
100
|
-
def _resolve(value, reason)
|
101
|
-
callbacks = []
|
102
|
-
add_on_resolution = false
|
103
|
-
|
104
|
-
synchronize do
|
105
|
-
if @state == :pending and not @resolving
|
106
|
-
if value.kind_of? SimplePromise
|
107
|
-
@resolving = true
|
108
|
-
add_on_resolution = true
|
109
|
-
elsif reason.nil?
|
110
|
-
@value = value
|
111
|
-
@state = :fulfilled
|
112
|
-
callbacks.concat @on_resolution
|
113
|
-
@on_resolution.clear
|
114
|
-
else
|
115
|
-
@reason = reason
|
116
|
-
@state = :rejected
|
117
|
-
callbacks.concat @on_resolution
|
118
|
-
@on_resolution.clear
|
119
|
-
end
|
120
|
-
end
|
121
|
-
end
|
122
|
-
|
123
|
-
if add_on_resolution
|
124
|
-
value.on_resolution { copy_resolution_from value }
|
125
|
-
end
|
126
|
-
|
127
|
-
callbacks.each {|c| EXECUTOR.submit { c.call } }
|
128
|
-
end
|
129
|
-
|
130
|
-
def copy_resolution_from(other)
|
131
|
-
callbacks = []
|
132
|
-
|
133
|
-
synchronize do
|
134
|
-
@value = other.value
|
135
|
-
@reason = other.reason
|
136
|
-
@state = other.state
|
137
|
-
@resolving = false
|
138
|
-
callbacks.concat @on_resolution
|
139
|
-
@on_resolution.clear
|
140
|
-
end
|
141
|
-
|
142
|
-
callbacks.each {|c| EXECUTOR.submit { c.call } }
|
143
|
-
end
|
144
|
-
|
145
|
-
protected
|
146
|
-
|
147
|
-
def on_resolution(&block)
|
148
|
-
immediate = synchronize do
|
149
|
-
if @state == :fulfilled or @state == :rejected
|
150
|
-
true
|
151
|
-
else
|
152
|
-
@on_resolution << block
|
153
|
-
false
|
154
|
-
end
|
155
|
-
end
|
156
|
-
|
157
|
-
block.call if immediate
|
158
|
-
|
159
|
-
nil
|
160
|
-
end
|
161
|
-
|
162
|
-
end
|
163
|
-
|
164
|
-
end
|