comparison src/luan/modules/ThreadLuan.java @ 1766:8df0b80e715e

fix scheduled tasks
author Franklin Schmidt <fschmidt@gmail.com>
date Tue, 06 Jun 2023 14:33:24 -0600
parents 7c7f28c724e8
children d3ea0380dfb6
comparison
equal deleted inserted replaced
1765:1ffe1e06ea55 1766:8df0b80e715e
1 package luan.modules; 1 package luan.modules;
2 2
3 import java.io.Closeable; 3 import java.io.Closeable;
4 import java.util.Arrays;
5 import java.util.Iterator; 4 import java.util.Iterator;
6 import java.util.Map; 5 import java.util.Map;
7 import java.util.HashMap; 6 import java.util.HashMap;
8 import java.util.concurrent.Executor; 7 import java.util.concurrent.Executor;
9 import java.util.concurrent.Executors; 8 import java.util.concurrent.Executors;
24 23
25 24
26 public final class ThreadLuan { 25 public final class ThreadLuan {
27 private static final Logger logger = LoggerFactory.getLogger(ThreadLuan.class); 26 private static final Logger logger = LoggerFactory.getLogger(ThreadLuan.class);
28 27
28 public static final String CLOSEABLES = "Luan.closeables";
29 public interface Closeables {
30 public void addCloseable(Closeable c) throws LuanException;
31 }
32
29 private static final Executor exec = Executors.newCachedThreadPool(); 33 private static final Executor exec = Executors.newCachedThreadPool();
30 public static final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1); 34 public static final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
31 35
32 private static Runnable runnable(final Luan luan,final LuanFunction fn) { 36 private static Runnable runnable(final Luan luan,final LuanFunction fn) {
33 return new Runnable() { 37 return new Runnable() {
48 luan = new Luan(luan); 52 luan = new Luan(luan);
49 LuanMutable.makeImmutable(fn); 53 LuanMutable.makeImmutable(fn);
50 exec.execute(runnable(luan,fn)); 54 exec.execute(runnable(luan,fn));
51 } 55 }
52 56
53 private static final Map<String,ScheduledFuture> scheduleds = new WeakCacheMap<String,ScheduledFuture>();
54
55 private static void cancel(ScheduledFuture sf,String src) { 57 private static void cancel(ScheduledFuture sf,String src) {
56 boolean b = sf.cancel(false); 58 boolean b = sf.cancel(false);
57 if( !sf.isCancelled() ) 59 if( !sf.isCancelled() )
58 logger.error(src+" cancel="+b+" isCancelled="+sf.isCancelled()+" isDone="+sf.isDone()+" "+sf); 60 logger.error(src+" cancel="+b+" isCancelled="+sf.isCancelled()+" isDone="+sf.isDone()+" "+sf);
59 } 61 }
80 { 82 {
81 options = new LuanTable(options); 83 options = new LuanTable(options);
82 Number delay = Utils.removeNumber(options,"delay"); 84 Number delay = Utils.removeNumber(options,"delay");
83 Number repeatingDelay = Utils.removeNumber(options,"repeating_delay"); 85 Number repeatingDelay = Utils.removeNumber(options,"repeating_delay");
84 Number repeatingRate = Utils.removeNumber(options,"repeating_rate"); 86 Number repeatingRate = Utils.removeNumber(options,"repeating_rate");
85 Boolean dontGc = Utils.removeBoolean(options,"dont_gc");
86 String id = Utils.removeString(options,"id"); 87 String id = Utils.removeString(options,"id");
88 if( id != null )
89 logger.error("thread option 'id' is obsolete: "+id);
87 if( repeatingDelay!=null && repeatingRate!=null ) 90 if( repeatingDelay!=null && repeatingRate!=null )
88 throw new LuanException("can't define both repeating_delay and repeating_rate"); 91 throw new LuanException("can't define both repeating_delay and repeating_rate");
89 boolean repeating = repeatingDelay!=null || repeatingRate!=null; 92 boolean repeating = repeatingDelay!=null || repeatingRate!=null;
90 Utils.checkEmpty(options); 93 Utils.checkEmpty(options);
91 if( id != null ) {
92 ScheduledFuture sf = scheduleds.remove(id);
93 if( sf != null )
94 cancel(sf,"id "+id);
95 }
96 final Runnable r = runnable(newLuan,fn); 94 final Runnable r = runnable(newLuan,fn);
97 final ScheduledFuture sf; 95 final ScheduledFuture sf;
98 if( repeatingDelay != null ) { 96 if( repeatingDelay != null ) {
99 if( delay==null ) 97 if( delay==null )
100 delay = repeatingDelay; 98 delay = repeatingDelay;
107 sf = scheduler.schedule(r,delay.longValue(),TimeUnit.MILLISECONDS); 105 sf = scheduler.schedule(r,delay.longValue(),TimeUnit.MILLISECONDS);
108 } else { 106 } else {
109 scheduler.schedule(r,0L,TimeUnit.MILLISECONDS); 107 scheduler.schedule(r,0L,TimeUnit.MILLISECONDS);
110 return; 108 return;
111 } 109 }
112 if( !Boolean.TRUE.equals(dontGc) ) { 110 Closeables cs = (Closeables)luan.registry().get(CLOSEABLES);
113 Object c = new Object() { 111 if( cs != null ) {
112 Closeable cl = new Closeable() {
113 public void close() {
114 cancel(sf,"close");
115 }
114 protected void finalize() throws Throwable { 116 protected void finalize() throws Throwable {
115 cancel(sf,"gc"); 117 cancel(sf,"gc"); // cancel on gc
116 } 118 }
117 }; 119 };
118 luan.registry().put(c,c); // cancel on gc 120 cs.addCloseable(cl);
119 } 121 }
120 if( id != null )
121 scheduleds.put(id,sf);
122 } 122 }
123 123
124 124
125 public static void sleep(long millis) throws InterruptedException { 125 public static void sleep(long millis) throws InterruptedException {
126 Thread.sleep(millis); 126 Thread.sleep(millis);