Skip to content

Commit 74db134

Browse files
committed
CLJ-2924 - LazySeq - fix visibility issues with non-volatile reads
1 parent 6a4ba6a commit 74db134

1 file changed

Lines changed: 17 additions & 30 deletions

File tree

src/jvm/clojure/lang/LazySeq.java

Lines changed: 17 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ public final class LazySeq extends Obj implements ISeq, Sequential, List, IPendi
2525
private transient IFn fn;
2626
private Object sv;
2727
private ISeq s;
28-
private Lock lock;
28+
private volatile Lock lock;
2929

3030
public LazySeq(IFn f){
3131
fn = f;
@@ -52,24 +52,22 @@ final private void force() {
5252
}
5353
}
5454

55-
final private void lockAndForce() {
56-
Lock l = lock;
57-
if(l != null) {
58-
l.lock();
59-
try {
60-
force();
61-
} finally {
62-
l.unlock();
63-
}
64-
}
65-
}
66-
6755
final private Object sval() {
68-
if(fn != null)
69-
lockAndForce();
70-
if(sv != null)
71-
return sv;
72-
return s;
56+
Lock l = lock;
57+
if(l != null) {
58+
l.lock();
59+
try {
60+
//must re-examine under lock
61+
if(lock != null) { //unrealized
62+
force();
63+
return sv;
64+
}
65+
} finally {
66+
l.unlock();
67+
}
68+
}
69+
// realized, read of lock above guarantees visibility of s
70+
return s;
7371
}
7472

7573
final private Object unwrap(Object ls){
@@ -287,18 +285,7 @@ public boolean addAll(int index, Collection c){
287285
}
288286

289287
public boolean isRealized(){
290-
if(lock != null) {
291-
Lock l = lock;
292-
if(l != null) {
293-
l.lock();
294-
try {
295-
return lock == null;
296-
} finally {
297-
l.unlock();
298-
}
299-
}
300-
}
301-
return true;
288+
return lock == null;
302289
}
303290

304291
// custom Serializable implementation - ensure seq is fully-realized before writing

0 commit comments

Comments
 (0)