concurrent-ruby 0.9.2-java → 1.0.0-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (121) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +49 -1
  3. data/README.md +86 -120
  4. data/lib/concurrent.rb +14 -5
  5. data/lib/concurrent/agent.rb +587 -0
  6. data/lib/concurrent/array.rb +39 -0
  7. data/lib/concurrent/async.rb +296 -149
  8. data/lib/concurrent/atom.rb +135 -45
  9. data/lib/concurrent/atomic/abstract_thread_local_var.rb +38 -0
  10. data/lib/concurrent/atomic/atomic_boolean.rb +83 -118
  11. data/lib/concurrent/atomic/atomic_fixnum.rb +101 -163
  12. data/lib/concurrent/atomic/atomic_reference.rb +1 -8
  13. data/lib/concurrent/atomic/count_down_latch.rb +62 -103
  14. data/lib/concurrent/atomic/cyclic_barrier.rb +3 -1
  15. data/lib/concurrent/atomic/event.rb +1 -1
  16. data/lib/concurrent/atomic/java_count_down_latch.rb +39 -0
  17. data/lib/concurrent/atomic/java_thread_local_var.rb +50 -0
  18. data/lib/concurrent/atomic/mutex_atomic_boolean.rb +60 -0
  19. data/lib/concurrent/atomic/mutex_atomic_fixnum.rb +91 -0
  20. data/lib/concurrent/atomic/mutex_count_down_latch.rb +43 -0
  21. data/lib/concurrent/atomic/mutex_semaphore.rb +115 -0
  22. data/lib/concurrent/atomic/read_write_lock.rb +5 -4
  23. data/lib/concurrent/atomic/reentrant_read_write_lock.rb +3 -1
  24. data/lib/concurrent/atomic/ruby_thread_local_var.rb +172 -0
  25. data/lib/concurrent/atomic/semaphore.rb +84 -178
  26. data/lib/concurrent/atomic/thread_local_var.rb +65 -294
  27. data/lib/concurrent/atomic_reference/jruby+truffle.rb +1 -0
  28. data/lib/concurrent/atomic_reference/jruby.rb +1 -1
  29. data/lib/concurrent/atomic_reference/mutex_atomic.rb +14 -8
  30. data/lib/concurrent/atomic_reference/ruby.rb +1 -1
  31. data/lib/concurrent/atomics.rb +7 -37
  32. data/lib/concurrent/collection/copy_on_notify_observer_set.rb +7 -15
  33. data/lib/concurrent/collection/copy_on_write_observer_set.rb +7 -15
  34. data/lib/concurrent/collection/java_non_concurrent_priority_queue.rb +84 -0
  35. data/lib/concurrent/collection/map/atomic_reference_map_backend.rb +927 -0
  36. data/lib/concurrent/collection/map/mri_map_backend.rb +66 -0
  37. data/lib/concurrent/collection/map/non_concurrent_map_backend.rb +144 -0
  38. data/lib/concurrent/collection/map/synchronized_map_backend.rb +86 -0
  39. data/lib/concurrent/collection/non_concurrent_priority_queue.rb +143 -0
  40. data/lib/concurrent/collection/ruby_non_concurrent_priority_queue.rb +150 -0
  41. data/lib/concurrent/concern/dereferenceable.rb +9 -24
  42. data/lib/concurrent/concern/logging.rb +1 -1
  43. data/lib/concurrent/concern/obligation.rb +11 -20
  44. data/lib/concurrent/concern/observable.rb +38 -13
  45. data/lib/concurrent/configuration.rb +23 -152
  46. data/lib/concurrent/constants.rb +8 -0
  47. data/lib/concurrent/delay.rb +14 -12
  48. data/lib/concurrent/exchanger.rb +339 -41
  49. data/lib/concurrent/executor/abstract_executor_service.rb +134 -0
  50. data/lib/concurrent/executor/executor_service.rb +23 -359
  51. data/lib/concurrent/executor/immediate_executor.rb +3 -2
  52. data/lib/concurrent/executor/java_executor_service.rb +100 -0
  53. data/lib/concurrent/executor/java_single_thread_executor.rb +3 -3
  54. data/lib/concurrent/executor/java_thread_pool_executor.rb +3 -4
  55. data/lib/concurrent/executor/ruby_executor_service.rb +78 -0
  56. data/lib/concurrent/executor/ruby_single_thread_executor.rb +10 -66
  57. data/lib/concurrent/executor/ruby_thread_pool_executor.rb +25 -22
  58. data/lib/concurrent/executor/safe_task_executor.rb +6 -7
  59. data/lib/concurrent/executor/serial_executor_service.rb +34 -0
  60. data/lib/concurrent/executor/serialized_execution.rb +10 -33
  61. data/lib/concurrent/executor/serialized_execution_delegator.rb +28 -0
  62. data/lib/concurrent/executor/simple_executor_service.rb +1 -10
  63. data/lib/concurrent/executor/single_thread_executor.rb +20 -10
  64. data/lib/concurrent/executor/timer_set.rb +8 -10
  65. data/lib/concurrent/executors.rb +12 -2
  66. data/lib/concurrent/future.rb +6 -4
  67. data/lib/concurrent/hash.rb +35 -0
  68. data/lib/concurrent/immutable_struct.rb +5 -1
  69. data/lib/concurrent/ivar.rb +12 -16
  70. data/lib/concurrent/lazy_register.rb +11 -8
  71. data/lib/concurrent/map.rb +180 -0
  72. data/lib/concurrent/maybe.rb +6 -3
  73. data/lib/concurrent/mutable_struct.rb +7 -6
  74. data/lib/concurrent/mvar.rb +26 -2
  75. data/lib/concurrent/{executor/executor.rb → options.rb} +5 -29
  76. data/lib/concurrent/promise.rb +7 -5
  77. data/lib/concurrent/scheduled_task.rb +13 -71
  78. data/lib/concurrent/settable_struct.rb +5 -4
  79. data/lib/concurrent/synchronization.rb +15 -3
  80. data/lib/concurrent/synchronization/abstract_lockable_object.rb +98 -0
  81. data/lib/concurrent/synchronization/abstract_object.rb +7 -146
  82. data/lib/concurrent/synchronization/abstract_struct.rb +2 -3
  83. data/lib/concurrent/synchronization/condition.rb +6 -4
  84. data/lib/concurrent/synchronization/jruby_lockable_object.rb +13 -0
  85. data/lib/concurrent/synchronization/jruby_object.rb +44 -0
  86. data/lib/concurrent/synchronization/lock.rb +3 -2
  87. data/lib/concurrent/synchronization/lockable_object.rb +72 -0
  88. data/lib/concurrent/synchronization/mri_lockable_object.rb +71 -0
  89. data/lib/concurrent/synchronization/mri_object.rb +43 -0
  90. data/lib/concurrent/synchronization/object.rb +140 -73
  91. data/lib/concurrent/synchronization/rbx_lockable_object.rb +65 -0
  92. data/lib/concurrent/synchronization/rbx_object.rb +30 -73
  93. data/lib/concurrent/synchronization/volatile.rb +34 -0
  94. data/lib/concurrent/thread_safe/synchronized_delegator.rb +50 -0
  95. data/lib/concurrent/thread_safe/util.rb +14 -0
  96. data/lib/concurrent/thread_safe/util/adder.rb +74 -0
  97. data/lib/concurrent/thread_safe/util/array_hash_rbx.rb +30 -0
  98. data/lib/concurrent/thread_safe/util/cheap_lockable.rb +118 -0
  99. data/lib/concurrent/thread_safe/util/power_of_two_tuple.rb +38 -0
  100. data/lib/concurrent/thread_safe/util/striped64.rb +241 -0
  101. data/lib/concurrent/thread_safe/util/volatile.rb +75 -0
  102. data/lib/concurrent/thread_safe/util/xor_shift_random.rb +50 -0
  103. data/lib/concurrent/timer_task.rb +3 -4
  104. data/lib/concurrent/tuple.rb +86 -0
  105. data/lib/concurrent/tvar.rb +5 -1
  106. data/lib/concurrent/utility/at_exit.rb +1 -1
  107. data/lib/concurrent/utility/engine.rb +4 -0
  108. data/lib/concurrent/utility/monotonic_time.rb +3 -4
  109. data/lib/concurrent/utility/native_extension_loader.rb +50 -30
  110. data/lib/concurrent/version.rb +2 -2
  111. data/lib/concurrent_ruby_ext.jar +0 -0
  112. metadata +47 -12
  113. data/lib/concurrent/atomic/condition.rb +0 -78
  114. data/lib/concurrent/collection/priority_queue.rb +0 -360
  115. data/lib/concurrent/synchronization/java_object.rb +0 -34
  116. data/lib/concurrent/synchronization/monitor_object.rb +0 -27
  117. data/lib/concurrent/synchronization/mutex_object.rb +0 -43
  118. data/lib/concurrent/utilities.rb +0 -5
  119. data/lib/concurrent/utility/timeout.rb +0 -39
  120. data/lib/concurrent/utility/timer.rb +0 -26
  121. data/lib/concurrent_ruby.rb +0 -2
@@ -7,19 +7,22 @@ module Concurrent
7
7
  #
8
8
  # @example
9
9
  # register = Concurrent::LazyRegister.new
10
- # #=> #<Concurrent::LazyRegister:0x007fd7ecd5e230 @data=#<Concurrent::AtomicReference:0x007fd7ecd5e1e0>>
10
+ # #=> #<Concurrent::LazyRegister:0x007fd7ecd5e230 @Data=#<Concurrent::AtomicReference:0x007fd7ecd5e1e0>>
11
11
  # register[:key]
12
12
  # #=> nil
13
13
  # register.add(:key) { Concurrent::Actor.spawn!(Actor::AdHoc, :ping) { -> message { message } } }
14
- # #=> #<Concurrent::LazyRegister:0x007fd7ecd5e230 @data=#<Concurrent::AtomicReference:0x007fd7ecd5e1e0>>
14
+ # #=> #<Concurrent::LazyRegister:0x007fd7ecd5e230 @Data=#<Concurrent::AtomicReference:0x007fd7ecd5e1e0>>
15
15
  # register[:key]
16
16
  # #=> #<Concurrent::Actor::Reference /ping (Concurrent::Actor::AdHoc)>
17
17
  #
18
18
  # @!macro edge_warning
19
- class LazyRegister
19
+ class LazyRegister < Synchronization::Object
20
+
21
+ private(*attr_atomic(:data))
20
22
 
21
23
  def initialize
22
- @data = AtomicReference.new(Hash.new)
24
+ super
25
+ self.data = {}
23
26
  end
24
27
 
25
28
  # Element reference. Retrieves the value object corresponding to the
@@ -31,7 +34,7 @@ module Concurrent
31
34
  #
32
35
  # @raise Exception when the initialization block fails
33
36
  def [](key)
34
- delay = @data.get[key]
37
+ delay = data[key]
35
38
  delay ? delay.value! : nil
36
39
  end
37
40
 
@@ -40,7 +43,7 @@ module Concurrent
40
43
  # @param [Object] key
41
44
  # @return [true, false] if the key is registered
42
45
  def registered?(key)
43
- @data.get.key?(key)
46
+ data.key?(key)
44
47
  end
45
48
 
46
49
  alias_method :key?, :registered?
@@ -55,7 +58,7 @@ module Concurrent
55
58
  # @return [LazyRegister] self
56
59
  def register(key, &block)
57
60
  delay = Delay.new(executor: :immediate, &block)
58
- @data.update { |h| h.merge(key => delay) }
61
+ update_data { |h| h.merge(key => delay) }
59
62
  self
60
63
  end
61
64
 
@@ -68,7 +71,7 @@ module Concurrent
68
71
  #
69
72
  # @return [LazyRegister] self
70
73
  def unregister(key)
71
- @data.update { |h| h.dup.tap { |j| j.delete(key) } }
74
+ update_data { |h| h.dup.tap { |j| j.delete(key) } }
72
75
  self
73
76
  end
74
77
 
@@ -0,0 +1,180 @@
1
+ require 'thread'
2
+ require 'concurrent/constants'
3
+ require 'concurrent/synchronization'
4
+
5
+ module Concurrent
6
+ # @!visibility private
7
+ module Collection
8
+
9
+ # @!visibility private
10
+ MapImplementation = if Concurrent.java_extensions_loaded?
11
+ # noinspection RubyResolve
12
+ JRubyMapBackend
13
+ elsif defined?(RUBY_ENGINE)
14
+ case RUBY_ENGINE
15
+ when 'ruby'
16
+ require 'concurrent/collection/map/mri_map_backend'
17
+ MriMapBackend
18
+ when 'rbx'
19
+ require 'concurrent/collection/map/atomic_reference_map_backend'
20
+ AtomicReferenceMapBackend
21
+ else
22
+ warn 'Concurrent::Map: unsupported Ruby engine, using a fully synchronized Concurrent::Map implementation' if $VERBOSE
23
+ require 'concurrent/collection/map/synchronized_map_backend'
24
+ SynchronizedMapBackend
25
+ end
26
+ else
27
+ MriMapBackend
28
+ end
29
+ end
30
+
31
+ # `Concurrent::Map` is a hash-like object and should have much better performance
32
+ # characteristics, especially under high concurrency, than `Concurrent::Hash`.
33
+ # However, `Concurrent::Map `is not strictly semantically equivalent to a ruby `Hash`
34
+ # -- for instance, it does not necessarily retain ordering by insertion time as `Hash`
35
+ # does. For most uses it should do fine though, and we recommend you consider
36
+ # `Concurrent::Map` instead of `Concurrent::Hash` for your concurrency-safe hash needs.
37
+ #
38
+ # > require 'concurrent'
39
+ # >
40
+ # > map = Concurrent::Map.new
41
+
42
+ class Map < Collection::MapImplementation
43
+ def initialize(options = nil, &block)
44
+ if options.kind_of?(::Hash)
45
+ validate_options_hash!(options)
46
+ else
47
+ options = nil
48
+ end
49
+
50
+ super(options)
51
+ @default_proc = block
52
+ end
53
+
54
+ def [](key)
55
+ if value = super # non-falsy value is an existing mapping, return it right away
56
+ value
57
+ # re-check is done with get_or_default(key, NULL) instead of a simple !key?(key) in order to avoid a race condition, whereby by the time the current thread gets to the key?(key) call
58
+ # a key => value mapping might have already been created by a different thread (key?(key) would then return true, this elsif branch wouldn't be taken and an incorrent +nil+ value
59
+ # would be returned)
60
+ # note: nil == value check is not technically necessary
61
+ elsif @default_proc && nil == value && NULL == (value = get_or_default(key, NULL))
62
+ @default_proc.call(self, key)
63
+ else
64
+ value
65
+ end
66
+ end
67
+
68
+ alias_method :get, :[]
69
+ alias_method :put, :[]=
70
+
71
+ def fetch(key, default_value = NULL)
72
+ if NULL != (value = get_or_default(key, NULL))
73
+ value
74
+ elsif block_given?
75
+ yield key
76
+ elsif NULL != default_value
77
+ default_value
78
+ else
79
+ raise_fetch_no_key
80
+ end
81
+ end
82
+
83
+ def fetch_or_store(key, default_value = NULL)
84
+ fetch(key) do
85
+ put(key, block_given? ? yield(key) : (NULL == default_value ? raise_fetch_no_key : default_value))
86
+ end
87
+ end
88
+
89
+ def put_if_absent(key, value)
90
+ computed = false
91
+ result = compute_if_absent(key) do
92
+ computed = true
93
+ value
94
+ end
95
+ computed ? nil : result
96
+ end unless method_defined?(:put_if_absent)
97
+
98
+ def value?(value)
99
+ each_value do |v|
100
+ return true if value.equal?(v)
101
+ end
102
+ false
103
+ end unless method_defined?(:value?)
104
+
105
+ def keys
106
+ arr = []
107
+ each_pair {|k, v| arr << k}
108
+ arr
109
+ end unless method_defined?(:keys)
110
+
111
+ def values
112
+ arr = []
113
+ each_pair {|k, v| arr << v}
114
+ arr
115
+ end unless method_defined?(:values)
116
+
117
+ def each_key
118
+ each_pair {|k, v| yield k}
119
+ end unless method_defined?(:each_key)
120
+
121
+ def each_value
122
+ each_pair {|k, v| yield v}
123
+ end unless method_defined?(:each_value)
124
+
125
+ def key(value)
126
+ each_pair {|k, v| return k if v == value}
127
+ nil
128
+ end unless method_defined?(:key)
129
+ alias_method :index, :key if RUBY_VERSION < '1.9'
130
+
131
+ def empty?
132
+ each_pair {|k, v| return false}
133
+ true
134
+ end unless method_defined?(:empty?)
135
+
136
+ def size
137
+ count = 0
138
+ each_pair {|k, v| count += 1}
139
+ count
140
+ end unless method_defined?(:size)
141
+
142
+ def marshal_dump
143
+ raise TypeError, "can't dump hash with default proc" if @default_proc
144
+ h = {}
145
+ each_pair {|k, v| h[k] = v}
146
+ h
147
+ end
148
+
149
+ def marshal_load(hash)
150
+ initialize
151
+ populate_from(hash)
152
+ end
153
+
154
+ undef :freeze
155
+
156
+ private
157
+ def raise_fetch_no_key
158
+ raise KeyError, 'key not found'
159
+ end
160
+
161
+ def initialize_copy(other)
162
+ super
163
+ populate_from(other)
164
+ end
165
+
166
+ def populate_from(hash)
167
+ hash.each_pair {|k, v| self[k] = v}
168
+ self
169
+ end
170
+
171
+ def validate_options_hash!(options)
172
+ if (initial_capacity = options[:initial_capacity]) && (!initial_capacity.kind_of?(Fixnum) || initial_capacity < 0)
173
+ raise ArgumentError, ":initial_capacity must be a positive Fixnum"
174
+ end
175
+ if (load_factor = options[:load_factor]) && (!load_factor.kind_of?(Numeric) || load_factor <= 0 || load_factor > 1)
176
+ raise ArgumentError, ":load_factor must be a number between 0 and 1"
177
+ end
178
+ end
179
+ end
180
+ end
@@ -1,3 +1,5 @@
1
+ require 'concurrent/synchronization'
2
+
1
3
  module Concurrent
2
4
 
3
5
  # A `Maybe` encapsulates an optional value. A `Maybe` either contains a value
@@ -99,8 +101,9 @@ module Concurrent
99
101
  #
100
102
  # @see https://hackage.haskell.org/package/base-4.2.0.1/docs/Data-Maybe.html Haskell Data.Maybe
101
103
  # @see https://github.com/purescript/purescript-maybe/blob/master/docs/Data.Maybe.md PureScript Data.Maybe
102
- class Maybe
104
+ class Maybe < Synchronization::Object
103
105
  include Comparable
106
+ safe_initialization!
104
107
 
105
108
  # Indicates that the given attribute has not been set.
106
109
  # When `Just` the {#nothing} getter will return `NONE`.
@@ -168,7 +171,7 @@ module Concurrent
168
171
  end
169
172
 
170
173
  # Is this `Maybe` a `Just` (successfully fulfilled with a value)?
171
- #
174
+ #
172
175
  # @return [Boolean] True if `Just` or false if `Nothing`.
173
176
  def just?
174
177
  ! nothing?
@@ -176,7 +179,7 @@ module Concurrent
176
179
  alias :fulfilled? :just?
177
180
 
178
181
  # Is this `Maybe` a `nothing` (rejected with an exception upon fulfillment)?
179
- #
182
+ #
180
183
  # @return [Boolean] True if `Nothing` or false if `Just`.
181
184
  def nothing?
182
185
  @nothing != NONE
@@ -75,7 +75,7 @@ module Concurrent
75
75
  alias_method :to_s, :inspect
76
76
 
77
77
  # @!macro [attach] struct_merge
78
- #
78
+ #
79
79
  # Returns a new struct containing the contents of `other` and the contents
80
80
  # of `self`. If no block is specified, the value for entries with duplicate
81
81
  # keys will be that of `other`. Otherwise the value for each duplicate key
@@ -98,7 +98,7 @@ module Concurrent
98
98
  # @!macro [attach] struct_to_h
99
99
  #
100
100
  # Returns a hash containing the names and values for the struct’s members.
101
- #
101
+ #
102
102
  # @return [Hash] the names and values for the struct’s members
103
103
  def to_h
104
104
  synchronize { ns_to_h }
@@ -184,8 +184,9 @@ module Concurrent
184
184
  # @raise [IndexError] if the index is out of range.
185
185
  def []=(member, value)
186
186
  if member.is_a? Integer
187
- if member >= @values.length
188
- raise IndexError.new("offset #{member} too large for struct(size:#{@values.length})")
187
+ length = synchronize { @values.length }
188
+ if member >= length
189
+ raise IndexError.new("offset #{member} too large for struct(size:#{length})")
189
190
  end
190
191
  synchronize { @values[member] = value }
191
192
  else
@@ -206,10 +207,10 @@ module Concurrent
206
207
  FACTORY.define_struct(clazz_name, args, &block)
207
208
  end
208
209
 
209
- FACTORY = Class.new(Synchronization::Object) do
210
+ FACTORY = Class.new(Synchronization::LockableObject) do
210
211
  def define_struct(name, members, &block)
211
212
  synchronize do
212
- clazz = Synchronization::AbstractStruct.define_struct_class(MutableStruct, Synchronization::Object, name, members, &block)
213
+ clazz = Synchronization::AbstractStruct.define_struct_class(MutableStruct, Synchronization::LockableObject, name, members, &block)
213
214
  members.each_with_index do |member, index|
214
215
  clazz.send(:define_method, member) do
215
216
  synchronize { @values[index] }
@@ -1,4 +1,5 @@
1
1
  require 'concurrent/concern/dereferenceable'
2
+ require 'concurrent/synchronization'
2
3
 
3
4
  module Concurrent
4
5
 
@@ -34,9 +35,9 @@ module Concurrent
34
35
  # 2. S. Peyton Jones, A. Gordon, and S. Finne. [Concurrent Haskell](http://dl.acm.org/citation.cfm?id=237794).
35
36
  # In Proceedings of the 23rd Symposium on Principles of Programming Languages
36
37
  # (PoPL), 1996.
37
- class MVar
38
-
38
+ class MVar < Synchronization::Object
39
39
  include Concern::Dereferenceable
40
+ safe_initialization!
40
41
 
41
42
  # Unique value that represents that an `MVar` was empty
42
43
  EMPTY = Object.new
@@ -78,6 +79,23 @@ module Concurrent
78
79
  end
79
80
  end
80
81
 
82
+ # acquires lock on the from an `MVAR`, yields the value to provided block,
83
+ # and release lock. A timeout can be set to limit the time spent blocked,
84
+ # in which case it returns `TIMEOUT` if the time is exceeded.
85
+ # @return [Object] the value returned by the block, or `TIMEOUT`
86
+ def borrow(timeout = nil)
87
+ @mutex.synchronize do
88
+ wait_for_full(timeout)
89
+
90
+ # if we timeoud out we'll still be empty
91
+ if unlocked_full?
92
+ yield @value
93
+ else
94
+ TIMEOUT
95
+ end
96
+ end
97
+ end
98
+
81
99
  # Put a value into an `MVar`, blocking if there is already a value until
82
100
  # it is empty. A timeout can be set to limit the time spent blocked, in
83
101
  # which case it returns `TIMEOUT` if the time is exceeded.
@@ -183,6 +201,12 @@ module Concurrent
183
201
  !empty?
184
202
  end
185
203
 
204
+ protected
205
+
206
+ def synchronize(&block)
207
+ @mutex.synchronize(&block)
208
+ end
209
+
186
210
  private
187
211
 
188
212
  def unlocked_empty?
@@ -1,12 +1,11 @@
1
+ # This file has circular require issues. It must be autoloaded.
2
+
1
3
  require 'concurrent/configuration'
2
- require 'concurrent/concern/deprecation'
3
- require 'concurrent/executor/executor_service'
4
4
 
5
5
  module Concurrent
6
6
 
7
7
  # @!visibility private
8
- module Executor
9
- extend Concern::Deprecation
8
+ module Options
10
9
 
11
10
  # Get the requested `Executor` based on the values set in the options hash.
12
11
  #
@@ -20,25 +19,8 @@ module Concurrent
20
19
  #
21
20
  # @!visibility private
22
21
  def self.executor_from_options(opts = {}) # :nodoc:
23
- case
24
- when opts.key?(:executor)
25
- if opts[:executor].nil?
26
- nil
27
- else
28
- executor(opts[:executor])
29
- end
30
- when opts.key?(:operation) || opts.key?(:task)
31
- if opts[:operation] == true || opts[:task] == false
32
- deprecated 'use `executor: :fast` instead'
33
- return Concurrent.global_fast_executor
34
- end
35
-
36
- if opts[:operation] == false || opts[:task] == true
37
- deprecated 'use `executor: :io` instead'
38
- return Concurrent.global_io_executor
39
- end
40
-
41
- raise ArgumentError.new("executor '#{opts[:executor]}' not recognized")
22
+ if identifier = opts.fetch(:executor, nil)
23
+ executor(identifier)
42
24
  else
43
25
  nil
44
26
  end
@@ -52,12 +34,6 @@ module Concurrent
52
34
  Concurrent.global_io_executor
53
35
  when :immediate
54
36
  Concurrent.global_immediate_executor
55
- when :operation
56
- deprecated 'use `executor: :fast` instead'
57
- Concurrent.global_fast_executor
58
- when :task
59
- deprecated 'use `executor: :io` instead'
60
- Concurrent.global_io_executor
61
37
  when Concurrent::ExecutorService
62
38
  executor_identifier
63
39
  else
@@ -1,10 +1,12 @@
1
1
  require 'thread'
2
+ require 'concurrent/constants'
2
3
  require 'concurrent/errors'
3
4
  require 'concurrent/ivar'
4
- require 'concurrent/executor/executor'
5
5
 
6
6
  module Concurrent
7
7
 
8
+ autoload :Options, 'concurrent/options'
9
+
8
10
  PromiseExecutionError = Class.new(StandardError)
9
11
 
10
12
  # Promises are inspired by the JavaScript [Promises/A](http://wiki.commonjs.org/wiki/Promises/A)
@@ -205,7 +207,7 @@ module Concurrent
205
207
  # @see http://promises-aplus.github.io/promises-spec/
206
208
  def initialize(opts = {}, &block)
207
209
  opts.delete_if { |k, v| v.nil? }
208
- super(IVar::NO_VALUE, opts.merge(__promise_body_from_block__: block), &nil)
210
+ super(NULL, opts.merge(__promise_body_from_block__: block), &nil)
209
211
  end
210
212
 
211
213
  # Create a new `Promise` and fulfill it immediately.
@@ -254,7 +256,7 @@ module Concurrent
254
256
  # @!macro ivar_set_method
255
257
  #
256
258
  # @raise [Concurrent::PromiseExecutionError] if not the root promise
257
- def set(value = IVar::NO_VALUE, &block)
259
+ def set(value = NULL, &block)
258
260
  raise PromiseExecutionError.new('supported only on root promise') unless root?
259
261
  check_for_block_or_value!(block_given?, value)
260
262
  synchronize do
@@ -302,7 +304,7 @@ module Concurrent
302
304
  # @return [Promise] the new promise
303
305
  def then(rescuer = nil, &block)
304
306
  raise ArgumentError.new('rescuers and block are both missing') if rescuer.nil? && !block_given?
305
- block = Proc.new { |result| result } if block.nil?
307
+ block = Proc.new { |result| result } unless block_given?
306
308
  child = Promise.new(
307
309
  parent: self,
308
310
  executor: @executor,
@@ -441,7 +443,7 @@ module Concurrent
441
443
  def ns_initialize(value, opts)
442
444
  super
443
445
 
444
- @executor = Executor.executor_from_options(opts) || Concurrent.global_io_executor
446
+ @executor = Options.executor_from_options(opts) || Concurrent.global_io_executor
445
447
  @args = get_arguments_from(opts)
446
448
 
447
449
  @parent = opts.fetch(:parent) { nil }