Skip to content

Commit fc690d0

Browse files
committed
MVar: include Dereferenceable.
1 parent a21697b commit fc690d0

File tree

4 files changed

+52
-16
lines changed

4 files changed

+52
-16
lines changed

lib/concurrent/dereferenceable.rb

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -32,19 +32,23 @@ def set_deref_options(opts = {})
3232
# by the #set_deref_options method.
3333
def value
3434
mutex.synchronize do
35-
return nil if @value.nil?
36-
return @value if @do_nothing_on_deref
37-
value = @value
38-
value = @copy_on_deref.call(value) if @copy_on_deref
39-
value = value.dup if @dup_on_deref
40-
value = value.freeze if @freeze_on_deref
41-
value
35+
apply_deref_options(@value)
4236
end
4337
end
4438
alias_method :deref, :value
4539

4640
protected
4741

42+
def apply_deref_options(value)
43+
return nil if value.nil?
44+
return value if @do_nothing_on_deref
45+
value = value
46+
value = @copy_on_deref.call(value) if @copy_on_deref
47+
value = value.dup if @dup_on_deref
48+
value = value.freeze if @freeze_on_deref
49+
value
50+
end
51+
4852
def mutex # :nodoc:
4953
@mutex
5054
end

lib/concurrent/mvar.rb

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,17 @@ module Concurrent
44

55
class MVar
66

7+
include Dereferenceable
8+
79
EMPTY = Object.new
810
TIMEOUT = Object.new
911

10-
def initialize(value=EMPTY)
12+
def initialize(value = EMPTY, opts = {})
1113
@value = value
1214
@mutex = Mutex.new
1315
@empty_condition = ConditionVariable.new
1416
@full_condition = ConditionVariable.new
17+
set_deref_options(opts)
1518
end
1619

1720
def take(timeout = nil)
@@ -24,7 +27,7 @@ def take(timeout = nil)
2427
value = @value
2528
@value = EMPTY
2629
@empty_condition.signal
27-
value
30+
apply_deref_options(value)
2831
else
2932
TIMEOUT
3033
end
@@ -40,7 +43,7 @@ def put(value, timeout = nil)
4043
if empty?
4144
@value = value
4245
@full_condition.signal
43-
value
46+
apply_deref_options(value)
4447
else
4548
TIMEOUT
4649
end
@@ -59,7 +62,7 @@ def modify(timeout = nil)
5962
value = @value
6063
@value = yield value
6164
@full_condition.signal
62-
value
65+
apply_deref_options(value)
6366
else
6467
TIMEOUT
6568
end
@@ -72,7 +75,7 @@ def try_take!
7275
value = @value
7376
@value = EMPTY
7477
@empty_condition.signal
75-
value
78+
apply_deref_options(value)
7679
else
7780
EMPTY
7881
end
@@ -93,8 +96,10 @@ def try_put!(value)
9396

9497
def set!(value)
9598
@mutex.synchronize do
99+
old_value = @value
96100
@value = value
97101
@full_condition.signal
102+
apply_deref_options(old_value)
98103
end
99104
end
100105

@@ -109,7 +114,7 @@ def modify!(timeout = nil)
109114
else
110115
@full_condition.signal
111116
end
112-
value
117+
apply_deref_options(value)
113118
end
114119
end
115120

md/mvar.md

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,17 @@ On top of the fundamental `#put` and `#take` operations, we also provide a
1010
operations all support timeouts.
1111

1212
We also support non-blocking operations `#try_put!` and `#try_take!`, a `#set!`
13-
that ignores existing values, and a `#modify!` that yields `MVar::EMPTY` if the
13+
that ignores existing values, a `#value` that returns the value without removing
14+
it or returns `MVar::EMPTY`, and a `#modify!` that yields `MVar::EMPTY` if the
1415
`MVar` is empty and can be used to set `MVar::EMPTY`. You shouldn't use these
1516
operations in the first instance.
1617

17-
`MVar is related to M-structures in Id, MVar in Haskell and SyncVar in Scala.
18-
`See
18+
`MVar` is a Dereferenceable.
19+
20+
`MVar` is related to M-structures in Id, `MVar` in Haskell and `SyncVar` in
21+
Scala.
22+
23+
See:
1924

2025
1. P. Barth, R. Nikhil, and Arvind. M-Structures: Extending a parallel, non-
2126
strict, functional language with state. In Proceedings of the 5th ACM Conference

spec/concurrent/mvar_spec.rb

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,18 @@ module Concurrent
44

55
describe MVar do
66

7+
context 'behavior' do
8+
9+
# dereferenceable
10+
11+
def dereferenceable_subject(value, opts = {})
12+
MVar.new(value, opts)
13+
end
14+
15+
it_should_behave_like :dereferenceable
16+
17+
end
18+
719
context '#initialize' do
820

921
it 'accepts no initial value' do
@@ -233,6 +245,16 @@ module Concurrent
233245
m.take.should eq 14
234246
end
235247

248+
it 'returns EMPTY on an empty MVar' do
249+
m = MVar.new
250+
m.set!(2).should eq MVar::EMPTY
251+
end
252+
253+
it 'returns the original value on a full MVar' do
254+
m = MVar.new(14)
255+
m.set!(2).should eq 14
256+
end
257+
236258
end
237259

238260
context '#modify!' do

0 commit comments

Comments
 (0)