diff options
author | Rich Hickey <richhickey@gmail.com> | 2006-06-03 16:44:49 +0000 |
---|---|---|
committer | Rich Hickey <richhickey@gmail.com> | 2006-06-03 16:44:49 +0000 |
commit | 9f0e5fc90b67ac32dd0516065af2ff82f9d9d3bf (patch) | |
tree | f7b1144ee70c5a9d7c622ff89acede57a43bea4b /src | |
parent | be2df160b1e5c916174262bc411dffa081eded99 (diff) |
added has, resize, load, and isolate
Diffstat (limited to 'src')
-rw-r--r-- | src/cli/runtime/PersistentArray.cs | 42 | ||||
-rw-r--r-- | src/org/clojure/runtime/PersistentArray.java | 62 |
2 files changed, 96 insertions, 8 deletions
diff --git a/src/cli/runtime/PersistentArray.cs b/src/cli/runtime/PersistentArray.cs index 59d41117..654aa2e8 100644 --- a/src/cli/runtime/PersistentArray.cs +++ b/src/cli/runtime/PersistentArray.cs @@ -37,12 +37,14 @@ internal class Master{ internal readonly Entry[] array;
internal readonly Object defaultVal;
internal int rev;
+ internal int load;
internal Master(int size, Object defaultVal)
{
this.array = new Entry[size];
this.defaultVal = defaultVal;
this.rev = 0;
+ this.load = 0;
}
}
@@ -122,16 +124,51 @@ public int length(){ }
public Object get(int i){
+ Entry e = getEntry(i);
+ if(e != null)
+ return e.val;
+ return master.defaultVal;
+}
+
+public bool has(int i){
+ return getEntry(i) != null;
+}
+
+public PersistentArray resize(int newLength)
+ {
+ PersistentArray ret = new PersistentArray(newLength, master.defaultVal);
+ for (int i = 0; i < Math.Min(length(), newLength); i++)
+ {
+ Entry e = getEntry(i);
+ if (e != null)
+ {
+ ret.master.array[i] = new Entry(0, e.val, null);
+ ++ret.master.load;
+ }
+ }
+ return ret;
+ }
+
+public int load(){
+ return master.load;
+}
+
+public PersistentArray isolate()
+ {
+ return resize(length());
+ }
+
+Entry getEntry(int i){
for(Entry e = (Entry) master.array[i];e != null;e = e.rest)
{
if(e.rev <= rev)
{
if(e.rev >= baseline
|| (history != null && e.rev < history.Length && history.Get(e.rev)))
- return e.val;
+ return e;
}
}
- return master.defaultVal;
+ return null;
}
public PersistentArray set(int i,Object val) {
@@ -148,6 +185,7 @@ void doSet(int i, Object val){ newEntry = new Entry(rev, val, oldEntry);
master.array[i] = newEntry;
}
+ Interlocked.Increment(ref master.load);
}
PersistentArray getSetArray(){
diff --git a/src/org/clojure/runtime/PersistentArray.java b/src/org/clojure/runtime/PersistentArray.java index 1fc52e30..ab60f115 100644 --- a/src/org/clojure/runtime/PersistentArray.java +++ b/src/org/clojure/runtime/PersistentArray.java @@ -21,6 +21,12 @@ import java.util.Random; /** * Hybrid range/bitset, multi-thread-safe + * Multiple versions (thread-safely) share the same master array + * + * By default, all old values are retained, even if the array revisions aren't + * you can determine how many values are in the shared master by calling load() + * and can trim them by calling isolate() or resize(), which yield a new array with no + * sharing and no old values * * See Cohen for basic idea */ @@ -34,12 +40,14 @@ public Iterator iterator(){ static class Master{ final AtomicReferenceArray array; final Object defaultVal; - final AtomicInteger rev; + final AtomicInteger rev; + final AtomicInteger load; Master(int size,Object defaultVal){ this.array = new AtomicReferenceArray(size); this.defaultVal = defaultVal; - this.rev = new AtomicInteger(0); + this.rev = new AtomicInteger(0); + this.load = new AtomicInteger(0); } } @@ -104,17 +112,58 @@ public int length(){ return master.array.length(); } -public Object get(int i){ +public Object get(int i) { + Entry e = getEntry(i); + if(e != null) + return e.val; + return master.defaultVal; +} + +public boolean has(int i){ + return getEntry(i) != null; +} + +public PersistentArray resize(int newLength) { + PersistentArray ret = new PersistentArray(newLength, master.defaultVal); + int load = 0; + for(int i=0;i< Math.min(length(),newLength);i++) + { + Entry e = getEntry(i); + if(e != null) + { + ret.master.array.set(i,new Entry(0,e.val, null)); + ++load; + } + } + + ret.master.load.set(load); + + return ret; +} + +/** + * + * @return number of values (of all revisions) stored in shared array + */ +public int load(){ + return master.load.get(); +} + +public PersistentArray isolate() { + return resize(length()); +} + +Entry getEntry(int i){ for(Entry e = (Entry) master.array.get(i);e != null;e = e.rest) { if(e.rev <= rev) { if(e.rev >= baseline || (history != null && history.get(e.rev))) - return e.val; + return e; } } - return master.defaultVal; + return null; } public PersistentArray set(int i,Object val) { @@ -130,6 +179,7 @@ void doSet(int i, Object val){ oldEntry = (Entry) master.array.get(i); newEntry = new Entry(rev, val, oldEntry); } while(!master.array.compareAndSet(i, oldEntry, newEntry)); + master.load.incrementAndGet(); } PersistentArray getSetArray(){ @@ -150,7 +200,7 @@ PersistentArray getSetArray(){ if(history != null) nextHistory = (BitSet) history.clone(); else - nextHistory = new BitSet(rev); + nextHistory = new BitSet(rev+1); nextHistory.set(baseline,rev+1); } |