concurrent-ruby 0.8.0.pre2-java → 0.9.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 (145) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +114 -3
  3. data/README.md +111 -55
  4. data/lib/concurrent.rb +90 -14
  5. data/lib/concurrent/async.rb +143 -51
  6. data/lib/concurrent/atom.rb +131 -0
  7. data/lib/concurrent/atomic/atomic_boolean.rb +57 -107
  8. data/lib/concurrent/atomic/atomic_fixnum.rb +73 -101
  9. data/lib/concurrent/atomic/atomic_reference.rb +49 -0
  10. data/lib/concurrent/atomic/condition.rb +23 -12
  11. data/lib/concurrent/atomic/count_down_latch.rb +23 -21
  12. data/lib/concurrent/atomic/cyclic_barrier.rb +47 -47
  13. data/lib/concurrent/atomic/event.rb +33 -42
  14. data/lib/concurrent/atomic/read_write_lock.rb +252 -0
  15. data/lib/concurrent/atomic/semaphore.rb +64 -89
  16. data/lib/concurrent/atomic/thread_local_var.rb +130 -58
  17. data/lib/concurrent/atomic/thread_local_var/weak_key_map.rb +236 -0
  18. data/lib/concurrent/atomic_reference/direct_update.rb +34 -3
  19. data/lib/concurrent/atomic_reference/jruby.rb +6 -3
  20. data/lib/concurrent/atomic_reference/mutex_atomic.rb +17 -39
  21. data/lib/concurrent/atomic_reference/numeric_cas_wrapper.rb +3 -0
  22. data/lib/concurrent/atomic_reference/rbx.rb +4 -1
  23. data/lib/concurrent/atomic_reference/ruby.rb +6 -3
  24. data/lib/concurrent/atomics.rb +74 -4
  25. data/lib/concurrent/collection/copy_on_notify_observer_set.rb +115 -0
  26. data/lib/concurrent/collection/copy_on_write_observer_set.rb +119 -0
  27. data/lib/concurrent/collection/priority_queue.rb +300 -245
  28. data/lib/concurrent/concern/deprecation.rb +34 -0
  29. data/lib/concurrent/concern/dereferenceable.rb +88 -0
  30. data/lib/concurrent/concern/logging.rb +27 -0
  31. data/lib/concurrent/concern/obligation.rb +228 -0
  32. data/lib/concurrent/concern/observable.rb +85 -0
  33. data/lib/concurrent/configuration.rb +234 -109
  34. data/lib/concurrent/dataflow.rb +2 -3
  35. data/lib/concurrent/delay.rb +141 -50
  36. data/lib/concurrent/edge.rb +30 -0
  37. data/lib/concurrent/errors.rb +19 -7
  38. data/lib/concurrent/exchanger.rb +25 -1
  39. data/lib/concurrent/executor/cached_thread_pool.rb +51 -33
  40. data/lib/concurrent/executor/executor.rb +46 -299
  41. data/lib/concurrent/executor/executor_service.rb +521 -0
  42. data/lib/concurrent/executor/fixed_thread_pool.rb +196 -23
  43. data/lib/concurrent/executor/immediate_executor.rb +9 -9
  44. data/lib/concurrent/executor/indirect_immediate_executor.rb +4 -3
  45. data/lib/concurrent/executor/java_single_thread_executor.rb +17 -16
  46. data/lib/concurrent/executor/java_thread_pool_executor.rb +55 -102
  47. data/lib/concurrent/executor/ruby_single_thread_executor.rb +14 -16
  48. data/lib/concurrent/executor/ruby_thread_pool_executor.rb +250 -166
  49. data/lib/concurrent/executor/safe_task_executor.rb +5 -4
  50. data/lib/concurrent/executor/serialized_execution.rb +22 -18
  51. data/lib/concurrent/executor/{per_thread_executor.rb → simple_executor_service.rb} +29 -20
  52. data/lib/concurrent/executor/single_thread_executor.rb +32 -21
  53. data/lib/concurrent/executor/thread_pool_executor.rb +73 -60
  54. data/lib/concurrent/executor/timer_set.rb +96 -84
  55. data/lib/concurrent/executors.rb +1 -1
  56. data/lib/concurrent/future.rb +71 -38
  57. data/lib/concurrent/immutable_struct.rb +89 -0
  58. data/lib/concurrent/ivar.rb +152 -60
  59. data/lib/concurrent/lazy_register.rb +40 -20
  60. data/lib/concurrent/maybe.rb +226 -0
  61. data/lib/concurrent/mutable_struct.rb +227 -0
  62. data/lib/concurrent/mvar.rb +44 -43
  63. data/lib/concurrent/promise.rb +229 -136
  64. data/lib/concurrent/scheduled_task.rb +341 -43
  65. data/lib/concurrent/settable_struct.rb +127 -0
  66. data/lib/concurrent/synchronization.rb +17 -0
  67. data/lib/concurrent/synchronization/abstract_object.rb +163 -0
  68. data/lib/concurrent/synchronization/abstract_struct.rb +158 -0
  69. data/lib/concurrent/synchronization/condition.rb +53 -0
  70. data/lib/concurrent/synchronization/java_object.rb +34 -0
  71. data/lib/concurrent/synchronization/lock.rb +32 -0
  72. data/lib/concurrent/synchronization/monitor_object.rb +26 -0
  73. data/lib/concurrent/synchronization/mutex_object.rb +43 -0
  74. data/lib/concurrent/synchronization/object.rb +78 -0
  75. data/lib/concurrent/synchronization/rbx_object.rb +75 -0
  76. data/lib/concurrent/timer_task.rb +92 -103
  77. data/lib/concurrent/tvar.rb +42 -38
  78. data/lib/concurrent/utilities.rb +3 -1
  79. data/lib/concurrent/utility/at_exit.rb +97 -0
  80. data/lib/concurrent/utility/engine.rb +44 -0
  81. data/lib/concurrent/utility/monotonic_time.rb +59 -0
  82. data/lib/concurrent/utility/native_extension_loader.rb +56 -0
  83. data/lib/concurrent/utility/processor_counter.rb +156 -0
  84. data/lib/concurrent/utility/timeout.rb +18 -14
  85. data/lib/concurrent/utility/timer.rb +11 -6
  86. data/lib/concurrent/version.rb +2 -1
  87. data/lib/concurrent_ruby.rb +1 -0
  88. data/lib/concurrent_ruby_ext.jar +0 -0
  89. metadata +46 -66
  90. data/lib/concurrent/actor.rb +0 -103
  91. data/lib/concurrent/actor/behaviour.rb +0 -70
  92. data/lib/concurrent/actor/behaviour/abstract.rb +0 -48
  93. data/lib/concurrent/actor/behaviour/awaits.rb +0 -21
  94. data/lib/concurrent/actor/behaviour/buffer.rb +0 -54
  95. data/lib/concurrent/actor/behaviour/errors_on_unknown_message.rb +0 -12
  96. data/lib/concurrent/actor/behaviour/executes_context.rb +0 -18
  97. data/lib/concurrent/actor/behaviour/linking.rb +0 -45
  98. data/lib/concurrent/actor/behaviour/pausing.rb +0 -77
  99. data/lib/concurrent/actor/behaviour/removes_child.rb +0 -16
  100. data/lib/concurrent/actor/behaviour/sets_results.rb +0 -36
  101. data/lib/concurrent/actor/behaviour/supervised.rb +0 -59
  102. data/lib/concurrent/actor/behaviour/supervising.rb +0 -34
  103. data/lib/concurrent/actor/behaviour/terminates_children.rb +0 -13
  104. data/lib/concurrent/actor/behaviour/termination.rb +0 -54
  105. data/lib/concurrent/actor/context.rb +0 -154
  106. data/lib/concurrent/actor/core.rb +0 -217
  107. data/lib/concurrent/actor/default_dead_letter_handler.rb +0 -9
  108. data/lib/concurrent/actor/envelope.rb +0 -41
  109. data/lib/concurrent/actor/errors.rb +0 -27
  110. data/lib/concurrent/actor/internal_delegations.rb +0 -49
  111. data/lib/concurrent/actor/public_delegations.rb +0 -40
  112. data/lib/concurrent/actor/reference.rb +0 -81
  113. data/lib/concurrent/actor/root.rb +0 -37
  114. data/lib/concurrent/actor/type_check.rb +0 -48
  115. data/lib/concurrent/actor/utils.rb +0 -10
  116. data/lib/concurrent/actor/utils/ad_hoc.rb +0 -21
  117. data/lib/concurrent/actor/utils/balancer.rb +0 -42
  118. data/lib/concurrent/actor/utils/broadcast.rb +0 -52
  119. data/lib/concurrent/actor/utils/pool.rb +0 -59
  120. data/lib/concurrent/actress.rb +0 -3
  121. data/lib/concurrent/agent.rb +0 -209
  122. data/lib/concurrent/atomic.rb +0 -92
  123. data/lib/concurrent/atomic/copy_on_notify_observer_set.rb +0 -118
  124. data/lib/concurrent/atomic/copy_on_write_observer_set.rb +0 -117
  125. data/lib/concurrent/atomic/synchronization.rb +0 -51
  126. data/lib/concurrent/channel/buffered_channel.rb +0 -85
  127. data/lib/concurrent/channel/channel.rb +0 -41
  128. data/lib/concurrent/channel/unbuffered_channel.rb +0 -35
  129. data/lib/concurrent/channel/waitable_list.rb +0 -40
  130. data/lib/concurrent/channels.rb +0 -5
  131. data/lib/concurrent/collection/blocking_ring_buffer.rb +0 -71
  132. data/lib/concurrent/collection/ring_buffer.rb +0 -59
  133. data/lib/concurrent/collections.rb +0 -3
  134. data/lib/concurrent/dereferenceable.rb +0 -108
  135. data/lib/concurrent/executor/java_cached_thread_pool.rb +0 -32
  136. data/lib/concurrent/executor/java_fixed_thread_pool.rb +0 -31
  137. data/lib/concurrent/executor/ruby_cached_thread_pool.rb +0 -29
  138. data/lib/concurrent/executor/ruby_fixed_thread_pool.rb +0 -32
  139. data/lib/concurrent/executor/ruby_thread_pool_worker.rb +0 -73
  140. data/lib/concurrent/logging.rb +0 -20
  141. data/lib/concurrent/obligation.rb +0 -171
  142. data/lib/concurrent/observable.rb +0 -73
  143. data/lib/concurrent/options_parser.rb +0 -48
  144. data/lib/concurrent/utility/processor_count.rb +0 -152
  145. data/lib/extension_helper.rb +0 -37
@@ -1,51 +0,0 @@
1
- module Concurrent
2
-
3
- # Safe synchronization under JRuby, prevents reading uninitialized @mutex variable.
4
- # @note synchronized needs to be called in #initialize for this module to work properly
5
- # @example usage
6
- # class AClass
7
- # include Synchronized
8
- #
9
- # def initialize
10
- # synchronize do
11
- # # body of the constructor ...
12
- # end
13
- # end
14
- #
15
- # def a_method
16
- # synchronize do
17
- # # body of a_method ...
18
- # end
19
- # end
20
- # end
21
- module Synchronization
22
-
23
- engine = defined?(RUBY_ENGINE) && RUBY_ENGINE
24
-
25
- case engine
26
- when 'jruby'
27
- require 'jruby'
28
-
29
- def synchronize
30
- JRuby.reference0(self).synchronized { yield }
31
- end
32
-
33
- when 'rbx'
34
-
35
- def synchronize
36
- Rubinius.lock(self)
37
- yield
38
- ensure
39
- Rubinius.unlock(self)
40
- end
41
-
42
- else
43
-
44
- def synchronize
45
- @mutex ||= Mutex.new
46
- @mutex.synchronize { yield }
47
- end
48
-
49
- end
50
- end
51
- end
@@ -1,85 +0,0 @@
1
- require 'concurrent/atomic/condition'
2
-
3
- require_relative 'waitable_list'
4
-
5
- module Concurrent
6
- class BufferedChannel
7
-
8
- def initialize(size)
9
- @mutex = Mutex.new
10
- @condition = Condition.new
11
- @buffer_condition = Condition.new
12
-
13
- @probe_set = WaitableList.new
14
- @buffer = RingBuffer.new(size)
15
- end
16
-
17
- def probe_set_size
18
- @probe_set.size
19
- end
20
-
21
- def buffer_queue_size
22
- @mutex.synchronize { @buffer.count }
23
- end
24
-
25
- def push(value)
26
- until set_probe_or_push_into_buffer(value)
27
- end
28
- end
29
-
30
- def pop
31
- probe = Channel::Probe.new
32
- select(probe)
33
- probe.value
34
- end
35
-
36
- def select(probe)
37
- @mutex.synchronize do
38
-
39
- if @buffer.empty?
40
- @probe_set.put(probe)
41
- true
42
- else
43
- shift_buffer if probe.set_unless_assigned(peek_buffer, self)
44
- end
45
-
46
- end
47
- end
48
-
49
- def remove_probe(probe)
50
- @probe_set.delete(probe)
51
- end
52
-
53
- private
54
-
55
- def push_into_buffer(value)
56
- @buffer_condition.wait(@mutex) while @buffer.full?
57
- @buffer.offer value
58
- @buffer_condition.broadcast
59
- end
60
-
61
- def peek_buffer
62
- @buffer_condition.wait(@mutex) while @buffer.empty?
63
- @buffer.peek
64
- end
65
-
66
- def shift_buffer
67
- @buffer_condition.wait(@mutex) while @buffer.empty?
68
- result = @buffer.poll
69
- @buffer_condition.broadcast
70
- result
71
- end
72
-
73
- def set_probe_or_push_into_buffer(value)
74
- @mutex.synchronize do
75
- if @probe_set.empty?
76
- push_into_buffer(value)
77
- true
78
- else
79
- @probe_set.take.set_unless_assigned(value, self)
80
- end
81
- end
82
- end
83
-
84
- end
85
- end
@@ -1,41 +0,0 @@
1
- require 'concurrent/ivar'
2
-
3
- module Concurrent
4
- module Channel
5
-
6
- class Probe < Concurrent::IVar
7
-
8
- def initialize(value = NO_VALUE, opts = {})
9
- super(value, opts)
10
- end
11
-
12
- def set_unless_assigned(value, channel)
13
- mutex.synchronize do
14
- return false if [:fulfilled, :rejected].include? @state
15
-
16
- set_state(true, [value, channel], nil)
17
- event.set
18
- true
19
- end
20
- end
21
-
22
- alias_method :composite_value, :value
23
-
24
- def value
25
- composite_value.nil? ? nil : composite_value[0]
26
- end
27
-
28
- def channel
29
- composite_value.nil? ? nil : composite_value[1]
30
- end
31
- end
32
-
33
- def self.select(*channels)
34
- probe = Probe.new
35
- channels.each { |channel| channel.select(probe) }
36
- result = probe.composite_value
37
- channels.each { |channel| channel.remove_probe(probe) }
38
- result
39
- end
40
- end
41
- end
@@ -1,35 +0,0 @@
1
- require_relative 'waitable_list'
2
-
3
- module Concurrent
4
- class UnbufferedChannel
5
-
6
- def initialize
7
- @probe_set = WaitableList.new
8
- end
9
-
10
- def probe_set_size
11
- @probe_set.size
12
- end
13
-
14
- def push(value)
15
- # TODO set_unless_assigned define on IVar as #set_state? or #try_set_state
16
- until @probe_set.take.set_unless_assigned(value, self)
17
- end
18
- end
19
-
20
- def pop
21
- probe = Channel::Probe.new
22
- select(probe)
23
- probe.value
24
- end
25
-
26
- def select(probe)
27
- @probe_set.put(probe)
28
- end
29
-
30
- def remove_probe(probe)
31
- @probe_set.delete(probe)
32
- end
33
-
34
- end
35
- end
@@ -1,40 +0,0 @@
1
- require 'concurrent/atomic/condition'
2
-
3
- module Concurrent
4
- class WaitableList
5
-
6
- def initialize
7
- @mutex = Mutex.new
8
- @condition = Condition.new
9
-
10
- @list = []
11
- end
12
-
13
- def size
14
- @mutex.synchronize { @list.size }
15
- end
16
-
17
- def empty?
18
- @mutex.synchronize { @list.empty? }
19
- end
20
-
21
- def put(value)
22
- @mutex.synchronize do
23
- @list << value
24
- @condition.signal
25
- end
26
- end
27
-
28
- def delete(value)
29
- @mutex.synchronize { @list.delete(value) }
30
- end
31
-
32
- def take
33
- @mutex.synchronize do
34
- @condition.wait(@mutex) while @list.empty?
35
- @list.shift
36
- end
37
- end
38
-
39
- end
40
- end
@@ -1,5 +0,0 @@
1
- require 'concurrent/collections'
2
-
3
- require 'concurrent/channel/channel'
4
- require 'concurrent/channel/unbuffered_channel'
5
- require 'concurrent/channel/buffered_channel'
@@ -1,71 +0,0 @@
1
- require 'concurrent/atomic/condition'
2
-
3
- module Concurrent
4
- class BlockingRingBuffer
5
-
6
- def initialize(capacity)
7
- @buffer = RingBuffer.new(capacity)
8
- @first = @last = 0
9
- @count = 0
10
- @mutex = Mutex.new
11
- @condition = Condition.new
12
- end
13
-
14
- # @return [Integer] the capacity of the buffer
15
- def capacity
16
- @mutex.synchronize { @buffer.capacity }
17
- end
18
-
19
- # @return [Integer] the number of elements currently in the buffer
20
- def count
21
- @mutex.synchronize { @buffer.count }
22
- end
23
-
24
- # @return [Boolean] true if buffer is empty, false otherwise
25
- def empty?
26
- @mutex.synchronize { @buffer.empty? }
27
- end
28
-
29
- # @return [Boolean] true if buffer is full, false otherwise
30
- def full?
31
- @mutex.synchronize { @buffer.full? }
32
- end
33
-
34
- # @param [Object] value the value to be inserted
35
- # @return [Boolean] true if value has been inserted, false otherwise
36
- def put(value)
37
- @mutex.synchronize do
38
- wait_while_full
39
- @buffer.offer(value)
40
- @condition.signal
41
- true
42
- end
43
- end
44
-
45
- # @return [Object] the first available value and removes it from the buffer. If buffer is empty it blocks until an element is available
46
- def take
47
- @mutex.synchronize do
48
- wait_while_empty
49
- result = @buffer.poll
50
- @condition.signal
51
- result
52
- end
53
- end
54
-
55
- # @return [Object] the first available value and without removing it from the buffer. If buffer is empty returns nil
56
- def peek
57
- @mutex.synchronize { @buffer.peek }
58
- end
59
-
60
- private
61
-
62
- def wait_while_full
63
- @condition.wait(@mutex) while @buffer.full?
64
- end
65
-
66
- def wait_while_empty
67
- @condition.wait(@mutex) while @buffer.empty?
68
- end
69
-
70
- end
71
- end
@@ -1,59 +0,0 @@
1
- module Concurrent
2
-
3
- # non-thread safe buffer
4
- class RingBuffer
5
-
6
- def initialize(capacity)
7
- @buffer = Array.new(capacity)
8
- @first = @last = 0
9
- @count = 0
10
- end
11
-
12
-
13
- # @return [Integer] the capacity of the buffer
14
- def capacity
15
- @buffer.size
16
- end
17
-
18
- # @return [Integer] the number of elements currently in the buffer
19
- def count
20
- @count
21
- end
22
-
23
- # @return [Boolean] true if buffer is empty, false otherwise
24
- def empty?
25
- @count == 0
26
- end
27
-
28
- # @return [Boolean] true if buffer is full, false otherwise
29
- def full?
30
- @count == capacity
31
- end
32
-
33
- # @param [Object] value
34
- # @return [Boolean] true if value has been inserted, false otherwise
35
- def offer(value)
36
- return false if full?
37
-
38
- @buffer[@last] = value
39
- @last = (@last + 1) % @buffer.size
40
- @count += 1
41
- true
42
- end
43
-
44
- # @return [Object] the first available value and removes it from the buffer. If buffer is empty returns nil
45
- def poll
46
- result = @buffer[@first]
47
- @buffer[@first] = nil
48
- @first = (@first + 1) % @buffer.size
49
- @count -= 1
50
- result
51
- end
52
-
53
- # @return [Object] the first available value and without removing it from the buffer. If buffer is empty returns nil
54
- def peek
55
- @buffer[@first]
56
- end
57
-
58
- end
59
- end
@@ -1,3 +0,0 @@
1
- require 'concurrent/collection/priority_queue'
2
- require 'concurrent/collection/ring_buffer'
3
- require 'concurrent/collection/blocking_ring_buffer'
@@ -1,108 +0,0 @@
1
- module Concurrent
2
-
3
- # Object references in Ruby are mutable. This can lead to serious problems when
4
- # the `#value` of a concurrent object is a mutable reference. Which is always the
5
- # case unless the value is a `Fixnum`, `Symbol`, or similar "primitive" data type.
6
- # Most classes in this library that expose a `#value` getter method do so using the
7
- # `Dereferenceable` mixin module.
8
- #
9
- # Objects with this mixin can be configured with a few options that can help protect
10
- # the program from potentially dangerous operations.
11
- #
12
- # * `:dup_on_deref` when true will call the `#dup` method on the `value` object every time the `#value` method is called (default: false)
13
- # * `:freeze_on_deref` when true will call the `#freeze` method on the `value` object every time the `#value` method is called (default: false)
14
- # * `:copy_on_deref` when given a `Proc` object the `Proc` will be run every time the `#value` method is called. The `Proc` will be given the current `value` as its only parameter and the result returned by the block will be the return value of the `#value` call. When `nil` this option will be ignored (default: nil)
15
- module Dereferenceable
16
-
17
- # Return the value this object represents after applying the options specified
18
- # by the `#set_deref_options` method.
19
- #
20
- # When multiple deref options are set the order of operations is strictly defined.
21
- # The order of deref operations is:
22
- # * `:copy_on_deref`
23
- # * `:dup_on_deref`
24
- # * `:freeze_on_deref`
25
- #
26
- # Because of this ordering there is no need to `#freeze` an object created by a
27
- # provided `:copy_on_deref` block. Simply set `:freeze_on_deref` to `true`.
28
- # Setting both `:dup_on_deref` to `true` and `:freeze_on_deref` to `true` is
29
- # as close to the behavior of a "pure" functional language (like Erlang, Clojure,
30
- # or Haskell) as we are likely to get in Ruby.
31
- #
32
- # This method is thread-safe and synchronized with the internal `#mutex`.
33
- #
34
- # @return [Object] the current value of the object
35
- def value
36
- mutex.lock
37
- apply_deref_options(@value)
38
- ensure
39
- mutex.unlock
40
- end
41
-
42
- alias_method :deref, :value
43
-
44
- protected
45
-
46
- # Set the internal value of this object
47
- #
48
- # @param [Object] val the new value
49
- def value=(val)
50
- mutex.lock
51
- @value = val
52
- ensure
53
- mutex.unlock
54
- end
55
-
56
- # A mutex lock used for synchronizing thread-safe operations. Methods defined
57
- # by `Dereferenceable` are synchronized using the `Mutex` returned from this
58
- # method. Operations performed by the including class that operate on the
59
- # `@value` instance variable should be locked with this `Mutex`.
60
- #
61
- # @return [Mutex] the synchronization object
62
- def mutex
63
- @mutex
64
- end
65
-
66
- # Initializes the internal `Mutex`.
67
- #
68
- # @note This method *must* be called from within the constructor of the including class.
69
- #
70
- # @see #mutex
71
- def init_mutex
72
- @mutex = Mutex.new
73
- end
74
-
75
- # Set the options which define the operations #value performs before
76
- # returning data to the caller (dereferencing).
77
- #
78
- # @note Most classes that include this module will call `#set_deref_options`
79
- # from within the constructor, thus allowing these options to be set at
80
- # object creation.
81
- #
82
- # @param [Hash] opts the options defining dereference behavior.
83
- # @option opts [String] :dup_on_deref (false) call `#dup` before returning the data
84
- # @option opts [String] :freeze_on_deref (false) call `#freeze` before returning the data
85
- # @option opts [String] :copy_on_deref (nil) call the given `Proc` passing the internal value and
86
- # returning the value returned from the proc
87
- def set_deref_options(opts = {})
88
- mutex.lock
89
- @dup_on_deref = opts[:dup_on_deref] || opts[:dup]
90
- @freeze_on_deref = opts[:freeze_on_deref] || opts[:freeze]
91
- @copy_on_deref = opts[:copy_on_deref] || opts[:copy]
92
- @do_nothing_on_deref = !(@dup_on_deref || @freeze_on_deref || @copy_on_deref)
93
- nil
94
- ensure
95
- mutex.unlock
96
- end
97
-
98
- # @!visibility private
99
- def apply_deref_options(value) # :nodoc:
100
- return nil if value.nil?
101
- return value if @do_nothing_on_deref
102
- value = @copy_on_deref.call(value) if @copy_on_deref
103
- value = value.dup if @dup_on_deref
104
- value = value.freeze if @freeze_on_deref
105
- value
106
- end
107
- end
108
- end