comparison 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
comparison
equal deleted inserted replaced
1400:221eedb0f54e 1401:ef1620aa99cb
4 import java.util.Arrays; 4 import java.util.Arrays;
5 import java.util.Iterator; 5 import java.util.Iterator;
6 import java.util.Map; 6 import java.util.Map;
7 import java.util.HashMap; 7 import java.util.HashMap;
8 import java.util.LinkedHashMap; 8 import java.util.LinkedHashMap;
9 import java.lang.ref.Reference;
10 import java.lang.ref.WeakReference;
9 import java.util.concurrent.Executor; 11 import java.util.concurrent.Executor;
10 import java.util.concurrent.Executors; 12 import java.util.concurrent.Executors;
11 import java.util.concurrent.ScheduledExecutorService; 13 import java.util.concurrent.ScheduledExecutorService;
12 import java.util.concurrent.ScheduledFuture; 14 import java.util.concurrent.ScheduledFuture;
13 import java.util.concurrent.TimeUnit; 15 import java.util.concurrent.TimeUnit;
16 import java.util.concurrent.ConcurrentHashMap;
14 import java.util.concurrent.locks.Lock; 17 import java.util.concurrent.locks.Lock;
15 import java.util.concurrent.locks.ReadWriteLock; 18 import java.util.concurrent.locks.ReadWriteLock;
16 import java.util.concurrent.locks.ReentrantLock; 19 import java.util.concurrent.locks.ReentrantLock;
17 import java.util.concurrent.locks.ReentrantReadWriteLock; 20 import java.util.concurrent.locks.ReentrantReadWriteLock;
18 import luan.Luan; 21 import luan.Luan;
19 import luan.LuanFunction; 22 import luan.LuanFunction;
20 import luan.LuanTable; 23 import luan.LuanTable;
21 import luan.LuanException; 24 import luan.LuanException;
22 import luan.LuanCloner; 25 import luan.LuanCloner;
23 import luan.LuanCloneable; 26 import luan.LuanCloneable;
27 import luan.lib.logging.Logger;
28 import luan.lib.logging.LoggerFactory;
24 29
25 30
26 public final class ThreadLuan { 31 public final class ThreadLuan {
32 private static final Logger logger = LoggerFactory.getLogger(ThreadLuan.class);
33
27 private static final Executor exec = Executors.newCachedThreadPool(); 34 private static final Executor exec = Executors.newCachedThreadPool();
28 public static final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1); 35 public static final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
29 36
30 private static Runnable runnable(final LuanFunction fn) { 37 private static Runnable runnable(final LuanFunction fn) {
31 return new Runnable() { 38 return new Runnable() {
43 LuanCloner cloner = new LuanCloner(LuanCloner.Type.COMPLETE); 50 LuanCloner cloner = new LuanCloner(LuanCloner.Type.COMPLETE);
44 final LuanFunction newFn = (LuanFunction)cloner.get(fn); 51 final LuanFunction newFn = (LuanFunction)cloner.get(fn);
45 exec.execute(runnable(newFn)); 52 exec.execute(runnable(newFn));
46 } 53 }
47 54
55 private static Map<String,Reference<ScheduledFuture>> scheduleds = new ConcurrentHashMap<String,Reference<ScheduledFuture>>();
56
48 public static void schedule(LuanFunction fn,LuanTable options) 57 public static void schedule(LuanFunction fn,LuanTable options)
49 throws LuanException 58 throws LuanException
50 { 59 {
51 Map map = options.asMap(); 60 Map map = options.asMap();
52 Number delay = Utils.removeNumber(map,"delay"); 61 Number delay = Utils.removeNumber(map,"delay");
53 Number repeatingDelay = Utils.removeNumber(map,"repeating_delay"); 62 Number repeatingDelay = Utils.removeNumber(map,"repeating_delay");
54 Number repeatingRate = Utils.removeNumber(map,"repeating_rate"); 63 Number repeatingRate = Utils.removeNumber(map,"repeating_rate");
55 boolean daemon = Boolean.TRUE.equals(Utils.removeBoolean(map,"daemon")); 64 String id = Utils.removeString(map,"id");
56 final boolean runOnClose = Boolean.TRUE.equals(Utils.removeBoolean(map,"run_on_close"));
57 if( repeatingDelay!=null && repeatingRate!=null ) 65 if( repeatingDelay!=null && repeatingRate!=null )
58 throw new LuanException("can't define both repeating_delay and repeating_rate"); 66 throw new LuanException("can't define both repeating_delay and repeating_rate");
59 boolean repeating = repeatingDelay!=null || repeatingRate!=null; 67 boolean repeating = repeatingDelay!=null || repeatingRate!=null;
60 Utils.checkEmpty(map); 68 Utils.checkEmpty(map);
69 if( id != null ) {
70 Reference<ScheduledFuture> ref = scheduleds.remove(id);
71 if( ref != null ) {
72 ScheduledFuture sf = ref.get();
73 if( sf != null )
74 sf.cancel(false);
75 }
76 }
61 Luan luan = fn.luan(); 77 Luan luan = fn.luan();
62 LuanCloner cloner = new LuanCloner(LuanCloner.Type.COMPLETE); 78 LuanCloner cloner = new LuanCloner(LuanCloner.Type.COMPLETE);
63 final Luan newLuan = (Luan)cloner.clone(luan); 79 final Luan newLuan = (Luan)cloner.clone(luan);
64 final LuanFunction newFn = (LuanFunction)cloner.get(fn); 80 final LuanFunction newFn = (LuanFunction)cloner.get(fn);
65 final Runnable r = runnable(newFn); 81 final Runnable r = runnable(newFn);
72 if( delay==null ) 88 if( delay==null )
73 delay = repeatingRate; 89 delay = repeatingRate;
74 sf = scheduler.scheduleWithFixedDelay(r,delay.longValue(),repeatingRate.longValue(),TimeUnit.MILLISECONDS); 90 sf = scheduler.scheduleWithFixedDelay(r,delay.longValue(),repeatingRate.longValue(),TimeUnit.MILLISECONDS);
75 } else if( delay != null ) { 91 } else if( delay != null ) {
76 sf = scheduler.schedule(r,delay.longValue(),TimeUnit.MILLISECONDS); 92 sf = scheduler.schedule(r,delay.longValue(),TimeUnit.MILLISECONDS);
77 } else if( runOnClose ) {
78 Closeable c = new Closeable(){public void close(){
79 scheduler.schedule(r,0L,TimeUnit.MILLISECONDS);
80 }};
81 luan.registry().put(c,c); // prevent gc
82 luan.onClose(c);
83 return;
84 } else { 93 } else {
85 scheduler.schedule(r,0L,TimeUnit.MILLISECONDS); 94 scheduler.schedule(r,0L,TimeUnit.MILLISECONDS);
86 return; 95 return;
87 } 96 }
88 Closeable c = new Closeable(){public void close(){ 97 Object c = new Object() {
89 boolean b = sf.cancel(false); 98 protected void finalize() throws Throwable {
90 if( runOnClose ) 99 sf.cancel(false);
91 scheduler.schedule(r,0L,TimeUnit.MILLISECONDS); 100 }
92 }}; 101 };
93 if( !daemon ) 102 luan.registry().put(c,c); // cancel on gc
94 newLuan.registry().put(luan,luan); // prevent gc 103 if( id != null )
95 luan.registry().put(c,c); // prevent gc 104 scheduleds.put(id,new WeakReference<ScheduledFuture>(sf));
96 luan.onClose(c);
97 } 105 }
98 106
99 /* 107 /*
100 public static class GlobalMap { 108 public static class GlobalMap {
101 109