diff src/luan/modules/ThreadLuan.java @ 1401:ef1620aa99cb

fix gc issues
author Franklin Schmidt <fschmidt@gmail.com>
date Mon, 16 Sep 2019 22:51:41 -0400
parents eb8b35dccd99
children 27efb1fcbcb5
line wrap: on
line diff
--- a/src/luan/modules/ThreadLuan.java	Fri Sep 13 05:05:51 2019 -0600
+++ b/src/luan/modules/ThreadLuan.java	Mon Sep 16 22:51:41 2019 -0400
@@ -6,11 +6,14 @@
 import java.util.Map;
 import java.util.HashMap;
 import java.util.LinkedHashMap;
+import java.lang.ref.Reference;
+import java.lang.ref.WeakReference;
 import java.util.concurrent.Executor;
 import java.util.concurrent.Executors;
 import java.util.concurrent.ScheduledExecutorService;
 import java.util.concurrent.ScheduledFuture;
 import java.util.concurrent.TimeUnit;
+import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.locks.Lock;
 import java.util.concurrent.locks.ReadWriteLock;
 import java.util.concurrent.locks.ReentrantLock;
@@ -21,9 +24,13 @@
 import luan.LuanException;
 import luan.LuanCloner;
 import luan.LuanCloneable;
+import luan.lib.logging.Logger;
+import luan.lib.logging.LoggerFactory;
 
 
 public final class ThreadLuan {
+	private static final Logger logger = LoggerFactory.getLogger(ThreadLuan.class);
+
 	private static final Executor exec = Executors.newCachedThreadPool();
 	public static final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
 
@@ -45,6 +52,8 @@
 		exec.execute(runnable(newFn));
 	}
 
+	private static Map<String,Reference<ScheduledFuture>> scheduleds = new ConcurrentHashMap<String,Reference<ScheduledFuture>>();
+
 	public static void schedule(LuanFunction fn,LuanTable options)
 		throws LuanException
 	{
@@ -52,12 +61,19 @@
 		Number delay = Utils.removeNumber(map,"delay");
 		Number repeatingDelay = Utils.removeNumber(map,"repeating_delay");
 		Number repeatingRate = Utils.removeNumber(map,"repeating_rate");
-		boolean daemon = Boolean.TRUE.equals(Utils.removeBoolean(map,"daemon"));
-		final boolean runOnClose = Boolean.TRUE.equals(Utils.removeBoolean(map,"run_on_close"));
+		String id = Utils.removeString(map,"id");
 		if( repeatingDelay!=null && repeatingRate!=null )
 			throw new LuanException("can't define both repeating_delay and repeating_rate");
 		boolean repeating = repeatingDelay!=null || repeatingRate!=null;
 		Utils.checkEmpty(map);
+		if( id != null ) {
+			Reference<ScheduledFuture> ref = scheduleds.remove(id);
+			if( ref != null ) {
+				ScheduledFuture sf = ref.get();
+				if( sf != null )
+					sf.cancel(false);
+			}
+		}
 		Luan luan = fn.luan();
 		LuanCloner cloner = new LuanCloner(LuanCloner.Type.COMPLETE);
 		final Luan newLuan = (Luan)cloner.clone(luan);
@@ -74,26 +90,18 @@
 			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 {
 			scheduler.schedule(r,0L,TimeUnit.MILLISECONDS);
 			return;
 		}
-		Closeable c = new Closeable(){public void close(){
-			boolean b = sf.cancel(false);
-			if( runOnClose )
-				scheduler.schedule(r,0L,TimeUnit.MILLISECONDS);
-		}};
-		if( !daemon )
-			newLuan.registry().put(luan,luan);  // prevent gc
-		luan.registry().put(c,c);  // prevent gc
-		luan.onClose(c);
+		Object c = new Object() {
+			protected void finalize() throws Throwable {
+				sf.cancel(false);
+			}
+		};
+		luan.registry().put(c,c);  // cancel on gc
+		if( id != null )
+			scheduleds.put(id,new WeakReference<ScheduledFuture>(sf));
 	}
 
 /*