concurrent-ruby 0.9.2-java → 1.0.0-java

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 (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 }