concurrent-ruby 1.0.5 → 1.1.0.pre1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (107) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +42 -0
  3. data/Gemfile +39 -0
  4. data/{LICENSE.txt → LICENSE.md} +2 -0
  5. data/README.md +203 -105
  6. data/Rakefile +278 -0
  7. data/ext/concurrent-ruby/ConcurrentRubyService.java +17 -0
  8. data/ext/concurrent-ruby/com/concurrent_ruby/ext/AtomicReferenceLibrary.java +175 -0
  9. data/ext/concurrent-ruby/com/concurrent_ruby/ext/JRubyMapBackendLibrary.java +248 -0
  10. data/ext/concurrent-ruby/com/concurrent_ruby/ext/JavaAtomicBooleanLibrary.java +93 -0
  11. data/ext/concurrent-ruby/com/concurrent_ruby/ext/JavaAtomicFixnumLibrary.java +113 -0
  12. data/ext/concurrent-ruby/com/concurrent_ruby/ext/JavaSemaphoreLibrary.java +159 -0
  13. data/ext/concurrent-ruby/com/concurrent_ruby/ext/SynchronizationLibrary.java +304 -0
  14. data/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166e/ConcurrentHashMap.java +31 -0
  15. data/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166e/ConcurrentHashMapV8.java +3863 -0
  16. data/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166e/LongAdder.java +203 -0
  17. data/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166e/Striped64.java +342 -0
  18. data/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166e/nounsafe/ConcurrentHashMapV8.java +3800 -0
  19. data/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166e/nounsafe/LongAdder.java +204 -0
  20. data/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166e/nounsafe/Striped64.java +291 -0
  21. data/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166y/ThreadLocalRandom.java +199 -0
  22. data/lib/concurrent-ruby.rb +1 -0
  23. data/lib/concurrent.rb +24 -20
  24. data/lib/concurrent/agent.rb +7 -7
  25. data/lib/concurrent/array.rb +59 -32
  26. data/lib/concurrent/async.rb +4 -4
  27. data/lib/concurrent/atom.rb +9 -9
  28. data/lib/concurrent/atomic/atomic_boolean.rb +24 -20
  29. data/lib/concurrent/atomic/atomic_fixnum.rb +27 -23
  30. data/lib/concurrent/atomic/atomic_markable_reference.rb +164 -0
  31. data/lib/concurrent/atomic/atomic_reference.rb +176 -33
  32. data/lib/concurrent/atomic/count_down_latch.rb +6 -6
  33. data/lib/concurrent/atomic/cyclic_barrier.rb +1 -1
  34. data/lib/concurrent/atomic/event.rb +1 -1
  35. data/lib/concurrent/atomic/java_count_down_latch.rb +6 -5
  36. data/lib/concurrent/atomic/mutex_count_down_latch.rb +1 -0
  37. data/lib/concurrent/atomic/read_write_lock.rb +2 -1
  38. data/lib/concurrent/atomic/reentrant_read_write_lock.rb +3 -1
  39. data/lib/concurrent/atomic/semaphore.rb +8 -8
  40. data/lib/concurrent/atomic/thread_local_var.rb +7 -7
  41. data/lib/concurrent/atomic_reference/mutex_atomic.rb +3 -8
  42. data/lib/concurrent/atomic_reference/numeric_cas_wrapper.rb +1 -1
  43. data/lib/concurrent/atomics.rb +0 -43
  44. data/lib/concurrent/collection/lock_free_stack.rb +127 -0
  45. data/lib/concurrent/collection/map/atomic_reference_map_backend.rb +3 -3
  46. data/lib/concurrent/collection/map/non_concurrent_map_backend.rb +1 -2
  47. data/lib/concurrent/collection/non_concurrent_priority_queue.rb +29 -29
  48. data/lib/concurrent/concern/dereferenceable.rb +1 -1
  49. data/lib/concurrent/concern/logging.rb +6 -1
  50. data/lib/concurrent/concern/observable.rb +7 -7
  51. data/lib/concurrent/concurrent_ruby.jar +0 -0
  52. data/lib/concurrent/configuration.rb +1 -6
  53. data/lib/concurrent/constants.rb +1 -1
  54. data/lib/concurrent/dataflow.rb +2 -1
  55. data/lib/concurrent/delay.rb +9 -7
  56. data/lib/concurrent/exchanger.rb +13 -21
  57. data/lib/concurrent/executor/abstract_executor_service.rb +2 -2
  58. data/lib/concurrent/executor/cached_thread_pool.rb +1 -1
  59. data/lib/concurrent/executor/executor_service.rb +15 -15
  60. data/lib/concurrent/executor/fixed_thread_pool.rb +18 -18
  61. data/lib/concurrent/executor/java_thread_pool_executor.rb +10 -7
  62. data/lib/concurrent/executor/single_thread_executor.rb +2 -2
  63. data/lib/concurrent/executor/thread_pool_executor.rb +6 -6
  64. data/lib/concurrent/executor/timer_set.rb +1 -1
  65. data/lib/concurrent/future.rb +4 -1
  66. data/lib/concurrent/hash.rb +53 -30
  67. data/lib/concurrent/ivar.rb +5 -6
  68. data/lib/concurrent/map.rb +20 -25
  69. data/lib/concurrent/maybe.rb +1 -1
  70. data/lib/concurrent/mutable_struct.rb +15 -14
  71. data/lib/concurrent/mvar.rb +2 -2
  72. data/lib/concurrent/promise.rb +53 -21
  73. data/lib/concurrent/promises.rb +1938 -0
  74. data/lib/concurrent/re_include.rb +58 -0
  75. data/lib/concurrent/set.rb +66 -0
  76. data/lib/concurrent/settable_struct.rb +1 -0
  77. data/lib/concurrent/synchronization.rb +4 -5
  78. data/lib/concurrent/synchronization/abstract_lockable_object.rb +5 -5
  79. data/lib/concurrent/synchronization/abstract_struct.rb +6 -4
  80. data/lib/concurrent/synchronization/lockable_object.rb +6 -6
  81. data/lib/concurrent/synchronization/{mri_lockable_object.rb → mutex_lockable_object.rb} +19 -14
  82. data/lib/concurrent/synchronization/object.rb +8 -4
  83. data/lib/concurrent/synchronization/truffleruby_object.rb +46 -0
  84. data/lib/concurrent/synchronization/volatile.rb +11 -9
  85. data/lib/concurrent/thread_safe/util/data_structures.rb +55 -0
  86. data/lib/concurrent/thread_safe/util/striped64.rb +9 -4
  87. data/lib/concurrent/timer_task.rb +5 -2
  88. data/lib/concurrent/tuple.rb +1 -1
  89. data/lib/concurrent/tvar.rb +2 -2
  90. data/lib/concurrent/utility/at_exit.rb +1 -1
  91. data/lib/concurrent/utility/engine.rb +2 -2
  92. data/lib/concurrent/utility/monotonic_time.rb +3 -3
  93. data/lib/concurrent/utility/native_extension_loader.rb +31 -33
  94. data/lib/concurrent/utility/processor_counter.rb +0 -2
  95. data/lib/concurrent/version.rb +2 -2
  96. metadata +35 -21
  97. data/lib/concurrent/atomic_reference/concurrent_update_error.rb +0 -8
  98. data/lib/concurrent/atomic_reference/direct_update.rb +0 -81
  99. data/lib/concurrent/atomic_reference/jruby+truffle.rb +0 -2
  100. data/lib/concurrent/atomic_reference/jruby.rb +0 -16
  101. data/lib/concurrent/atomic_reference/rbx.rb +0 -22
  102. data/lib/concurrent/atomic_reference/ruby.rb +0 -32
  103. data/lib/concurrent/edge.rb +0 -26
  104. data/lib/concurrent/lazy_register.rb +0 -81
  105. data/lib/concurrent/synchronization/truffle_lockable_object.rb +0 -9
  106. data/lib/concurrent/synchronization/truffle_object.rb +0 -31
  107. data/lib/concurrent/thread_safe/util/array_hash_rbx.rb +0 -30
@@ -90,10 +90,10 @@ if Concurrent.on_jruby?
90
90
  private
91
91
 
92
92
  def ns_initialize(opts)
93
- min_length = opts.fetch(:min_threads, DEFAULT_MIN_POOL_SIZE).to_i
94
- max_length = opts.fetch(:max_threads, DEFAULT_MAX_POOL_SIZE).to_i
95
- idletime = opts.fetch(:idletime, DEFAULT_THREAD_IDLETIMEOUT).to_i
96
- @max_queue = opts.fetch(:max_queue, DEFAULT_MAX_QUEUE_SIZE).to_i
93
+ min_length = opts.fetch(:min_threads, DEFAULT_MIN_POOL_SIZE).to_i
94
+ max_length = opts.fetch(:max_threads, DEFAULT_MAX_POOL_SIZE).to_i
95
+ idletime = opts.fetch(:idletime, DEFAULT_THREAD_IDLETIMEOUT).to_i
96
+ @max_queue = opts.fetch(:max_queue, DEFAULT_MAX_QUEUE_SIZE).to_i
97
97
  @fallback_policy = opts.fetch(:fallback_policy, :abort)
98
98
 
99
99
  raise ArgumentError.new("`max_threads` cannot be less than #{DEFAULT_MIN_POOL_SIZE}") if max_length < DEFAULT_MIN_POOL_SIZE
@@ -109,9 +109,12 @@ if Concurrent.on_jruby?
109
109
  end
110
110
 
111
111
  @executor = java.util.concurrent.ThreadPoolExecutor.new(
112
- min_length, max_length,
113
- idletime, java.util.concurrent.TimeUnit::SECONDS,
114
- queue, FALLBACK_POLICY_CLASSES[@fallback_policy].new)
112
+ min_length,
113
+ max_length,
114
+ idletime,
115
+ java.util.concurrent.TimeUnit::SECONDS,
116
+ queue,
117
+ FALLBACK_POLICY_CLASSES[@fallback_policy].new)
115
118
 
116
119
  self.auto_terminate = opts.fetch(:auto_terminate, true)
117
120
  end
@@ -14,7 +14,7 @@ module Concurrent
14
14
  end
15
15
  private_constant :SingleThreadExecutorImplementation
16
16
 
17
- # @!macro [attach] single_thread_executor
17
+ # @!macro single_thread_executor
18
18
  #
19
19
  # A thread pool with a single thread an unlimited queue. Should the thread
20
20
  # die for any reason it will be removed and replaced, thus ensuring that
@@ -35,7 +35,7 @@ module Concurrent
35
35
  # @!macro abstract_executor_service_public_api
36
36
  class SingleThreadExecutor < SingleThreadExecutorImplementation
37
37
 
38
- # @!macro [new] single_thread_executor_method_initialize
38
+ # @!macro single_thread_executor_method_initialize
39
39
  #
40
40
  # Create a new thread pool.
41
41
  #
@@ -15,7 +15,7 @@ module Concurrent
15
15
  end
16
16
  private_constant :ThreadPoolExecutorImplementation
17
17
 
18
- # @!macro [attach] thread_pool_executor
18
+ # @!macro thread_pool_executor
19
19
  #
20
20
  # An abstraction composed of one or more threads and a task queue. Tasks
21
21
  # (blocks or `proc` objects) are submitted to the pool and added to the queue.
@@ -55,12 +55,12 @@ module Concurrent
55
55
  # @!macro thread_pool_executor_public_api
56
56
  class ThreadPoolExecutor < ThreadPoolExecutorImplementation
57
57
 
58
- # @!macro [new] thread_pool_executor_method_initialize
58
+ # @!macro thread_pool_executor_method_initialize
59
59
  #
60
60
  # Create a new thread pool.
61
- #
61
+ #
62
62
  # @param [Hash] opts the options which configure the thread pool.
63
- #
63
+ #
64
64
  # @option opts [Integer] :max_threads (DEFAULT_MAX_POOL_SIZE) the maximum
65
65
  # number of threads to be created
66
66
  # @option opts [Integer] :min_threads (DEFAULT_MIN_POOL_SIZE) When a new task is submitted
@@ -73,12 +73,12 @@ module Concurrent
73
73
  # @option opts [Symbol] :fallback_policy (:abort) the policy for handling new
74
74
  # tasks that are received when the queue size has reached
75
75
  # `max_queue` or the executor has shut down
76
- #
76
+ #
77
77
  # @raise [ArgumentError] if `:max_threads` is less than one
78
78
  # @raise [ArgumentError] if `:min_threads` is less than zero
79
79
  # @raise [ArgumentError] if `:fallback_policy` is not one of the values specified
80
80
  # in `FALLBACK_POLICIES`
81
- #
81
+ #
82
82
  # @see http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ThreadPoolExecutor.html
83
83
 
84
84
  # @!method initialize(opts = {})
@@ -20,7 +20,7 @@ module Concurrent
20
20
 
21
21
  # Create a new set of timed tasks.
22
22
  #
23
- # @!macro [attach] executor_options
23
+ # @!macro executor_options
24
24
  #
25
25
  # @param [Hash] opts the options used to specify the executor on which to perform actions
26
26
  # @option opts [Executor] :executor when set use the given `Executor` instance.
@@ -6,9 +6,12 @@ require 'concurrent/executor/safe_task_executor'
6
6
 
7
7
  require 'concurrent/options'
8
8
 
9
+ # TODO (pitr-ch 14-Mar-2017): deprecate, Future, Promise, etc.
10
+
11
+
9
12
  module Concurrent
10
13
 
11
- # {include:file:doc/future.md}
14
+ # {include:file:docs-source/future.md}
12
15
  #
13
16
  # @!macro copy_options
14
17
  #
@@ -2,35 +2,58 @@ require 'concurrent/utility/engine'
2
2
  require 'concurrent/thread_safe/util'
3
3
 
4
4
  module Concurrent
5
- if Concurrent.on_cruby?
6
-
7
- # @!macro [attach] concurrent_hash
8
- #
9
- # A thread-safe subclass of Hash. This version locks against the object
10
- # itself for every method call, ensuring only one thread can be reading
11
- # or writing at a time. This includes iteration methods like `#each`,
12
- # which takes the lock repeatedly when reading an item.
13
- #
14
- # @see http://ruby-doc.org/core-2.2.0/Hash.html Ruby standard library `Hash`
15
- class Hash < ::Hash;
16
- end
17
-
18
- elsif Concurrent.on_jruby?
19
- require 'jruby/synchronized'
20
-
21
- # @!macro concurrent_hash
22
- class Hash < ::Hash
23
- include JRuby::Synchronized
24
- end
25
-
26
- elsif Concurrent.on_rbx? || Concurrent.on_truffle?
27
- require 'monitor'
28
- require 'concurrent/thread_safe/util/array_hash_rbx'
29
-
30
- # @!macro concurrent_hash
31
- class Hash < ::Hash
32
- end
33
-
34
- ThreadSafe::Util.make_synchronized_on_rbx Hash
5
+
6
+ # @!macro concurrent_hash
7
+ #
8
+ # A thread-safe subclass of Hash. This version locks against the object
9
+ # itself for every method call, ensuring only one thread can be reading
10
+ # or writing at a time. This includes iteration methods like `#each`,
11
+ # which takes the lock repeatedly when reading an item.
12
+ #
13
+ # @see http://ruby-doc.org/core-2.2.0/Hash.html Ruby standard library `Hash`
14
+
15
+ # @!macro internal_implementation_note
16
+ HashImplementation = case
17
+ when Concurrent.on_cruby?
18
+ # Because MRI never runs code in parallel, the existing
19
+ # non-thread-safe structures should usually work fine.
20
+ ::Hash
21
+
22
+ when Concurrent.on_jruby?
23
+ require 'jruby/synchronized'
24
+
25
+ class JRubyHash < ::Hash
26
+ include JRuby::Synchronized
27
+ end
28
+ JRubyHash
29
+
30
+ when Concurrent.on_rbx?
31
+ require 'monitor'
32
+ require 'concurrent/thread_safe/util/data_structures'
33
+
34
+ class RbxHash < ::Hash
35
+ end
36
+ ThreadSafe::Util.make_synchronized_on_rbx RbxHash
37
+ RbxHash
38
+
39
+ when Concurrent.on_truffleruby?
40
+ require 'concurrent/thread_safe/util/data_structures'
41
+
42
+ class TruffleRubyHash < ::Hash
43
+ end
44
+
45
+ ThreadSafe::Util.make_synchronized_on_truffleruby TruffleRubyHash
46
+ TruffleRubyHash
47
+
48
+ else
49
+ warn 'Possibly unsupported Ruby implementation'
50
+ ::Hash
51
+ end
52
+ private_constant :HashImplementation
53
+
54
+ # @!macro concurrent_hash
55
+ class Hash < HashImplementation
35
56
  end
57
+
36
58
  end
59
+
@@ -98,10 +98,10 @@ module Concurrent
98
98
  observer
99
99
  end
100
100
 
101
- # @!macro [attach] ivar_set_method
101
+ # @!macro ivar_set_method
102
102
  # Set the `IVar` to a value and wake or notify all threads waiting on it.
103
103
  #
104
- # @!macro [attach] ivar_set_parameters_and_exceptions
104
+ # @!macro ivar_set_parameters_and_exceptions
105
105
  # @param [Object] value the value to store in the `IVar`
106
106
  # @yield A block operation to use for setting the value
107
107
  # @raise [ArgumentError] if both a value and a block are given
@@ -124,7 +124,7 @@ module Concurrent
124
124
  self
125
125
  end
126
126
 
127
- # @!macro [attach] ivar_fail_method
127
+ # @!macro ivar_fail_method
128
128
  # Set the `IVar` to failed due to some error and wake or notify all threads waiting on it.
129
129
  #
130
130
  # @param [Object] reason for the failure
@@ -157,9 +157,8 @@ module Concurrent
157
157
  self.observers = Collection::CopyOnWriteObserverSet.new
158
158
  set_deref_options(opts)
159
159
 
160
- if value == NULL
161
- @state = :pending
162
- else
160
+ @state = :pending
161
+ if value != NULL
163
162
  ns_complete_without_notification(true, value, nil)
164
163
  end
165
164
  end
@@ -1,33 +1,27 @@
1
1
  require 'thread'
2
2
  require 'concurrent/constants'
3
3
  require 'concurrent/synchronization'
4
+ require 'concurrent/utility/engine'
4
5
 
5
6
  module Concurrent
6
7
  # @!visibility private
7
8
  module Collection
8
9
 
9
10
  # @!visibility private
10
- MapImplementation = if Concurrent.java_extensions_loaded?
11
+ MapImplementation = case
12
+ when Concurrent.on_jruby?
11
13
  # noinspection RubyResolve
12
14
  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
- when 'jruby+truffle'
22
- require 'concurrent/collection/map/atomic_reference_map_backend'
23
- AtomicReferenceMapBackend
24
- else
25
- warn 'Concurrent::Map: unsupported Ruby engine, using a fully synchronized Concurrent::Map implementation' if $VERBOSE
26
- require 'concurrent/collection/map/synchronized_map_backend'
27
- SynchronizedMapBackend
28
- end
29
- else
15
+ when Concurrent.on_cruby?
16
+ require 'concurrent/collection/map/mri_map_backend'
30
17
  MriMapBackend
18
+ when Concurrent.on_rbx? || Concurrent.on_truffleruby?
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'
23
+ require 'concurrent/collection/map/synchronized_map_backend'
24
+ SynchronizedMapBackend
31
25
  end
32
26
  end
33
27
 
@@ -43,7 +37,7 @@ module Concurrent
43
37
  # > map = Concurrent::Map.new
44
38
  class Map < Collection::MapImplementation
45
39
 
46
- # @!macro [new] map_method_is_atomic
40
+ # @!macro map_method_is_atomic
47
41
  # This method is atomic. Atomic methods of `Map` which accept a block
48
42
  # do not allow the `self` instance to be used within the block. Doing
49
43
  # so will cause a deadlock.
@@ -106,7 +100,7 @@ module Concurrent
106
100
  alias_method :get, :[]
107
101
  alias_method :put, :[]=
108
102
 
109
- # @!macro [attach] map_method_not_atomic
103
+ # @!macro map_method_not_atomic
110
104
  # The "fetch-then-act" methods of `Map` are not atomic. `Map` is intended
111
105
  # to be use as a concurrency primitive with strong happens-before
112
106
  # guarantees. It is not intended to be used as a high-level abstraction
@@ -171,6 +165,11 @@ module Concurrent
171
165
  each_pair {|k, v| yield v}
172
166
  end unless method_defined?(:each_value)
173
167
 
168
+ def each_pair
169
+ return enum_for :each_pair unless block_given?
170
+ super
171
+ end
172
+
174
173
  alias_method :each, :each_pair unless method_defined?(:each)
175
174
 
176
175
  def key(value)
@@ -205,12 +204,8 @@ module Concurrent
205
204
  undef :freeze
206
205
 
207
206
  # @!visibility private
208
- DEFAULT_OBJ_ID_STR_WIDTH = 0.size == 4 ? 7 : 14 # we want to look "native", 7 for 32-bit, 14 for 64-bit
209
- # override default #inspect() method: firstly, we don't want to be spilling our guts (i-vars), secondly, MRI backend's
210
- # #inspect() call on its @backend i-var will bump @backend's iter level while possibly yielding GVL
211
207
  def inspect
212
- id_str = (object_id << 1).to_s(16).rjust(DEFAULT_OBJ_ID_STR_WIDTH, '0')
213
- "#<#{self.class.name}:0x#{id_str} entries=#{size} default_proc=#{@default_proc.inspect}>"
208
+ format '%s entries=%d default_proc=%s>', to_s[0..-2], size.to_s, @default_proc.inspect
214
209
  end
215
210
 
216
211
  private
@@ -108,7 +108,7 @@ module Concurrent
108
108
  # Indicates that the given attribute has not been set.
109
109
  # When `Just` the {#nothing} getter will return `NONE`.
110
110
  # When `Nothing` the {#just} getter will return `NONE`.
111
- NONE = Object.new.freeze
111
+ NONE = ::Object.new.freeze
112
112
 
113
113
  # The value of a `Maybe` when `Just`. Will be `NONE` when `Nothing`.
114
114
  attr_reader :just
@@ -10,7 +10,7 @@ module Concurrent
10
10
  module MutableStruct
11
11
  include Synchronization::AbstractStruct
12
12
 
13
- # @!macro [new] struct_new
13
+ # @!macro struct_new
14
14
  #
15
15
  # Factory for creating new struct classes.
16
16
  #
@@ -42,7 +42,7 @@ module Concurrent
42
42
  #
43
43
  # @see http://ruby-doc.org/core-2.2.0/Struct.html#method-c-new Ruby standard library `Struct#new`
44
44
 
45
- # @!macro [attach] struct_values
45
+ # @!macro struct_values
46
46
  #
47
47
  # Returns the values for this struct as an Array.
48
48
  #
@@ -53,7 +53,7 @@ module Concurrent
53
53
  end
54
54
  alias_method :to_a, :values
55
55
 
56
- # @!macro [attach] struct_values_at
56
+ # @!macro struct_values_at
57
57
  #
58
58
  # Returns the struct member values for each selector as an Array.
59
59
  #
@@ -64,7 +64,7 @@ module Concurrent
64
64
  synchronize { ns_values_at(indexes) }
65
65
  end
66
66
 
67
- # @!macro [attach] struct_inspect
67
+ # @!macro struct_inspect
68
68
  #
69
69
  # Describe the contents of this struct in a string.
70
70
  #
@@ -74,7 +74,7 @@ module Concurrent
74
74
  end
75
75
  alias_method :to_s, :inspect
76
76
 
77
- # @!macro [attach] struct_merge
77
+ # @!macro 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
@@ -95,7 +95,7 @@ module Concurrent
95
95
  synchronize { ns_merge(other, &block) }
96
96
  end
97
97
 
98
- # @!macro [attach] struct_to_h
98
+ # @!macro struct_to_h
99
99
  #
100
100
  # Returns a hash containing the names and values for the struct’s members.
101
101
  #
@@ -104,11 +104,11 @@ module Concurrent
104
104
  synchronize { ns_to_h }
105
105
  end
106
106
 
107
- # @!macro [attach] struct_get
107
+ # @!macro struct_get
108
108
  #
109
109
  # Attribute Reference
110
110
  #
111
- # @param [Symbol, String, Integer] member the string or symbol name of the memeber
111
+ # @param [Symbol, String, Integer] member the string or symbol name of the member
112
112
  # for which to obtain the value or the member's index
113
113
  #
114
114
  # @return [Object] the value of the given struct member or the member at the given index.
@@ -119,7 +119,7 @@ module Concurrent
119
119
  synchronize { ns_get(member) }
120
120
  end
121
121
 
122
- # @!macro [attach] struct_equality
122
+ # @!macro struct_equality
123
123
  #
124
124
  # Equality
125
125
  #
@@ -129,7 +129,7 @@ module Concurrent
129
129
  synchronize { ns_equality(other) }
130
130
  end
131
131
 
132
- # @!macro [attach] struct_each
132
+ # @!macro struct_each
133
133
  #
134
134
  # Yields the value of each struct member in order. If no block is given
135
135
  # an enumerator is returned.
@@ -141,7 +141,7 @@ module Concurrent
141
141
  synchronize { ns_each(&block) }
142
142
  end
143
143
 
144
- # @!macro [attach] struct_each_pair
144
+ # @!macro struct_each_pair
145
145
  #
146
146
  # Yields the name and value of each struct member in order. If no block is
147
147
  # given an enumerator is returned.
@@ -154,7 +154,7 @@ module Concurrent
154
154
  synchronize { ns_each_pair(&block) }
155
155
  end
156
156
 
157
- # @!macro [attach] struct_select
157
+ # @!macro struct_select
158
158
  #
159
159
  # Yields each member value from the struct to the block and returns an Array
160
160
  # containing the member values from the struct for which the given block
@@ -169,13 +169,13 @@ module Concurrent
169
169
  synchronize { ns_select(&block) }
170
170
  end
171
171
 
172
- # @!macro [new] struct_set
172
+ # @!macro struct_set
173
173
  #
174
174
  # Attribute Assignment
175
175
  #
176
176
  # Sets the value of the given struct member or the member at the given index.
177
177
  #
178
- # @param [Symbol, String, Integer] member the string or symbol name of the memeber
178
+ # @param [Symbol, String, Integer] member the string or symbol name of the member
179
179
  # for which to obtain the value or the member's index
180
180
  #
181
181
  # @return [Object] the value of the given struct member or the member at the given index.
@@ -212,6 +212,7 @@ module Concurrent
212
212
  synchronize do
213
213
  clazz = Synchronization::AbstractStruct.define_struct_class(MutableStruct, Synchronization::LockableObject, name, members, &block)
214
214
  members.each_with_index do |member, index|
215
+ clazz.send :remove_method, member
215
216
  clazz.send(:define_method, member) do
216
217
  synchronize { @values[index] }
217
218
  end