static class ReliableSingleThread implements Runnable { O runnable; S name = "Single Thread"; bool cancelBeforeTrigger; // always cancel running thread and wait for it to end before starting new operation F0 enter; // optional ownership marker, e.g. for DynModules int cancelTimeOut = 10000; bool trigger; Thread thread; WeakReference threadBeingCancelled; *(O *runnable) {} void trigger() { go(); } synchronized void go() { if (cancelBeforeTrigger) cancel(); trigger = true; if (!running()) { temp callF(enter); thread = startThread(name, r { temp callF(enter); _run(); }); } } public void run() { go(); } void get() { go(); } // so you can use the ! syntax synchronized bool running() { ret thread != null; } // use only if this is the last time you trigger this void triggerAndWait() { trigger(); waitUntilDone(); } void waitUntilDone { while (running()) sleep(1); } void _run() ctex { while licensed { Thread oldThread; synchronized(this) { if (!trigger) { thread = null; break; } oldThread = getWeakRef(threadBeingCancelled); trigger = false; } if (oldThread != null && oldThread != currentThread()) oldThread.join(cancelTimeOut); pcallF(runnable); } } synchronized void cancel() { if (thread == null) ret; threadBeingCancelled = new WeakReference(thread); cancelAndInterruptThread(thread); thread = null; } void cancelAndTrigger() { cancel(); trigger(); } synchronized bool triggered() { ret trigger; } void cleanMeUp { cancel(); } selfType cancelBeforeTrigger() { cancelBeforeTrigger = true; this; } }