Skip to content

Commit 2a02fe2

Browse files
committed
AtomicMarkableReference: Add try_update_no_exception
In order to avoid raising errors (which are costly to performance), add an API for attempting an update which simply returns nil to the caller.
1 parent aff034f commit 2a02fe2

File tree

2 files changed

+40
-0
lines changed

2 files changed

+40
-0
lines changed

lib/concurrent/atomic/atomic_markable_reference.rb

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,27 @@ def try_update
147147
ImmutableArray[new_val, new_mark]
148148
end
149149

150+
# @!macro [attach] atomic_markable_reference_method_try_update_no_exception
151+
#
152+
# Pass the current value to the given block, replacing it with the
153+
# block's result. Simply return nil if update fails.
154+
#
155+
# @yield [Object] Calculate a new value and marked state for the atomic
156+
# reference using given (old) value and (old) marked
157+
# @yieldparam [Object] old_val the starting value of the atomic reference
158+
# @yieldparam [Boolean] old_mark the starting state of marked
159+
#
160+
# @return [ImmutableArray] the new value and marked state, or nil if
161+
# the update failed
162+
def try_update_no_exception
163+
old_val, old_mark = @Reference.get
164+
new_val, new_mark = yield old_val, old_mark
165+
166+
return unless compare_and_set old_val, new_val, old_mark, new_mark
167+
168+
ImmutableArray[new_val, new_mark]
169+
end
170+
150171
# Internal/private ImmutableArray for representing pairs
151172
class ImmutableArray < Array
152173
def self.new(*args)

spec/concurrent/atomic/atomic_markable_reference_spec.rb

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,25 @@
4545
end
4646
end
4747

48+
describe '#try_update_no_exception' do
49+
it 'updates the value and mark' do
50+
val, mark = subject.try_update { |v, m| [v + 1, !m] }
51+
52+
expect(subject.value).to eq 1001
53+
expect(val).to eq 1001
54+
expect(mark).to eq false
55+
end
56+
57+
it 'returns nil when attempting to set inside of block' do
58+
expect do
59+
subject.try_update do |v, m|
60+
subject.set(1001, false)
61+
[v + 1, !m]
62+
end.to eq nil
63+
end
64+
end
65+
end
66+
4867
describe '#update' do
4968
it 'updates the value and mark' do
5069
val, mark = subject.update { |v, m| [v + 1, !m] }

0 commit comments

Comments
 (0)