Mercurial Hosting > luan
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 |