Skip to content

Commit 204cf7b

Browse files
committed
Better ReadWriteLock exception handling; added pending specs.
1 parent 9237042 commit 204cf7b

File tree

2 files changed

+75
-10
lines changed

2 files changed

+75
-10
lines changed

lib/concurrent/atomic/read_write_lock.rb

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ module Concurrent
1414
# Any additional readers that come when the writer is already waiting, will also
1515
# wait (so writers are not starved).
1616
#
17+
# This implementation is based on `java.util.concurrent.ReentrantReadWriteLock`.
18+
#
1719
# @example
1820
# lock = Concurrent::ReadWriteLock.new
1921
# lock.with_read_lock { data.retrieve }
@@ -22,6 +24,8 @@ module Concurrent
2224
# @note Do **not** try to acquire the write lock while already holding a read lock
2325
# **or** try to acquire the write lock while you already have it.
2426
# This will lead to deadlock
27+
#
28+
# @see http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/locks/ReentrantReadWriteLock.html java.util.concurrent.ReentrantReadWriteLock
2529
class ReadWriteLock
2630

2731
# @!visibility private
@@ -69,8 +73,12 @@ def with_read_lock
6973
raise ArgumentError.new('no block given') unless block_given?
7074
acquire_read_lock
7175
yield
72-
ensure => ex
73-
release_read_lock unless ex.is_a? Concurrent::ResourceLimitError
76+
rescue => ex
77+
raise ex
78+
ensure
79+
if block_given? && ! ex.is_a?(Concurrent::ResourceLimitError)
80+
release_read_lock
81+
end
7482
end
7583

7684
# Execute a block operation within a write lock.
@@ -86,8 +94,12 @@ def with_write_lock
8694
raise ArgumentError.new('no block given') unless block_given?
8795
acquire_write_lock
8896
yield
89-
ensure => ex
90-
release_write_lock unless ex.is_a? Concurrent::ResourceLimitError
97+
rescue => ex
98+
raise ex
99+
ensure
100+
if block_given? && ! ex.is_a?(Concurrent::ResourceLimitError)
101+
release_write_lock
102+
end
91103
end
92104

93105
# Acquire a read lock.

spec/concurrent/atomic/read_write_lock_spec.rb

Lines changed: 59 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,27 +3,80 @@ module Concurrent
33
describe ReadWriteLock do
44

55
context '#with_read_lock' do
6-
pending
6+
7+
it 'acquires the lock'
8+
9+
it 'returns the value of the block operation'
10+
11+
it 'releases the lock'
12+
13+
it 'raises an exception if no block is given'
14+
15+
it 'raises an exception if maximum lock limit is exceeded'
16+
17+
it 'does not release the lock when an exception is raised'
718
end
819

920
context '#with_write_lock' do
10-
pending
21+
22+
it 'acquires the lock'
23+
24+
it 'returns the value of the block operation'
25+
26+
it 'releases the lock'
27+
28+
it 'raises an exception if no block is given'
29+
30+
it 'raises an exception if maximum lock limit is exceeded'
31+
32+
it 'does not release the lock when an exception is raised'
1133
end
1234

1335
context '#acquire_read_lock' do
14-
pending
36+
37+
it 'increments the lock count'
38+
39+
it 'waits for a running writer to finish'
40+
41+
it 'does not wait for any running readers'
42+
43+
it 'raises an exception if maximum lock limit is exceeded'
1544
end
1645

1746
context '#release_read_lock' do
18-
pending
47+
48+
it 'decrements the counter'
49+
50+
it 'unblocks running writers'
1951
end
2052

2153
context '#acquire_write_lock' do
22-
pending
54+
55+
it 'increments the lock count'
56+
57+
it 'waits for a running writer to finish'
58+
59+
it 'waits for a running reader to finish'
60+
61+
it 'raises an exception if maximum lock limit is exceeded'
2362
end
2463

2564
context '#release_write_lock' do
26-
pending
65+
66+
it 'decrements the counter'
67+
68+
it 'unblocks running readers'
69+
70+
it 'unblocks running writers'
71+
end
72+
73+
context '#to_s' do
74+
75+
it 'includes the running reader count'
76+
77+
it 'includes the running writer count'
78+
79+
it 'includes the waiting writer count'
2780
end
2881
end
2982
end

0 commit comments

Comments
 (0)