concurrent-ruby-edge 0.2.0.pre3 → 0.2.0.pre4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +8 -41
- data/lib/concurrent/channel.rb +33 -33
- data/lib/concurrent/channel/buffer/base.rb +16 -3
- data/lib/concurrent/channel/buffer/buffered.rb +16 -19
- data/lib/concurrent/channel/buffer/dropping.rb +1 -1
- data/lib/concurrent/channel/buffer/sliding.rb +2 -2
- data/lib/concurrent/channel/buffer/ticker.rb +5 -8
- data/lib/concurrent/channel/buffer/timer.rb +6 -10
- data/lib/concurrent/channel/buffer/unbuffered.rb +32 -30
- data/lib/concurrent/edge/atomic_markable_reference.rb +1 -1
- data/lib/concurrent/edge/future.rb +6 -1
- data/lib/concurrent/edge/lock_free_linked_set.rb +1 -1
- data/lib/concurrent/edge/lock_free_stack.rb +1 -1
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8589b43e4b23f4d4bb73cddf2123b436e0ea90ba
|
4
|
+
data.tar.gz: baa80cc8ded0dc8a050ce3a64a933183575584a4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2c3fbd2d6e8718e62457e39c61bfe95a0da959072af5e05d2162fd12d8aa1aa15137428916766bde9b32f7359f9cab8b21b5883851d5bf432541e1dd531ca719
|
7
|
+
data.tar.gz: a538eca680505fb8b3192fb6a1b5dbcdcc63ac757d56b00bca5745256bd01d007f40d50aad0c4db2df6a33f13e42efe7af384595b3998e9e4c0166094fa5635a
|
data/README.md
CHANGED
@@ -49,6 +49,14 @@ MRI 1.9.3, 2.0, 2.1, 2.2, JRuby (1.9 mode), and Rubinius 2.x are supported.
|
|
49
49
|
This gem should be fully compatible with any interpreter that is compliant with Ruby 1.9.3 or newer.
|
50
50
|
Java 8 is preferred for JRuby but every Java version on which JRuby 9000 runs will be supported.
|
51
51
|
|
52
|
+
## Thread Safety
|
53
|
+
|
54
|
+
*Concurrent Ruby makes the strongest thread safety guarantees of any Ruby concurrency library. We are the only library with a published [memory model](https://github.com/ruby-concurrency/concurrent-ruby/blob/master/doc/synchronization.md) which provides consistent behavior and guarantees on all three of the main Ruby interpreters (MRI/CRuby, JRuby, and Rubinius).*
|
55
|
+
|
56
|
+
Every abstraction in this library is thread safe. Similarly, all are deadlock free and many are fully lock free. Specific thread safety guarantees are documented with each abstraction.
|
57
|
+
|
58
|
+
It is critical to remember, however, that Ruby is a language of mutable references. *No* concurrency library for Ruby can ever prevent the user from making thread safety mistakes (such as sharing a mutable object between threads and modifying it on both threads) or from creating deadlocks through incorrect use of locks. All the library can do is provide safe abstractions which encourage safe practices. Concurrent Ruby provides more safe concurrency abstractions than any other Ruby library, many of which support the mantra of ["Do not communicate by sharing memory; instead, share memory by communicating"](https://blog.golang.org/share-memory-by-communicating). Concurrent Ruby is also the only Ruby library which provides a full suite of thread safe and immutable variable types and data structures.
|
59
|
+
|
52
60
|
## Features & Documentation
|
53
61
|
|
54
62
|
We have a roadmap guiding our work toward the [v1.0.0 release](https://github.com/ruby-concurrency/concurrent-ruby/issues/257).
|
@@ -229,39 +237,6 @@ and load the appropriate C extensions.
|
|
229
237
|
No gems should depend on `concurrent-ruby-ext`. Doing so will force C extensions on your users.
|
230
238
|
The best practice is to depend on `concurrent-ruby` and let users to decide if they want C extensions.
|
231
239
|
|
232
|
-
### Building
|
233
|
-
|
234
|
-
All published versions of this gem (core, extension, and several platform-specific packages) are compiled,
|
235
|
-
packaged, tested, and published using an open, [automated process](https://github.com/ruby-concurrency/rake-compiler-dev-box).
|
236
|
-
This process can also be used to create pre-compiled binaries of the extension gem for virtually
|
237
|
-
any platform. *Documentation is forthcoming...*
|
238
|
-
|
239
|
-
```
|
240
|
-
*MRI only*
|
241
|
-
bundle exec rake build:native # Build concurrent-ruby-ext-<version>-<platform>.gem into the pkg dir
|
242
|
-
bundle exec rake compile:extension # Compile extension
|
243
|
-
|
244
|
-
*JRuby only*
|
245
|
-
bundle exec rake build # Build JRuby-specific core gem (alias for `build:core`)
|
246
|
-
bundle exec rake build:core # Build concurrent-ruby-<version>-java.gem into the pkg directory
|
247
|
-
|
248
|
-
*All except JRuby*
|
249
|
-
bundle exec rake build:core # Build concurrent-ruby-<version>.gem into the pkg directory
|
250
|
-
bundle exec rake build:ext # Build concurrent-ruby-ext-<version>.gem into the pkg directory
|
251
|
-
|
252
|
-
*When Docker IS installed*
|
253
|
-
bundle exec rake build:windows # Build the windows binary <version> gems per rake-compiler-dock
|
254
|
-
bundle exec rake build # Build core, extension, and edge gems, including Windows binaries
|
255
|
-
|
256
|
-
*When Docker is NOT installed*
|
257
|
-
bundle exec rake build # Build core, extension, and edge gems (excluding Windows binaries)
|
258
|
-
|
259
|
-
*All*
|
260
|
-
bundle exec rake clean # Remove any temporary products
|
261
|
-
bundle exec rake clobber # Remove any generated file
|
262
|
-
bundle exec rake compile # Compile all the extensions
|
263
|
-
```
|
264
|
-
|
265
240
|
## Maintainers
|
266
241
|
|
267
242
|
* [Jerry D'Antonio](https://github.com/jdantonio) (creator)
|
@@ -277,14 +252,6 @@ bundle exec rake compile # Compile all the extensions
|
|
277
252
|
* [Charles Oliver Nutter](https://github.com/headius) for the `atomic` and `thread_safe` gems
|
278
253
|
* [thedarkone](https://github.com/thedarkone) for the `thread_safe` gem
|
279
254
|
|
280
|
-
## Contributing
|
281
|
-
|
282
|
-
1. Fork it
|
283
|
-
2. Create your feature branch (`git checkout -b my-new-feature`)
|
284
|
-
3. Commit your changes (`git commit -am 'Add some feature'`)
|
285
|
-
4. Push to the branch (`git push origin my-new-feature`)
|
286
|
-
5. Create new Pull Request
|
287
|
-
|
288
255
|
## License and Copyright
|
289
256
|
|
290
257
|
*Concurrent Ruby* is free software released under the [MIT License](http://www.opensource.org/licenses/MIT).
|
data/lib/concurrent/channel.rb
CHANGED
@@ -8,8 +8,10 @@ module Concurrent
|
|
8
8
|
|
9
9
|
# {include:file:doc/channel.md}
|
10
10
|
class Channel
|
11
|
+
extend Forwardable
|
11
12
|
include Enumerable
|
12
13
|
|
14
|
+
# NOTE: Move to global IO pool once stable
|
13
15
|
GOROUTINES = Concurrent::CachedThreadPool.new
|
14
16
|
private_constant :GOROUTINES
|
15
17
|
|
@@ -32,10 +34,17 @@ module Concurrent
|
|
32
34
|
end
|
33
35
|
end
|
34
36
|
|
37
|
+
def_delegators :buffer,
|
38
|
+
:size, :capacity, :close, :closed?,
|
39
|
+
:blocking?, :empty?, :full?
|
40
|
+
|
41
|
+
alias_method :length, :size
|
42
|
+
alias_method :stop, :close
|
43
|
+
|
35
44
|
def initialize(opts = {})
|
36
45
|
# undocumented -- for internal use only
|
37
46
|
if opts.is_a? Buffer::Base
|
38
|
-
|
47
|
+
self.buffer = opts
|
39
48
|
return
|
40
49
|
end
|
41
50
|
|
@@ -45,25 +54,20 @@ module Concurrent
|
|
45
54
|
if size && buffer == :unbuffered
|
46
55
|
raise ArgumentError.new('unbuffered channels cannot have a size')
|
47
56
|
elsif size.nil? && buffer.nil?
|
48
|
-
|
57
|
+
self.buffer = BUFFER_TYPES[:unbuffered].new
|
49
58
|
elsif size == 0 && buffer == :buffered
|
50
|
-
|
59
|
+
self.buffer = BUFFER_TYPES[:unbuffered].new
|
51
60
|
elsif buffer == :unbuffered
|
52
|
-
|
61
|
+
self.buffer = BUFFER_TYPES[:unbuffered].new
|
53
62
|
elsif size.nil? || size < 1
|
54
63
|
raise ArgumentError.new('size must be at least 1 for this buffer type')
|
55
64
|
else
|
56
65
|
buffer ||= :buffered
|
57
|
-
|
66
|
+
self.buffer = BUFFER_TYPES[buffer].new(size)
|
58
67
|
end
|
59
68
|
|
60
|
-
|
61
|
-
end
|
62
|
-
|
63
|
-
def size
|
64
|
-
@buffer.size
|
69
|
+
self.validator = opts.fetch(:validator, DEFAULT_VALIDATOR)
|
65
70
|
end
|
66
|
-
alias_method :capacity, :size
|
67
71
|
|
68
72
|
def put(item)
|
69
73
|
return false unless validate(item, false, false)
|
@@ -129,22 +133,21 @@ module Concurrent
|
|
129
133
|
item
|
130
134
|
end
|
131
135
|
|
136
|
+
# @example
|
132
137
|
#
|
133
|
-
#
|
138
|
+
# jobs = Channel.new
|
134
139
|
#
|
135
|
-
#
|
136
|
-
#
|
137
|
-
#
|
138
|
-
#
|
139
|
-
#
|
140
|
-
#
|
141
|
-
#
|
142
|
-
#
|
143
|
-
# print "received all jobs\n"
|
144
|
-
# break
|
145
|
-
# end
|
140
|
+
# Channel.go do
|
141
|
+
# loop do
|
142
|
+
# j, more = jobs.next
|
143
|
+
# if more
|
144
|
+
# print "received job #{j}\n"
|
145
|
+
# else
|
146
|
+
# print "received all jobs\n"
|
147
|
+
# break
|
146
148
|
# end
|
147
149
|
# end
|
150
|
+
# end
|
148
151
|
def next
|
149
152
|
item, more = do_next
|
150
153
|
item = nil if item == Buffer::NO_VALUE
|
@@ -191,11 +194,6 @@ module Concurrent
|
|
191
194
|
end
|
192
195
|
end
|
193
196
|
|
194
|
-
def close
|
195
|
-
@buffer.close
|
196
|
-
end
|
197
|
-
alias_method :stop, :close
|
198
|
-
|
199
197
|
class << self
|
200
198
|
def timer(seconds)
|
201
199
|
Channel.new(Buffer::Timer.new(seconds))
|
@@ -240,10 +238,12 @@ module Concurrent
|
|
240
238
|
|
241
239
|
private
|
242
240
|
|
241
|
+
attr_accessor :buffer, :validator
|
242
|
+
|
243
243
|
def validate(value, allow_nil, raise_error)
|
244
244
|
if !allow_nil && value.nil?
|
245
245
|
raise_error ? raise(ValidationError.new('nil is not a valid value')) : false
|
246
|
-
elsif
|
246
|
+
elsif !validator.call(value)
|
247
247
|
raise_error ? raise(ValidationError) : false
|
248
248
|
else
|
249
249
|
true
|
@@ -254,19 +254,19 @@ module Concurrent
|
|
254
254
|
end
|
255
255
|
|
256
256
|
def do_put(item)
|
257
|
-
|
257
|
+
buffer.put(item)
|
258
258
|
end
|
259
259
|
|
260
260
|
def do_offer(item)
|
261
|
-
|
261
|
+
buffer.offer(item)
|
262
262
|
end
|
263
263
|
|
264
264
|
def do_next
|
265
|
-
|
265
|
+
buffer.next
|
266
266
|
end
|
267
267
|
|
268
268
|
def do_poll
|
269
|
-
|
269
|
+
buffer.poll
|
270
270
|
end
|
271
271
|
end
|
272
272
|
end
|
@@ -20,19 +20,26 @@ module Concurrent
|
|
20
20
|
|
21
21
|
# @!macro [attach] channel_buffer_size_reader
|
22
22
|
#
|
23
|
+
# The number of items currently in the buffer.
|
24
|
+
attr_reader :size
|
25
|
+
|
26
|
+
# @!macro [attach] channel_buffer_capacity_reader
|
27
|
+
#
|
23
28
|
# The maximum number of values which can be {#put} onto the buffer
|
24
29
|
# it becomes full.
|
25
|
-
attr_reader :
|
26
|
-
alias_method :capacity, :size
|
30
|
+
attr_reader :capacity
|
27
31
|
|
28
32
|
# @!macro [attach] channel_buffer_initialize
|
29
33
|
#
|
30
34
|
# Creates a new buffer.
|
31
|
-
def initialize
|
35
|
+
def initialize(*args)
|
32
36
|
super()
|
33
37
|
synchronize do
|
34
38
|
@closed = false
|
35
39
|
@size = 0
|
40
|
+
@capacity = 0
|
41
|
+
@buffer = nil
|
42
|
+
ns_initialize(*args)
|
36
43
|
end
|
37
44
|
end
|
38
45
|
|
@@ -187,6 +194,12 @@ module Concurrent
|
|
187
194
|
|
188
195
|
private
|
189
196
|
|
197
|
+
attr_accessor :buffer
|
198
|
+
attr_writer :closed, :capacity, :size
|
199
|
+
|
200
|
+
def ns_initialize(*args)
|
201
|
+
end
|
202
|
+
|
190
203
|
# @!macro channel_buffer_closed_question
|
191
204
|
def ns_closed?
|
192
205
|
@closed
|
@@ -10,20 +10,6 @@ module Concurrent
|
|
10
10
|
# an item is removed from the buffer, creating spare capacity.
|
11
11
|
class Buffered < Base
|
12
12
|
|
13
|
-
# @!macro channel_buffer_initialize
|
14
|
-
#
|
15
|
-
# @param [Integer] size the maximum capacity of the buffer; must be
|
16
|
-
# greater than zero.
|
17
|
-
# @raise [ArgumentError] when the size is zero (0) or less.
|
18
|
-
def initialize(size)
|
19
|
-
raise ArgumentError.new('size must be greater than 0') if size.to_i <= 0
|
20
|
-
super()
|
21
|
-
synchronize do
|
22
|
-
@size = size.to_i
|
23
|
-
@buffer = []
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
13
|
# @!macro channel_buffer_empty_question
|
28
14
|
def empty?
|
29
15
|
synchronize { ns_empty? }
|
@@ -85,7 +71,7 @@ module Concurrent
|
|
85
71
|
if ns_closed? && ns_empty?
|
86
72
|
return NO_VALUE, false
|
87
73
|
elsif !ns_empty?
|
88
|
-
item =
|
74
|
+
item = buffer.shift
|
89
75
|
more = !ns_empty? || !ns_closed?
|
90
76
|
return item, more
|
91
77
|
end
|
@@ -100,26 +86,37 @@ module Concurrent
|
|
100
86
|
if ns_empty?
|
101
87
|
NO_VALUE
|
102
88
|
else
|
103
|
-
|
89
|
+
buffer.shift
|
104
90
|
end
|
105
91
|
end
|
106
92
|
end
|
107
93
|
|
108
94
|
private
|
109
95
|
|
96
|
+
# @!macro channel_buffer_initialize
|
97
|
+
#
|
98
|
+
# @param [Integer] size the maximum capacity of the buffer; must be
|
99
|
+
# greater than zero.
|
100
|
+
# @raise [ArgumentError] when the size is zero (0) or less.
|
101
|
+
def ns_initialize(size)
|
102
|
+
raise ArgumentError.new('size must be greater than 0') if size.to_i <= 0
|
103
|
+
self.capacity = size.to_i
|
104
|
+
self.buffer = []
|
105
|
+
end
|
106
|
+
|
110
107
|
# @!macro channel_buffer_empty_question
|
111
108
|
def ns_empty?
|
112
|
-
|
109
|
+
buffer.length == 0
|
113
110
|
end
|
114
111
|
|
115
112
|
# @!macro channel_buffer_full_question
|
116
113
|
def ns_full?
|
117
|
-
|
114
|
+
buffer.length == capacity
|
118
115
|
end
|
119
116
|
|
120
117
|
# @!macro channel_buffer_put
|
121
118
|
def ns_put_onto_buffer(item)
|
122
|
-
|
119
|
+
buffer.push(item)
|
123
120
|
end
|
124
121
|
end
|
125
122
|
end
|
@@ -8,14 +8,6 @@ module Concurrent
|
|
8
8
|
|
9
9
|
class Ticker < Base
|
10
10
|
|
11
|
-
def initialize(interval)
|
12
|
-
super()
|
13
|
-
synchronize do
|
14
|
-
@interval = interval.to_f
|
15
|
-
@next_tick = Concurrent.monotonic_time + interval
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
11
|
def size() 1; end
|
20
12
|
|
21
13
|
def empty?() false; end
|
@@ -63,6 +55,11 @@ module Concurrent
|
|
63
55
|
|
64
56
|
private
|
65
57
|
|
58
|
+
def ns_initialize(interval)
|
59
|
+
@interval = interval.to_f
|
60
|
+
@next_tick = Concurrent.monotonic_time + interval
|
61
|
+
end
|
62
|
+
|
66
63
|
def do_poll
|
67
64
|
if ns_closed?
|
68
65
|
return nil, false
|
@@ -8,15 +8,6 @@ module Concurrent
|
|
8
8
|
|
9
9
|
class Timer < Base
|
10
10
|
|
11
|
-
def initialize(delay)
|
12
|
-
super()
|
13
|
-
synchronize do
|
14
|
-
@tick = Concurrent.monotonic_time + delay.to_f
|
15
|
-
@closed = false
|
16
|
-
@empty = false
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
11
|
def size() 1; end
|
21
12
|
|
22
13
|
def empty?
|
@@ -59,13 +50,18 @@ module Concurrent
|
|
59
50
|
|
60
51
|
private
|
61
52
|
|
53
|
+
def ns_initialize(delay)
|
54
|
+
@tick = Concurrent.monotonic_time + delay.to_f
|
55
|
+
@closed = false
|
56
|
+
@empty = false
|
57
|
+
end
|
58
|
+
|
62
59
|
def do_poll
|
63
60
|
synchronize do
|
64
61
|
return :closed, false if ns_closed?
|
65
62
|
|
66
63
|
if Concurrent.monotonic_time > @tick
|
67
64
|
# only one listener gets notified
|
68
|
-
@closed = @empty = true
|
69
65
|
return :tick, Concurrent::Channel::Tick.new(@tick)
|
70
66
|
else
|
71
67
|
return :wait, true
|
@@ -15,19 +15,8 @@ module Concurrent
|
|
15
15
|
# and the first blocked call will return.
|
16
16
|
class Unbuffered < Base
|
17
17
|
|
18
|
-
# @!macro channel_buffer_initialize
|
19
|
-
def initialize
|
20
|
-
super
|
21
|
-
synchronize do
|
22
|
-
# one will always be empty
|
23
|
-
@putting = []
|
24
|
-
@taking = []
|
25
|
-
@closed = false
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
18
|
# @!macro channel_buffer_size_reader
|
30
|
-
#
|
19
|
+
#
|
31
20
|
# Always returns zero (0).
|
32
21
|
def size() 0; end
|
33
22
|
|
@@ -54,11 +43,11 @@ module Concurrent
|
|
54
43
|
return false if ns_closed?
|
55
44
|
|
56
45
|
ref = Concurrent::AtomicReference.new(item)
|
57
|
-
if
|
58
|
-
|
46
|
+
if taking.empty?
|
47
|
+
putting.push(ref)
|
59
48
|
else
|
60
|
-
|
61
|
-
|
49
|
+
taken = taking.shift
|
50
|
+
taken.value = item
|
62
51
|
ref.value = nil
|
63
52
|
end
|
64
53
|
ref
|
@@ -78,10 +67,10 @@ module Concurrent
|
|
78
67
|
# buffer is closed, this method will return `false` immediately.
|
79
68
|
def offer(item)
|
80
69
|
synchronize do
|
81
|
-
return false if ns_closed? ||
|
70
|
+
return false if ns_closed? || taking.empty?
|
82
71
|
|
83
|
-
|
84
|
-
|
72
|
+
taken = taking.shift
|
73
|
+
taken.value = item
|
85
74
|
true
|
86
75
|
end
|
87
76
|
end
|
@@ -96,15 +85,15 @@ module Concurrent
|
|
96
85
|
# and this method will return.
|
97
86
|
def take
|
98
87
|
mine = synchronize do
|
99
|
-
return NO_VALUE if ns_closed? &&
|
88
|
+
return NO_VALUE if ns_closed? && putting.empty?
|
100
89
|
|
101
90
|
ref = Concurrent::AtomicReference.new(nil)
|
102
|
-
if
|
103
|
-
|
91
|
+
if putting.empty?
|
92
|
+
taking.push(ref)
|
104
93
|
else
|
105
|
-
|
106
|
-
ref.value =
|
107
|
-
|
94
|
+
put = putting.shift
|
95
|
+
ref.value = put.value
|
96
|
+
put.value = nil
|
108
97
|
end
|
109
98
|
ref
|
110
99
|
end
|
@@ -124,11 +113,11 @@ module Concurrent
|
|
124
113
|
# buffer is closed, this method will return `NO_VALUE` immediately.
|
125
114
|
def poll
|
126
115
|
synchronize do
|
127
|
-
return NO_VALUE if
|
116
|
+
return NO_VALUE if putting.empty?
|
128
117
|
|
129
|
-
|
130
|
-
value =
|
131
|
-
|
118
|
+
put = putting.shift
|
119
|
+
value = put.value
|
120
|
+
put.value = nil
|
132
121
|
value
|
133
122
|
end
|
134
123
|
end
|
@@ -142,9 +131,22 @@ module Concurrent
|
|
142
131
|
# @see {#take}
|
143
132
|
def next
|
144
133
|
item = take
|
145
|
-
more = synchronize {
|
134
|
+
more = synchronize { !putting.empty? }
|
146
135
|
return item, more
|
147
136
|
end
|
137
|
+
|
138
|
+
private
|
139
|
+
|
140
|
+
attr_accessor :putting, :taking
|
141
|
+
|
142
|
+
# @!macro channel_buffer_initialize
|
143
|
+
def ns_initialize
|
144
|
+
# one will always be empty
|
145
|
+
self.putting = []
|
146
|
+
self.taking = []
|
147
|
+
self.closed = false
|
148
|
+
self.capacity = 1
|
149
|
+
end
|
148
150
|
end
|
149
151
|
end
|
150
152
|
end
|
@@ -11,7 +11,7 @@ module Concurrent
|
|
11
11
|
# @api Edge
|
12
12
|
class AtomicMarkableReference < ::Concurrent::Synchronization::Object
|
13
13
|
|
14
|
-
private
|
14
|
+
private(*attr_volatile_with_cas(:reference))
|
15
15
|
|
16
16
|
# @!macro [attach] atomic_markable_reference_method_initialize
|
17
17
|
def initialize(value = nil, mark = false)
|
@@ -132,6 +132,7 @@ module Concurrent
|
|
132
132
|
class Event < Synchronization::LockableObject
|
133
133
|
safe_initialization!
|
134
134
|
include Concern::Deprecation
|
135
|
+
include Concern::Logging
|
135
136
|
|
136
137
|
# @!visibility private
|
137
138
|
class State
|
@@ -885,6 +886,7 @@ module Concurrent
|
|
885
886
|
# @!visibility private
|
886
887
|
class AbstractPromise < Synchronization::Object
|
887
888
|
safe_initialization!
|
889
|
+
include Concern::Logging
|
888
890
|
|
889
891
|
def initialize(future)
|
890
892
|
super()
|
@@ -925,7 +927,10 @@ module Concurrent
|
|
925
927
|
# @return [Future]
|
926
928
|
def evaluate_to(*args, block)
|
927
929
|
complete_with Future::Success.new(block.call(*args))
|
928
|
-
rescue => error
|
930
|
+
rescue StandardError => error
|
931
|
+
complete_with Future::Failed.new(error)
|
932
|
+
rescue Exception => error
|
933
|
+
log(ERROR, 'Edge::Future', error)
|
929
934
|
complete_with Future::Failed.new(error)
|
930
935
|
end
|
931
936
|
end
|
@@ -112,7 +112,7 @@ module Concurrent
|
|
112
112
|
removed = curr.successor_reference.compare_and_set succ, succ, false, true
|
113
113
|
|
114
114
|
#next_node unless removed
|
115
|
-
|
115
|
+
next unless removed
|
116
116
|
|
117
117
|
pred.successor_reference.compare_and_set curr, succ, false, false
|
118
118
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: concurrent-ruby-edge
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.0.
|
4
|
+
version: 0.2.0.pre4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jerry D'Antonio
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2015-
|
13
|
+
date: 2015-10-08 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: concurrent-ruby
|
@@ -18,14 +18,14 @@ dependencies:
|
|
18
18
|
requirements:
|
19
19
|
- - "~>"
|
20
20
|
- !ruby/object:Gem::Version
|
21
|
-
version: 1.0.0.
|
21
|
+
version: 1.0.0.pre4
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
24
|
version_requirements: !ruby/object:Gem::Requirement
|
25
25
|
requirements:
|
26
26
|
- - "~>"
|
27
27
|
- !ruby/object:Gem::Version
|
28
|
-
version: 1.0.0.
|
28
|
+
version: 1.0.0.pre4
|
29
29
|
description: |
|
30
30
|
These features are under active development and may change frequently. They are expected not to
|
31
31
|
keep backward compatibility (there may also lack tests and documentation). Semantic versions will
|