diff src/luan/modules/ThreadLuan.java @ 1578:c922446f53aa

immutable threading
author Franklin Schmidt <fschmidt@gmail.com>
date Mon, 08 Feb 2021 14:16:19 -0700
parents 8fbcc4747091
children f2a663a4ba9e
line wrap: on
line diff
--- a/src/luan/modules/ThreadLuan.java	Sun Jan 31 16:04:39 2021 -0700
+++ b/src/luan/modules/ThreadLuan.java	Mon Feb 08 14:16:19 2021 -0700
@@ -17,8 +17,7 @@
 import luan.LuanFunction;
 import luan.LuanTable;
 import luan.LuanException;
-import luan.LuanCloner;
-import luan.LuanCloneable;
+import luan.LuanMutable;
 import luan.modules.logging.LuanLogger;
 import goodjava.logging.Logger;
 import goodjava.logging.LoggerFactory;
@@ -45,10 +44,9 @@
 		};
 	}
 
-	public static void fork(Luan luan,LuanFunction fn) {
-		LuanCloner cloner = new LuanCloner(LuanCloner.Type.COMPLETE);
-		luan = (Luan)cloner.get(luan);
-		fn = (LuanFunction)cloner.get(fn);
+	public static void fork(Luan luan,LuanFunction fn) throws LuanException {
+		luan = new Luan(luan);
+		LuanMutable.makeImmutable(fn);
 		exec.execute(runnable(luan,fn));
 	}
 
@@ -60,9 +58,26 @@
 			logger.error(src+" cancel="+b+" isCancelled="+sf.isCancelled()+" isDone="+sf.isDone()+" "+sf);
 	}
 
+	public static synchronized void schedule_closure(Luan luan,LuanFunction initFn,LuanTable options)
+		throws LuanException
+	{
+		final Luan newLuan = new Luan(luan);
+		LuanMutable.makeImmutable(initFn);
+		LuanFunction fn = (LuanFunction)initFn.call(newLuan);
+		scheduleFn(luan,newLuan,fn,options);
+	}
+
 	public static synchronized void schedule(Luan luan,LuanFunction fn,LuanTable options)
 		throws LuanException
 	{
+		final Luan newLuan = new Luan(luan);
+		LuanMutable.makeImmutable(fn);
+		scheduleFn(luan,newLuan,fn,options);
+	}
+
+	private static synchronized void scheduleFn(Luan luan,final Luan newLuan,LuanFunction fn,LuanTable options)
+		throws LuanException
+	{
 		options = new LuanTable(options);
 		Number delay = Utils.removeNumber(options,"delay");
 		Number repeatingDelay = Utils.removeNumber(options,"repeating_delay");
@@ -77,10 +92,7 @@
 			if( sf != null )
 				cancel(sf,"id "+id);
 		}
-		LuanCloner cloner = new LuanCloner(LuanCloner.Type.COMPLETE);
-		final Luan newLuan = (Luan)cloner.clone(luan);
-		final LuanFunction newFn = (LuanFunction)cloner.get(fn);
-		final Runnable r = runnable(newLuan,newFn);
+		final Runnable r = runnable(newLuan,fn);
 		final ScheduledFuture sf;
 		if( repeatingDelay != null ) {
 			if( delay==null )
@@ -106,104 +118,24 @@
 			scheduleds.put(id,sf);
 	}
 
-/*
-	public static class GlobalMap {
-
-		private static class Value {
-			final long time = System.currentTimeMillis();
-			final Object v;
-
-			Value(Object v) {
-				this.v = v;
-			}
-		}
-
-		public long timeout = 60000L;  // one minute
-		private Map<String,Value> map = new LinkedHashMap<String,Value>() {
-			protected boolean removeEldestEntry(Map.Entry<String,Value> eldest) {
-				return eldest.getValue().time < System.currentTimeMillis() - timeout;
-			}
-		};
-
-		public synchronized Object get(String key) {
-			Value val = map.get(key);
-			return val==null ? null : val.v;
-		}
-
-		public synchronized Object put(String key,Object v) throws LuanException {
-			Value val;
-			if( v == null ) {
-				val = map.remove(key);
-			} else {
-				if( !(v instanceof String || v instanceof Boolean || v instanceof Number) )
-					throw new LuanException("can't assign type "+Luan.type(v)+" to Thread.global");
-				val = map.put(key,new Value(v));
-			}
-			return val==null ? null : val.v;
-		}
-	}
-*/
 
 	public static void sleep(long millis) throws InterruptedException {
 		Thread.sleep(millis);
 	}
 
 
-	private static class Unsafe {
-		private final String reason;
-
-		Unsafe(String reason) {
-			this.reason = reason;
-		}
-	}
-
-	private static Object makeSafe(Object v) throws LuanException {
-		if( v instanceof LuanTable ) {
-			LuanTable tbl = (LuanTable)v;
-			if( tbl.getMetatable() != null )
-				return new Unsafe("table with metatable");
-			LuanTable rtn = new LuanTable();
-			for( Map.Entry entry : tbl.rawIterable() ) {
-				Object key = makeSafe( entry.getKey() );
-				if( key instanceof Unsafe )
-					return key;
-				Object value = makeSafe( entry.getValue() );
-				if( value instanceof Unsafe )
-					return value;
-				rtn.rawPut(key,value);
-			}
-			return rtn;
-		} else if( v instanceof Object[] ) {
-			Object[] a = (Object[])v;
-			for( int i=0; i<a.length; i++ ) {
-				Object obj = makeSafe(a[i]);
-				if( obj instanceof Unsafe )
-					return obj;
-				a[i] = obj;
-			}
-			return a;
-		} else {
-			if( v instanceof LuanCloneable )
-				return new Unsafe("type "+Luan.type(v));
-			return v;
-		}
-	}
-
 	public static final class Callable {
 		private long expires;
 		private final Luan luan = new Luan();
 		private final LuanTable fns;
 
-		Callable(LuanTable fns) {
-			LuanCloner cloner = new LuanCloner(LuanCloner.Type.COMPLETE);
-			this.fns = (LuanTable)cloner.get(fns);
+		Callable(LuanFunction initFn) throws LuanException {
+			LuanMutable.makeImmutable(initFn);
+			this.fns = (LuanTable)initFn.call(luan);
 		}
 
 		public synchronized Object call(Luan callerLuan,String fnName,Object... args) throws LuanException {
-			Object obj = makeSafe(args);
-			if( obj instanceof Unsafe )
-				throw new LuanException("can't pass "+((Unsafe)obj).reason+" to global_callable "+Arrays.asList(args));
-			args = (Object[])obj;
+			LuanMutable.makeImmutable(args);
 			Object f = fns.get(luan,fnName);
 			if( f == null )
 				throw new LuanException("function '"+fnName+"' not found in global_callable");
@@ -211,9 +143,7 @@
 				throw new LuanException("value of '"+fnName+"' not a function in global_callable");
 			LuanFunction fn = (LuanFunction)f;
 			Object rtn = fn.call(luan,args);
-			rtn = makeSafe(rtn);
-			if( rtn instanceof Unsafe )
-				throw new LuanException("can't return "+((Unsafe)rtn).reason+" from global_callable");
+			LuanMutable.makeImmutable(rtn);
 			return rtn;
 		}
 	}
@@ -229,11 +159,11 @@
 		}
 	}
 
-	public static synchronized Callable globalCallable(String name,LuanTable fns,long timeout) {
+	public static synchronized Callable globalCallable(String name,LuanFunction initFn,long timeout) throws LuanException {
 		Callable callable = callableMap.get(name);
 		if( callable == null ) {
 			sweep();
-			callable = new Callable(fns);
+			callable = new Callable(initFn);
 			callableMap.put(name,callable);
 		}
 		callable.expires = System.currentTimeMillis() + timeout;