changeset 785:d69d3c51c44e

more work on incremental cloning
author Franklin Schmidt <fschmidt@gmail.com>
date Thu, 01 Sep 2016 21:32:28 -0600
parents 6a7c6879158d
children fe63c508a177
files src/luan/LuanCloner.java src/luan/LuanState.java src/luan/LuanTable.java src/luan/impl/Closure.java src/luan/impl/LuanParser.java src/luan/modules/ThreadLuan.java src/luan/modules/http/HttpServicer.java src/luan/modules/http/LuanHandler.java
diffstat 8 files changed, 85 insertions(+), 33 deletions(-) [+]
line wrap: on
line diff
--- a/src/luan/LuanCloner.java	Tue Aug 30 12:08:49 2016 -0600
+++ b/src/luan/LuanCloner.java	Thu Sep 01 21:32:28 2016 -0600
@@ -6,11 +6,13 @@
 
 
 public final class LuanCloner {
-	public final boolean deep;
+	public enum Type { COMPLETE, INCREMENTAL }
+
+	public final Type type;
 	private final Map cloned = new IdentityHashMap();
 
-	public LuanCloner(boolean deep) {
-		this.deep = deep;
+	public LuanCloner(Type type) {
+		this.type = type;
 	}
 
 	public LuanCloneable clone(LuanCloneable obj) {
@@ -62,14 +64,4 @@
 			return clone((Map)obj);
 		return obj;
 	}
-/*
-	public Object check(Object obj) {
-		if( deep )
-			throw new RuntimeException();
-		if( !(obj instanceof LuanCloneable) )
-			return obj;
-		LuanCloneable lc = (LuanCloneable)obj;
-		return lc.getCloner() == this ? lc : clone(lc);
-	}
-*/
 }
--- a/src/luan/LuanState.java	Tue Aug 30 12:08:49 2016 -0600
+++ b/src/luan/LuanState.java	Thu Sep 01 21:32:28 2016 -0600
@@ -33,6 +33,13 @@
 		LuanState clone = (LuanState)dc;
 		clone.registry = cloner.clone(registry);
 		clone.java = (LuanJava)cloner.clone(java);
+/*
+		if( !cloner.deep ) {
+			LuanCloner myCloner = new LuanCloner(false);
+			registry = myCloner.clone(registry);
+			java = (LuanJava)myCloner.clone(java);
+		}
+*/
 	}
 
 	public final Map registry() {
--- a/src/luan/LuanTable.java	Tue Aug 30 12:08:49 2016 -0600
+++ b/src/luan/LuanTable.java	Thu Sep 01 21:32:28 2016 -0600
@@ -61,24 +61,44 @@
 	}
 
 	@Override public void deepenClone(LuanCloneable dc,LuanCloner cloner) {
+		check();
 		LuanTable clone = (LuanTable)dc;
+		switch( cloner.type ) {
+		case COMPLETE:
+			deepenClone(clone,cloner);
+			return;
+		case INCREMENTAL:
+			clone.cloner = cloner;
+			clone.map = map;
+			clone.list = list;
+			clone.metatable = metatable;
+			clone.java = java;
+			return;
+		}
+	}
+
+	private void check() {
+		if( cloner != null ) {
+			deepenClone(this,cloner);
+			cloner = null;
+		}
+	}
+
+	private void deepenClone(LuanTable clone,LuanCloner cloner) {
 		if( map != null ) {
-			clone.map = newMap();
+			Map newMap = newMap();
 			for( Object stupid : map.entrySet() ) {
 				Map.Entry entry = (Map.Entry)stupid;
-				Object val = entry.getValue();
-				if( cloner.deep || !(val instanceof LuanTable) )
-					val = cloner.get(val);
-				clone.map.put( cloner.get(entry.getKey()), val );
+				newMap.put( cloner.get(entry.getKey()), cloner.get(entry.getValue()) );
 			}
+			clone.map = newMap;
 		}
 		if( list != null ) {
-			clone.list = new ArrayList<Object>();
+			List newList = new ArrayList<Object>();
 			for( Object obj : list ) {
-				if( cloner.deep || !(obj instanceof LuanTable) )
-					obj = cloner.get(obj);
-				clone.list.add(obj);
+				newList.add(cloner.get(obj));
 			}
+			clone.list = newList;
 		}
 		clone.metatable = (LuanTable)cloner.clone(metatable);
 		clone.java = (LuanJava)cloner.clone(java);
@@ -89,6 +109,7 @@
 	}
 
 	public List<Object> asList() {
+		check();
 		return list!=null ? list : Collections.emptyList();
 	}
 
@@ -127,6 +148,7 @@
 	}
 
 	public Object rawGet(Object key) {
+		check();
 		if( list != null ) {
 			Integer iT = Luan.asInteger(key);
 			if( iT != null ) {
@@ -169,6 +191,7 @@
 	}
 
 	public void rawPut(Object key,Object val) {
+		check();
 		Integer iT = Luan.asInteger(key);
 		if( iT != null ) {
 			int i = iT - 1;
@@ -235,6 +258,7 @@
 	}
 
 	public void rawInsert(int pos,Object value) {
+		check();
 		if( value==null )
 			throw new IllegalArgumentException("can't insert a nil value");
 		list().add(pos-1,value);
@@ -242,10 +266,12 @@
 	}
 
 	public Object rawRemove(int pos) {
+		check();
 		return list().remove(pos-1);
 	}
 
 	public void rawSort(Comparator<Object> cmp) {
+		check();
 		Collections.sort(list(),cmp);
 	}
 
@@ -259,6 +285,7 @@
 	}
 
 	public int rawLength() {
+		check();
 		return list==null ? 0 : list.size();
 	}
 
@@ -350,6 +377,7 @@
 	}
 
 	public Iterator<Map.Entry<Object,Object>> rawIterator() {
+		check();
 		if( list == null ) {
 			if( map == null )
 				return Collections.<Map.Entry<Object,Object>>emptyList().iterator();
@@ -403,20 +431,24 @@
 	}
 
 	public LuanTable rawSubList(int from,int to) {
+		check();
 		LuanTable tbl = new LuanTable();
 		tbl.list = new ArrayList<Object>(list().subList(from-1,to-1));
 		return tbl;
 	}
 
 	public LuanTable getMetatable() {
+		check();
 		return metatable;
 	}
 
 	public void setMetatable(LuanTable metatable) {
+		check();
 		this.metatable = metatable;
 	}
 
 	public Object getHandler(String op) {
+		check();
 		return metatable==null ? null : metatable.rawGet(op);
 	}
 
@@ -449,6 +481,7 @@
 	}
 
 	public void rawClear() {
+		check();
 		map = null;
 		list = null;
 	}
--- a/src/luan/impl/Closure.java	Tue Aug 30 12:08:49 2016 -0600
+++ b/src/luan/impl/Closure.java	Thu Sep 01 21:32:28 2016 -0600
@@ -11,11 +11,12 @@
 
 public abstract class Closure extends LuanFunction implements LuanCloneable, Cloneable {
 	public Pointer[] upValues;
-	public LuanJava java;
+	public LuanJava ljava;
+	private LuanCloner cloner;
 
 	public Closure(int nUpValues,LuanJava java) throws LuanException {
 		this.upValues = new Pointer[nUpValues];
-		this.java = java;
+		this.ljava = java;
 	}
 
 	@Override public Closure shallowClone() {
@@ -27,14 +28,33 @@
 	}
 
 	@Override public void deepenClone(LuanCloneable dc,LuanCloner cloner) {
+		check();
 		Closure clone = (Closure)dc;
-		clone.upValues = (Pointer[])cloner.clone(upValues);
-		clone.java = (LuanJava)cloner.clone(java);
+		switch( cloner.type ) {
+		case COMPLETE:
+			clone.upValues = (Pointer[])cloner.clone(upValues);
+			clone.ljava = (LuanJava)cloner.clone(ljava);
+			return;
+		case INCREMENTAL:
+			clone.cloner = cloner;
+			clone.upValues = upValues;
+			clone.ljava = ljava;
+			return;
+		}
+	}
+
+	private void check() {
+		if( cloner != null ) {
+			upValues = (Pointer[])cloner.clone(upValues);
+			ljava = (LuanJava)cloner.clone(ljava);
+			cloner = null;
+		}
 	}
 
 	@Override public final Object call(LuanState luan,Object[] args) throws LuanException {
+		check();
 		LuanJava old = luan.java;
-		luan.java = java;
+		luan.java = ljava;
 		try {
 			return doCall(luan,args);
 		} catch(StackOverflowError e) {
--- a/src/luan/impl/LuanParser.java	Tue Aug 30 12:08:49 2016 -0600
+++ b/src/luan/impl/LuanParser.java	Thu Sep 01 21:32:28 2016 -0600
@@ -1967,7 +1967,7 @@
 			stmt.add( "return LuanFunction.NOTHING;  " );
 		Expr exp = new Expr(Val.SINGLE,false);
 		exp.add( ""
-			+"new Closure("+upValueSymbols.size()+",java) {  "
+			+"new Closure("+upValueSymbols.size()+",ljava) {  "
 				+"{  "
 				+ init(upValueSymbols)
 				+"}  "
--- a/src/luan/modules/ThreadLuan.java	Tue Aug 30 12:08:49 2016 -0600
+++ b/src/luan/modules/ThreadLuan.java	Thu Sep 01 21:32:28 2016 -0600
@@ -19,7 +19,7 @@
 	private static final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
 
 	public static void fork(LuanState luan,LuanFunction fn,Object... args) {
-		LuanCloner cloner = new LuanCloner(true);
+		LuanCloner cloner = new LuanCloner(LuanCloner.Type.COMPLETE);
 		final LuanState newLuan = (LuanState)cloner.clone(luan);
 		final LuanFunction newFn = (LuanFunction)cloner.get(fn);
 		final Object[] newArgs = cloner.clone(args);
@@ -44,7 +44,7 @@
 	}
 
 	public static void schedule(LuanState luan,long delay,boolean repeat,LuanFunction fn,Object... args) {
-		LuanCloner cloner = new LuanCloner(true);
+		LuanCloner cloner = new LuanCloner(LuanCloner.Type.COMPLETE);
 		final LuanState newLuan = (LuanState)cloner.clone(luan);
 		final LuanFunction newFn = (LuanFunction)cloner.get(fn);
 		final Object[] newArgs = cloner.clone(args);
--- a/src/luan/modules/http/HttpServicer.java	Tue Aug 30 12:08:49 2016 -0600
+++ b/src/luan/modules/http/HttpServicer.java	Thu Sep 01 21:32:28 2016 -0600
@@ -59,13 +59,13 @@
 				if( sessionLuan!=null ) {
 					luan = sessionLuan;
 				} else {
-					LuanCloner cloner = new LuanCloner(true);
+					LuanCloner cloner = new LuanCloner(LuanCloner.Type.COMPLETE);
 					luan = (LuanState)cloner.clone(luan);
 					session.setAttribute("luan",luan);
 				}
 				fn = (LuanFunction)PackageLuan.require(luan,modName);
 			} else {
-				LuanCloner cloner = new LuanCloner(true);
+				LuanCloner cloner = new LuanCloner(LuanCloner.Type.COMPLETE);
 				luan = (LuanState)cloner.clone(luan);
 				fn = (LuanFunction)cloner.get(mod);
 			}
--- a/src/luan/modules/http/LuanHandler.java	Tue Aug 30 12:08:49 2016 -0600
+++ b/src/luan/modules/http/LuanHandler.java	Thu Sep 01 21:32:28 2016 -0600
@@ -70,7 +70,7 @@
 
 	public static Object callRpc(LuanState luan,String fnName,Object... args) throws LuanException {
 		synchronized(luan) {
-			LuanCloner cloner = new LuanCloner(true);
+			LuanCloner cloner = new LuanCloner(LuanCloner.Type.COMPLETE);
 			luan = (LuanState)cloner.clone(luan);
 		}
 		LuanTable rpc = (LuanTable)PackageLuan.require(luan,"luan:Rpc.luan");