changeset 1366:ae2321a09723

improve Thread.schedule
author Franklin Schmidt <fschmidt@gmail.com>
date Mon, 17 Jun 2019 21:50:40 -0600
parents 6617763dfd76
children 836e00bf7ce2
files conv.txt src/luan/modules/Thread.luan src/luan/modules/ThreadLuan.java src/luan/modules/host/Hosting.luan
diffstat 4 files changed, 87 insertions(+), 41 deletions(-) [+]
line wrap: on
line diff
--- a/conv.txt	Wed Jun 12 22:16:10 2019 -0600
+++ b/conv.txt	Mon Jun 17 21:50:40 2019 -0600
@@ -1,3 +1,5 @@
+Thread.schedule
+
 java()
 
 luan.webserver
--- a/src/luan/modules/Thread.luan	Wed Jun 12 22:16:10 2019 -0600
+++ b/src/luan/modules/Thread.luan	Mon Jun 17 21:50:40 2019 -0600
@@ -29,9 +29,10 @@
 	ThreadLuan.fork(fn)
 end
 
-function Thread.schedule(delay,fn,repeating)
+function Thread.schedule(fn,options)
 	fn = safe(fn)
-	ThreadLuan.schedule(delay,fn,repeating)
+	options = options or {}
+	ThreadLuan.schedule(fn,options)
 end
 
 
@@ -80,4 +81,13 @@
 	return tbl
 end
 
+
+local backup_lock = ThreadLuan.backupLock.readLock()
+local run_in_lock = ThreadLuan.runInLock
+
+function Thread.run_for_backup(fn)
+	return run_in_lock(backup_lock,fn)
+end
+
+
 return Thread
--- a/src/luan/modules/ThreadLuan.java	Wed Jun 12 22:16:10 2019 -0600
+++ b/src/luan/modules/ThreadLuan.java	Mon Jun 17 21:50:40 2019 -0600
@@ -8,9 +8,13 @@
 import java.util.LinkedHashMap;
 import java.util.concurrent.Executor;
 import java.util.concurrent.Executors;
-import java.util.concurrent.ScheduledThreadPoolExecutor;
+import java.util.concurrent.ScheduledExecutorService;
 import java.util.concurrent.ScheduledFuture;
 import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
 import luan.Luan;
 import luan.LuanFunction;
 import luan.LuanTable;
@@ -21,59 +25,74 @@
 
 public final class ThreadLuan {
 	private static final Executor exec = Executors.newCachedThreadPool();
-	public static final ScheduledThreadPoolExecutor scheduler = new ScheduledThreadPoolExecutor(1);
+	public static final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
 
-	public static void fork(LuanFunction fn) {
-		LuanCloner cloner = new LuanCloner(LuanCloner.Type.COMPLETE);
-		final LuanFunction newFn = (LuanFunction)cloner.get(fn);
-		exec.execute(new Runnable(){public void run() {
-			try {
-				newFn.call();
-			} catch(LuanException e) {
-				e.printStackTrace();
-			}
-		}});
-	}
-/*
-	public static LuanFunction synchronized_(final Luan luan,final LuanFunction fn) throws LuanException {
-		Utils.checkNotNull(fn);
-		return new LuanFunction() {
-			@Override public Object call(Luan ingored,Object[] args) throws LuanException {
-				synchronized(luan) {
-					return fn.call(luan,args);
+	private static Runnable runnable(final LuanFunction fn) {
+		return new Runnable() {
+			public synchronized void run() {
+				try {
+					fn.call();
+				} catch(LuanException e) {
+					e.printStackTrace();
 				}
 			}
 		};
 	}
-*/
-	public static void schedule(long delay,LuanFunction fn,String repeating)
+
+	public static void fork(LuanFunction fn) {
+		LuanCloner cloner = new LuanCloner(LuanCloner.Type.COMPLETE);
+		final LuanFunction newFn = (LuanFunction)cloner.get(fn);
+		exec.execute(runnable(newFn));
+	}
+
+	public static void schedule(LuanFunction fn,LuanTable options)
 		throws LuanException
 	{
+		Map map = options.asMap();
+		Number delay = (Number)map.remove("delay");
+		Number repeatingDelay = (Number)map.remove("repeating_delay");
+		Number repeatingRate = (Number)map.remove("repeating_rate");
+		boolean daemon = Boolean.TRUE.equals(map.remove("daemon"));
+		final boolean runOnClose = Boolean.TRUE.equals(map.remove("run_on_close"));
+		if( repeatingDelay!=null && repeatingRate!=null )
+			throw new LuanException("can't define both repeating_delay and repeating_rate");
+		boolean repeating = repeatingDelay!=null || repeatingRate!=null;
+		if( !map.isEmpty() )
+			throw new LuanException( "unrecognized options: "+map );
 		Luan luan = fn.luan();
 		LuanCloner cloner = new LuanCloner(LuanCloner.Type.COMPLETE);
 		final Luan newLuan = (Luan)cloner.clone(luan);
 		final LuanFunction newFn = (LuanFunction)cloner.get(fn);
-		Runnable r = new Runnable(){public void run() {
-			try {
-				newFn.call();
-			} catch(LuanException e) {
-				e.printStackTrace();
-			}
-		}};
+		final Runnable r = runnable(newFn);
 		final ScheduledFuture sf;
-		if( repeating==null ) {
-			sf = scheduler.schedule(r,delay,TimeUnit.MILLISECONDS);
-		} else if( repeating.equals("with_fixed_delay") ) {
-			sf = scheduler.scheduleWithFixedDelay(r,delay,delay,TimeUnit.MILLISECONDS);
-		} else if( repeating.equals("at_fixed_rate") ) {
-			sf = scheduler.scheduleAtFixedRate(r,delay,delay,TimeUnit.MILLISECONDS);
+		if( repeatingDelay != null ) {
+			if( delay==null )
+				delay = repeatingDelay;
+			sf = scheduler.scheduleWithFixedDelay(r,delay.longValue(),repeatingDelay.longValue(),TimeUnit.MILLISECONDS);
+		} else if( repeatingRate != null ) {
+			if( delay==null )
+				delay = repeatingRate;
+			sf = scheduler.scheduleWithFixedDelay(r,delay.longValue(),repeatingRate.longValue(),TimeUnit.MILLISECONDS);
+		} else if( delay != null ) {
+			sf = scheduler.schedule(r,delay.longValue(),TimeUnit.MILLISECONDS);
+		} else if( runOnClose ) {
+			Closeable c = new Closeable(){public void close(){
+				scheduler.schedule(r,0L,TimeUnit.MILLISECONDS);
+			}};
+			luan.registry().put(c,c);  // prevent gc
+			luan.onClose(c);
+			return;
 		} else {
-			throw new LuanException("repeating must be nil or 'with_fixed_delay' or 'at_fixed_rate'");
+			scheduler.schedule(r,0L,TimeUnit.MILLISECONDS);
+			return;
 		}
-		final Closeable c = new Closeable(){public void close(){
+		Closeable c = new Closeable(){public void close(){
 			boolean b = sf.cancel(false);
+			if( runOnClose )
+				scheduler.schedule(r,0L,TimeUnit.MILLISECONDS);
 		}};
-		newLuan.registry().put(luan,luan);  // prevent gc
+		if( !daemon )
+			newLuan.registry().put(luan,luan);  // prevent gc
 		luan.registry().put(c,c);  // prevent gc
 		luan.onClose(c);
 	}
@@ -216,4 +235,19 @@
 		callableMap.remove(name);
 	}
 
+
+	public static final ReadWriteLock backupLock = new ReentrantReadWriteLock();
+
+	public static Object runInLock(Lock lock,LuanFunction fn)
+		throws LuanException, InterruptedException
+	{
+		if( !lock.tryLock(10,TimeUnit.MINUTES) )
+			throw new LuanException("failed to acquire lock");
+		try {
+			return fn.call();
+		} finally {
+			lock.unlock();
+		}
+	}
+
 }
--- a/src/luan/modules/host/Hosting.luan	Wed Jun 12 22:16:10 2019 -0600
+++ b/src/luan/modules/host/Hosting.luan	Mon Jun 17 21:50:40 2019 -0600
@@ -47,7 +47,7 @@
 				end
 			end
 			for _, there_child in pairs(there.children) do
-				if host.delete_unused(domain,password,there_child.path)==true then   -- remove ==true later
+				if host.delete_unused(domain,password,there_child.path) then
 					print("deleted "..there_child.name)
 				end
 			end