Skip to content

Commit 42f68bc

Browse files
committed
Merge branch 'master' of github.com:clojure/clojure
2 parents ad7d9c4 + 46be47c commit 42f68bc

File tree

3 files changed

+49
-52
lines changed

3 files changed

+49
-52
lines changed

src/jvm/clojure/lang/PersistentArrayMap.java

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -374,10 +374,10 @@ public ITransientMap asTransient(){
374374
static final class TransientArrayMap extends ATransientMap {
375375
int len;
376376
final Object[] array;
377-
boolean owner;
377+
Thread owner;
378378

379379
public TransientArrayMap(Object[] array){
380-
this.owner = true;
380+
this.owner = Thread.currentThread();
381381
this.array = new Object[Math.max(HASHTABLE_THRESHOLD, array.length)];
382382
System.arraycopy(array, 0, this.array, 0, array.length);
383383
this.len = array.length;
@@ -436,16 +436,15 @@ int doCount() {
436436

437437
IPersistentMap doPersistent(){
438438
ensureEditable();
439-
owner = false;
439+
owner = null;
440440
Object[] a = new Object[len];
441441
System.arraycopy(array,0,a,0,len);
442442
return new PersistentArrayMap(a);
443443
}
444444

445445
void ensureEditable(){
446-
if(owner)
447-
return;
448-
throw new IllegalAccessError("Transient used after persistent! call");
446+
if(owner == null)
447+
throw new IllegalAccessError("Transient used after persistent! call");
449448
}
450449
}
451450
}

src/jvm/clojure/lang/PersistentHashMap.java

Lines changed: 34 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
import java.io.Serializable;
1414
import java.util.*;
1515
import java.util.concurrent.Callable;
16-
import java.util.concurrent.atomic.AtomicBoolean;
16+
import java.util.concurrent.atomic.AtomicReference;
1717

1818
/*
1919
A persistent rendition of Phil Bagwell's Hash Array Mapped Trie
@@ -238,7 +238,7 @@ public IPersistentMap meta(){
238238
}
239239

240240
static final class TransientHashMap extends ATransientMap {
241-
AtomicBoolean edit;
241+
AtomicReference<Thread> edit;
242242
INode root;
243243
int count;
244244
boolean hasNull;
@@ -247,10 +247,10 @@ static final class TransientHashMap extends ATransientMap {
247247

248248

249249
TransientHashMap(PersistentHashMap m) {
250-
this(new AtomicBoolean(true), m.root, m.count, m.hasNull, m.nullValue);
250+
this(new AtomicReference<Thread>(Thread.currentThread()), m.root, m.count, m.hasNull, m.nullValue);
251251
}
252252

253-
TransientHashMap(AtomicBoolean edit, INode root, int count, boolean hasNull, Object nullValue) {
253+
TransientHashMap(AtomicReference<Thread> edit, INode root, int count, boolean hasNull, Object nullValue) {
254254
this.edit = edit;
255255
this.root = root;
256256
this.count = count;
@@ -297,7 +297,7 @@ ITransientMap doWithout(Object key) {
297297
}
298298

299299
IPersistentMap doPersistent() {
300-
edit.set(false);
300+
edit.set(null);
301301
return new PersistentHashMap(count, root, hasNull, nullValue);
302302
}
303303

@@ -317,9 +317,8 @@ int doCount() {
317317
}
318318

319319
void ensureEditable(){
320-
if(edit.get())
321-
return;
322-
throw new IllegalAccessError("Transient used after persistent! call");
320+
if(edit.get() == null)
321+
throw new IllegalAccessError("Transient used after persistent! call");
323322
}
324323
}
325324

@@ -334,9 +333,9 @@ static interface INode extends Serializable {
334333

335334
ISeq nodeSeq();
336335

337-
INode assoc(AtomicBoolean edit, int shift, int hash, Object key, Object val, Box addedLeaf);
336+
INode assoc(AtomicReference<Thread> edit, int shift, int hash, Object key, Object val, Box addedLeaf);
338337

339-
INode without(AtomicBoolean edit, int shift, int hash, Object key, Box removedLeaf);
338+
INode without(AtomicReference<Thread> edit, int shift, int hash, Object key, Box removedLeaf);
340339

341340
public Object kvreduce(IFn f, Object init);
342341

@@ -346,9 +345,9 @@ static interface INode extends Serializable {
346345
final static class ArrayNode implements INode{
347346
int count;
348347
final INode[] array;
349-
final AtomicBoolean edit;
348+
final AtomicReference<Thread> edit;
350349

351-
ArrayNode(AtomicBoolean edit, int count, INode[] array){
350+
ArrayNode(AtomicReference<Thread> edit, int count, INode[] array){
352351
this.array = array;
353352
this.edit = edit;
354353
this.count = count;
@@ -459,20 +458,20 @@ public Object call() throws Exception{
459458
}
460459

461460

462-
private ArrayNode ensureEditable(AtomicBoolean edit){
461+
private ArrayNode ensureEditable(AtomicReference<Thread> edit){
463462
if(this.edit == edit)
464463
return this;
465464
return new ArrayNode(edit, count, this.array.clone());
466465
}
467466

468-
private ArrayNode editAndSet(AtomicBoolean edit, int i, INode n){
467+
private ArrayNode editAndSet(AtomicReference<Thread> edit, int i, INode n){
469468
ArrayNode editable = ensureEditable(edit);
470469
editable.array[i] = n;
471470
return editable;
472471
}
473472

474473

475-
private INode pack(AtomicBoolean edit, int idx) {
474+
private INode pack(AtomicReference<Thread> edit, int idx) {
476475
Object[] newArray = new Object[2*(count - 1)];
477476
int j = 1;
478477
int bitmap = 0;
@@ -491,7 +490,7 @@ private INode pack(AtomicBoolean edit, int idx) {
491490
return new BitmapIndexedNode(edit, bitmap, newArray);
492491
}
493492

494-
public INode assoc(AtomicBoolean edit, int shift, int hash, Object key, Object val, Box addedLeaf){
493+
public INode assoc(AtomicReference<Thread> edit, int shift, int hash, Object key, Object val, Box addedLeaf){
495494
int idx = mask(hash, shift);
496495
INode node = array[idx];
497496
if(node == null) {
@@ -505,7 +504,7 @@ public INode assoc(AtomicBoolean edit, int shift, int hash, Object key, Object v
505504
return editAndSet(edit, idx, n);
506505
}
507506

508-
public INode without(AtomicBoolean edit, int shift, int hash, Object key, Box removedLeaf){
507+
public INode without(AtomicReference<Thread> edit, int shift, int hash, Object key, Box removedLeaf){
509508
int idx = mask(hash, shift);
510509
INode node = array[idx];
511510
if(node == null)
@@ -571,13 +570,13 @@ final static class BitmapIndexedNode implements INode{
571570

572571
int bitmap;
573572
Object[] array;
574-
final AtomicBoolean edit;
573+
final AtomicReference<Thread> edit;
575574

576575
final int index(int bit){
577576
return Integer.bitCount(bitmap & (bit - 1));
578577
}
579578

580-
BitmapIndexedNode(AtomicBoolean edit, int bitmap, Object[] array){
579+
BitmapIndexedNode(AtomicReference<Thread> edit, int bitmap, Object[] array){
581580
this.bitmap = bitmap;
582581
this.array = array;
583582
this.edit = edit;
@@ -696,7 +695,7 @@ public Object fold(IFn combinef, IFn reducef, IFn fjtask, IFn fjfork, IFn fjjoin
696695
return NodeSeq.kvreduce(array, reducef, combinef.invoke());
697696
}
698697

699-
private BitmapIndexedNode ensureEditable(AtomicBoolean edit){
698+
private BitmapIndexedNode ensureEditable(AtomicReference<Thread> edit){
700699
if(this.edit == edit)
701700
return this;
702701
int n = Integer.bitCount(bitmap);
@@ -705,20 +704,20 @@ private BitmapIndexedNode ensureEditable(AtomicBoolean edit){
705704
return new BitmapIndexedNode(edit, bitmap, newArray);
706705
}
707706

708-
private BitmapIndexedNode editAndSet(AtomicBoolean edit, int i, Object a) {
707+
private BitmapIndexedNode editAndSet(AtomicReference<Thread> edit, int i, Object a) {
709708
BitmapIndexedNode editable = ensureEditable(edit);
710709
editable.array[i] = a;
711710
return editable;
712711
}
713712

714-
private BitmapIndexedNode editAndSet(AtomicBoolean edit, int i, Object a, int j, Object b) {
713+
private BitmapIndexedNode editAndSet(AtomicReference<Thread> edit, int i, Object a, int j, Object b) {
715714
BitmapIndexedNode editable = ensureEditable(edit);
716715
editable.array[i] = a;
717716
editable.array[j] = b;
718717
return editable;
719718
}
720719

721-
private BitmapIndexedNode editAndRemovePair(AtomicBoolean edit, int bit, int i) {
720+
private BitmapIndexedNode editAndRemovePair(AtomicReference<Thread> edit, int bit, int i) {
722721
if (bitmap == bit)
723722
return null;
724723
BitmapIndexedNode editable = ensureEditable(edit);
@@ -729,7 +728,7 @@ private BitmapIndexedNode editAndRemovePair(AtomicBoolean edit, int bit, int i)
729728
return editable;
730729
}
731730

732-
public INode assoc(AtomicBoolean edit, int shift, int hash, Object key, Object val, Box addedLeaf){
731+
public INode assoc(AtomicReference<Thread> edit, int shift, int hash, Object key, Object val, Box addedLeaf){
733732
int bit = bitpos(hash, shift);
734733
int idx = index(bit);
735734
if((bitmap & bit) != 0) {
@@ -789,7 +788,7 @@ public INode assoc(AtomicBoolean edit, int shift, int hash, Object key, Object v
789788
}
790789
}
791790

792-
public INode without(AtomicBoolean edit, int shift, int hash, Object key, Box removedLeaf){
791+
public INode without(AtomicReference<Thread> edit, int shift, int hash, Object key, Box removedLeaf){
793792
int bit = bitpos(hash, shift);
794793
if((bitmap & bit) == 0)
795794
return this;
@@ -820,9 +819,9 @@ final static class HashCollisionNode implements INode{
820819
final int hash;
821820
int count;
822821
Object[] array;
823-
final AtomicBoolean edit;
822+
final AtomicReference<Thread> edit;
824823

825-
HashCollisionNode(AtomicBoolean edit, int hash, int count, Object... array){
824+
HashCollisionNode(AtomicReference<Thread> edit, int hash, int count, Object... array){
826825
this.edit = edit;
827826
this.hash = hash;
828827
this.count = count;
@@ -897,15 +896,15 @@ public int findIndex(Object key){
897896
return -1;
898897
}
899898

900-
private HashCollisionNode ensureEditable(AtomicBoolean edit){
899+
private HashCollisionNode ensureEditable(AtomicReference<Thread> edit){
901900
if(this.edit == edit)
902901
return this;
903902
Object[] newArray = new Object[2*(count+1)]; // make room for next assoc
904903
System.arraycopy(array, 0, newArray, 0, 2*count);
905904
return new HashCollisionNode(edit, hash, count, newArray);
906905
}
907906

908-
private HashCollisionNode ensureEditable(AtomicBoolean edit, int count, Object[] array){
907+
private HashCollisionNode ensureEditable(AtomicReference<Thread> edit, int count, Object[] array){
909908
if(this.edit == edit) {
910909
this.array = array;
911910
this.count = count;
@@ -914,21 +913,21 @@ private HashCollisionNode ensureEditable(AtomicBoolean edit, int count, Object[]
914913
return new HashCollisionNode(edit, hash, count, array);
915914
}
916915

917-
private HashCollisionNode editAndSet(AtomicBoolean edit, int i, Object a) {
916+
private HashCollisionNode editAndSet(AtomicReference<Thread> edit, int i, Object a) {
918917
HashCollisionNode editable = ensureEditable(edit);
919918
editable.array[i] = a;
920919
return editable;
921920
}
922921

923-
private HashCollisionNode editAndSet(AtomicBoolean edit, int i, Object a, int j, Object b) {
922+
private HashCollisionNode editAndSet(AtomicReference<Thread> edit, int i, Object a, int j, Object b) {
924923
HashCollisionNode editable = ensureEditable(edit);
925924
editable.array[i] = a;
926925
editable.array[j] = b;
927926
return editable;
928927
}
929928

930929

931-
public INode assoc(AtomicBoolean edit, int shift, int hash, Object key, Object val, Box addedLeaf){
930+
public INode assoc(AtomicReference<Thread> edit, int shift, int hash, Object key, Object val, Box addedLeaf){
932931
if(hash == this.hash) {
933932
int idx = findIndex(key);
934933
if(idx != -1) {
@@ -954,7 +953,7 @@ public INode assoc(AtomicBoolean edit, int shift, int hash, Object key, Object v
954953
.assoc(edit, shift, hash, key, val, addedLeaf);
955954
}
956955

957-
public INode without(AtomicBoolean edit, int shift, int hash, Object key, Box removedLeaf){
956+
public INode without(AtomicReference<Thread> edit, int shift, int hash, Object key, Box removedLeaf){
958957
int idx = findIndex(key);
959958
if(idx == -1)
960959
return this;
@@ -1088,13 +1087,13 @@ private static INode createNode(int shift, Object key1, Object val1, int key2has
10881087
if(key1hash == key2hash)
10891088
return new HashCollisionNode(null, key1hash, 2, new Object[] {key1, val1, key2, val2});
10901089
Box addedLeaf = new Box(null);
1091-
AtomicBoolean edit = new AtomicBoolean(false);
1090+
AtomicReference<Thread> edit = new AtomicReference<Thread>();
10921091
return BitmapIndexedNode.EMPTY
10931092
.assoc(edit, shift, key1hash, key1, val1, addedLeaf)
10941093
.assoc(edit, shift, key2hash, key2, val2, addedLeaf);
10951094
}
10961095

1097-
private static INode createNode(AtomicBoolean edit, int shift, Object key1, Object val1, int key2hash, Object key2, Object val2) {
1096+
private static INode createNode(AtomicReference<Thread> edit, int shift, Object key1, Object val1, int key2hash, Object key2, Object val2) {
10981097
int key1hash = hash(key1);
10991098
if(key1hash == key2hash)
11001099
return new HashCollisionNode(null, key1hash, 2, new Object[] {key1, val1, key2, val2});

src/jvm/clojure/lang/PersistentVector.java

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,26 +15,26 @@
1515
import java.io.Serializable;
1616
import java.util.Iterator;
1717
import java.util.List;
18-
import java.util.concurrent.atomic.AtomicBoolean;
18+
import java.util.concurrent.atomic.AtomicReference;
1919

2020
public class PersistentVector extends APersistentVector implements IObj, IEditableCollection, IReduce{
2121

2222
public static class Node implements Serializable {
23-
transient public final AtomicBoolean edit;
23+
transient public final AtomicReference<Thread> edit;
2424
public final Object[] array;
2525

26-
public Node(AtomicBoolean edit, Object[] array){
26+
public Node(AtomicReference<Thread> edit, Object[] array){
2727
this.edit = edit;
2828
this.array = array;
2929
}
3030

31-
Node(AtomicBoolean edit){
31+
Node(AtomicReference<Thread> edit){
3232
this.edit = edit;
3333
this.array = new Object[32];
3434
}
3535
}
3636

37-
final static AtomicBoolean NOEDIT = new AtomicBoolean(false);
37+
final static AtomicReference<Thread> NOEDIT = new AtomicReference<Thread>(null);
3838
public final static Node EMPTY_NODE = new Node(NOEDIT, new Object[32]);
3939

4040
final int cnt;
@@ -215,7 +215,7 @@ private Node pushTail(int level, Node parent, Node tailnode){
215215
return ret;
216216
}
217217

218-
private static Node newPath(AtomicBoolean edit,int level, Node node){
218+
private static Node newPath(AtomicReference<Thread> edit,int level, Node node){
219219
if(level == 0)
220220
return node;
221221
Node ret = new Node(edit);
@@ -475,16 +475,15 @@ Node ensureEditable(Node node){
475475
}
476476

477477
void ensureEditable(){
478-
if(root.edit.get())
479-
return;
480-
throw new IllegalAccessError("Transient used after persistent! call");
478+
if(root.edit.get() == null)
479+
throw new IllegalAccessError("Transient used after persistent! call");
481480

482481
// root = editableRoot(root);
483482
// tail = editableTail(tail);
484483
}
485484

486485
static Node editableRoot(Node node){
487-
return new Node(new AtomicBoolean(true), node.array.clone());
486+
return new Node(new AtomicReference<Thread>(Thread.currentThread()), node.array.clone());
488487
}
489488

490489
public PersistentVector persistent(){
@@ -494,7 +493,7 @@ public PersistentVector persistent(){
494493
// {
495494
// throw new IllegalAccessError("Mutation release by non-owner thread");
496495
// }
497-
root.edit.set(false);
496+
root.edit.set(null);
498497
Object[] trimmedTail = new Object[cnt-tailoff()];
499498
System.arraycopy(tail,0,trimmedTail,0,trimmedTail.length);
500499
return new PersistentVector(cnt, shift, root, trimmedTail);

0 commit comments

Comments
 (0)