1 /*
2  * Hunt - A refined core library for D programming language.
3  *
4  * Copyright (C) 2018-2019 HuntLabs
5  *
6  * Website: https://www.huntlabs.net/
7  *
8  * Licensed under the Apache-2.0 License.
9  *
10  */
11 
12 module hunt.concurrency.thread.ThreadEx;
13 
14 import hunt.concurrency.thread.LockSupport;
15 
16 import hunt.Exceptions;
17 import hunt.Functions;
18 import hunt.logging;
19 import hunt.system.Memory;
20 import hunt.util.Common;
21 import hunt.util.DateTime;
22 import hunt.util.Runnable;
23 
24 import core.atomic;
25 import core.thread;
26 import core.time;
27 import core.sync.condition;
28 import core.sync.mutex;
29 
30 import std.algorithm: min, max;
31 import std.conv: to;
32 
33 
34 /**
35 */
36 interface Interruptible {
37     void interrupt(Thread t);
38 }
39 
40 
41 /**
42  * Interface for handlers invoked when a {@code Thread} abruptly
43  * terminates due to an uncaught exception.
44  * <p>When a thread is about to terminate due to an uncaught exception
45  * the Java Virtual Machine will query the thread for its
46  * {@code UncaughtExceptionHandler} using
47  * {@link #getUncaughtExceptionHandler} and will invoke the handler's
48  * {@code uncaughtException} method, passing the thread and the
49  * exception as arguments.
50  * If a thread has not had its {@code UncaughtExceptionHandler}
51  * explicitly set, then its {@code ThreadGroupEx} object acts as its
52  * {@code UncaughtExceptionHandler}. If the {@code ThreadGroupEx} object
53  * has no
54  * special requirements for dealing with the exception, it can forward
55  * the invocation to the {@linkplain #getDefaultUncaughtExceptionHandler
56  * default uncaught exception handler}.
57  *
58  * @see #setDefaultUncaughtExceptionHandler
59  * @see #setUncaughtExceptionHandler
60  * @see ThreadGroupEx#uncaughtException
61  */
62 interface UncaughtExceptionHandler {
63     /**
64      * Method invoked when the given thread terminates due to the
65      * given uncaught exception.
66      * <p>Any exception thrown by this method will be ignored by the
67      * Java Virtual Machine.
68      * @param t the thread
69      * @param e the exception
70      */
71     void uncaughtException(Thread t, Throwable e);
72 }
73 
74 
75 /**
76  * A thread state.  A thread can be in one of the following states:
77  * <ul>
78  * <li>{@link #NEW}<br>
79  *     A thread that has not yet started is in this state.
80  *     </li>
81  * <li>{@link #RUNNABLE}<br>
82  *     A thread executing in the Java virtual machine is in this state.
83  *     </li>
84  * <li>{@link #BLOCKED}<br>
85  *     A thread that is blocked waiting for a monitor lock
86  *     is in this state.
87  *     </li>
88  * <li>{@link #WAITING}<br>
89  *     A thread that is waiting indefinitely for another thread to
90  *     perform a particular action is in this state.
91  *     </li>
92  * <li>{@link #TIMED_WAITING}<br>
93  *     A thread that is waiting for another thread to perform an action
94  *     for up to a specified waiting time is in this state.
95  *     </li>
96  * <li>{@link #TERMINATED}<br>
97  *     A thread that has exited is in this state.
98  *     </li>
99  * </ul>
100  *
101  * <p>
102  * A thread can be in only one state at a given point in time.
103  * These states are virtual machine states which do not reflect
104  * any operating system thread states.
105  *
106  * @see #getState
107  */
108 enum ThreadState {
109     /**
110      * Thread state for a thread which has not yet started.
111      */
112     NEW,
113 
114     /**
115      * Thread state for a runnable thread.  A thread in the runnable
116      * state is executing in the Java virtual machine but it may
117      * be waiting for other resources from the operating system
118      * such as processor.
119      */
120     RUNNABLE,
121 
122     /**
123      * Thread state for a thread blocked waiting for a monitor lock.
124      * A thread in the blocked state is waiting for a monitor lock
125      * to enter a synchronized block/method or
126      * reenter a synchronized block/method after calling
127      * {@link Object#wait() Object.wait}.
128      */
129     BLOCKED,
130 
131     /**
132      * Thread state for a waiting thread.
133      * A thread is in the waiting state due to calling one of the
134      * following methods:
135      * <ul>
136      *   <li>{@link Object#wait() Object.wait} with no timeout</li>
137      *   <li>{@link #join() Thread.join} with no timeout</li>
138      *   <li>{@link LockSupport#park() LockSupport.park}</li>
139      * </ul>
140      *
141      * <p>A thread in the waiting state is waiting for another thread to
142      * perform a particular action.
143      *
144      * For example, a thread that has called {@code Object.wait()}
145      * on an object is waiting for another thread to call
146      * {@code Object.notify()} or {@code Object.notifyAll()} on
147      * that object. A thread that has called {@code Thread.join()}
148      * is waiting for a specified thread to terminate.
149      */
150     WAITING,
151 
152     /**
153      * Thread state for a waiting thread with a specified waiting time.
154      * A thread is in the timed waiting state due to calling one of
155      * the following methods with a specified positive waiting time:
156      * <ul>
157      *   <li>{@link #sleep Thread.sleep}</li>
158      *   <li>{@link Object#wait(long) Object.wait} with timeout</li>
159      *   <li>{@link #join(long) Thread.join} with timeout</li>
160      *   <li>{@link LockSupport#parkNanos LockSupport.parkNanos}</li>
161      *   <li>{@link LockSupport#parkUntil LockSupport.parkUntil}</li>
162      * </ul>
163      */
164     TIMED_WAITING,
165 
166     /**
167      * Thread state for a terminated thread.
168      * The thread has completed execution.
169      */
170     TERMINATED
171 }
172 
173 
174 /**
175  * A <i>thread</i> is a thread of execution in a program. The Java
176  * Virtual Machine allows an application to have multiple threads of
177  * execution running concurrently.
178  * <p>
179  * Every thread has a priority. Threads with higher priority are
180  * executed in preference to threads with lower priority. Each thread
181  * may or may not also be marked as a daemon. When code running in
182  * some thread creates a new {@code Thread} object, the new
183  * thread has its priority initially set equal to the priority of the
184  * creating thread, and is a daemon thread if and only if the
185  * creating thread is a daemon.
186  * <p>
187  * When a Java Virtual Machine starts up, there is usually a single
188  * non-daemon thread (which typically calls the method named
189  * {@code main} of some designated class). The Java Virtual
190  * Machine continues to execute threads until either of the following
191  * occurs:
192  * <ul>
193  * <li>The {@code exit} method of class {@code Runtime} has been
194  *     called and the security manager has permitted the exit operation
195  *     to take place.
196  * <li>All threads that are not daemon threads have died, either by
197  *     returning from the call to the {@code run} method or by
198  *     throwing an exception that propagates beyond the {@code run}
199  *     method.
200  * </ul>
201  * <p>
202  * There are two ways to create a new thread of execution. One is to
203  * declare a class to be a subclass of {@code Thread}. This
204  * subclass should override the {@code run} method of class
205  * {@code Thread}. An instance of the subclass can then be
206  * allocated and started. For example, a thread that computes primes
207  * larger than a stated value could be written as follows:
208  * <hr><blockquote><pre>
209  *     class PrimeThread extends Thread {
210  *         long minPrime;
211  *         PrimeThread(long minPrime) {
212  *             this.minPrime = minPrime;
213  *         }
214  *
215  *         public void run() {
216  *             // compute primes larger than minPrime
217  *             &nbsp;.&nbsp;.&nbsp;.
218  *         }
219  *     }
220  * </pre></blockquote><hr>
221  * <p>
222  * The following code would then create a thread and start it running:
223  * <blockquote><pre>
224  *     PrimeThread p = new PrimeThread(143);
225  *     p.start();
226  * </pre></blockquote>
227  * <p>
228  * The other way to create a thread is to declare a class that
229  * implements the {@code Runnable} interface. That class then
230  * implements the {@code run} method. An instance of the class can
231  * then be allocated, passed as an argument when creating
232  * {@code Thread}, and started. The same example in this other
233  * style looks like the following:
234  * <hr><blockquote><pre>
235  *     class PrimeRun implements Runnable {
236  *         long minPrime;
237  *         PrimeRun(long minPrime) {
238  *             this.minPrime = minPrime;
239  *         }
240  *
241  *         public void run() {
242  *             // compute primes larger than minPrime
243  *             &nbsp;.&nbsp;.&nbsp;.
244  *         }
245  *     }
246  * </pre></blockquote><hr>
247  * <p>
248  * The following code would then create a thread and start it running:
249  * <blockquote><pre>
250  *     PrimeRun p = new PrimeRun(143);
251  *     new Thread(p).start();
252  * </pre></blockquote>
253  * <p>
254  * Every thread has a name for identification purposes. More than
255  * one thread may have the same name. If a name is not specified when
256  * a thread is created, a new name is generated for it.
257  * <p>
258  * Unless otherwise noted, passing a {@code null} argument to a constructor
259  * or method in this class will cause a {@link NullPointerException} to be
260  * thrown.
261  *
262  */
263 class ThreadEx : Thread, Runnable {
264 
265     /* What will be run. */
266     private Runnable target;
267 
268     // Object parkBlocker;
269     ThreadState state;
270     
271 
272     /* The object in which this thread is blocked in an interruptible I/O
273      * operation, if any.  The blocker's interrupt method should be invoked
274      * after setting this thread's interrupt status.
275      */
276     private Interruptible blocker;
277     private Object blockerLock;
278     private shared bool _interrupted;     // Thread.isInterrupted state
279     
280     /* For autonumbering anonymous threads. */
281     private static shared int threadInitNumber;
282     private static int nextThreadNum() {
283         return core.atomic.atomicOp!"+="(threadInitNumber, 1);
284     }
285 
286     this() {
287         this(null, null, "Thread-" ~ nextThreadNum().to!string());
288     }
289 
290     this(string name) {
291         this(null, null, name);
292     }
293 
294     this(Runnable target) {
295         this(null, target, "Thread-" ~ nextThreadNum().to!string());
296     }
297 
298     this(Runnable target, string name) {
299         this(null, target, name);
300     }
301 
302     this(ThreadGroupEx group,  string name) {
303         this(group, null, name);
304     }
305 
306     this(ThreadGroupEx group, Runnable target, string name,  size_t sz = 0) {
307         this.name = name;
308         this.group = group;
309         this.target = target;
310         super(&run, sz);
311         initialize();
312     }
313 
314     this(Action dg, string name) {
315         this(new class Runnable {
316             void run() { dg();}
317         }, name);
318     }
319 
320     this(Action dg) {
321         this(new class Runnable {
322             void run() { dg();}
323         });
324     }
325 
326     this(void function() fn) {
327         this(new class Runnable {
328             void run() { fn();}
329         });
330     }
331 
332     ~this() {
333         blocker = null;
334         blockerLock = null;
335         // parkBlocker = null;
336         target = null;
337         _parker = null;
338     }
339 
340     private void initialize() nothrow {
341         _parker = Parker.allocate(this);
342         blockerLock = new Object();
343         state = ThreadState.NEW;
344     }
345 
346     
347     /**
348      * Returns the thread group to which this thread belongs.
349      * This method returns null if this thread has died
350      * (been stopped).
351      *
352      * @return  this thread's thread group.
353      */
354     final ThreadGroupEx getThreadGroup() {
355         return group;
356     }
357 
358     /* The group of this thread */
359     private ThreadGroupEx group;
360 
361     /**
362      * If this thread was constructed using a separate
363      * {@code Runnable} run object, then that
364      * {@code Runnable} object's {@code run} method is called;
365      * otherwise, this method does nothing and returns.
366      * <p>
367      * Subclasses of {@code Thread} should override this method.
368      *
369      * @see     #start()
370      * @see     #stop()
371      * @see     #Thread(ThreadGroup, Runnable, String)
372      * See_also:
373      *  https://stackoverflow.com/questions/8579657/whats-the-difference-between-thread-start-and-runnable-run
374      */
375     void run() {
376         version(HUNT_CONCURRENCY_DEBUG_MORE) {
377             infof("trying to run a target %s...", target is null ? "(null)" : "");
378         }
379         if (target !is null) {
380             target.run();
381         }
382     }
383 
384 
385 
386      /**
387      * Tests if this thread is alive. A thread is alive if it has
388      * been started and has not yet died.
389      *
390      * @return  <code>true</code> if this thread is alive;
391      *          <code>false</code> otherwise.
392      */
393     final bool isAlive() {
394         // TODO: Tasks pending completion -@zxp at 11/7/2018, 10:30:43 AM
395         // 
396         return isRunning();
397     }
398 
399 
400     /**
401      * Marks this thread as either a {@linkplain #isDaemon daemon} thread
402      * or a user thread. The Java Virtual Machine exits when the only
403      * threads running are all daemon threads.
404      *
405      * <p> This method must be invoked before the thread is started.
406      *
407      * @param  on
408      *         if {@code true}, marks this thread as a daemon thread
409      *
410      * @throws  IllegalThreadStateException
411      *          if this thread is {@linkplain #isAlive alive}
412      *
413      * @throws  SecurityException
414      *          if {@link #checkAccess} determines that the current
415      *          thread cannot modify this thread
416      */
417     final void setDaemon(bool on) {
418         if (isAlive()) {
419             throw new IllegalThreadStateException();
420         }
421         isDaemon(on);
422     }
423 
424     /**
425      * Returns the state of this thread.
426      * This method is designed for use in monitoring of the system state,
427      * not for synchronization control.
428      *
429      * @return this thread's state.
430      */
431     ThreadState getState() {
432         // get current thread state
433         // return jdk.internal.misc.VM.toThreadState(threadStatus);
434         return state;
435     }
436 
437     /* Set the blocker field; invoked via sun.misc.SharedSecrets from java.nio code
438      */
439     void blockedOn(Interruptible b) {
440         synchronized (blockerLock) {
441             blocker = b;
442         }
443     }
444 
445     /**
446      * Interrupts this thread.
447      *
448      * <p> Unless the current thread is interrupting itself, which is
449      * always permitted, the {@link #checkAccess() checkAccess} method
450      * of this thread is invoked, which may cause a {@link
451      * SecurityException} to be thrown.
452      *
453      * <p> If this thread is blocked in an invocation of the {@link
454      * Object#wait() wait()}, {@link Object#wait(long) wait(long)}, or {@link
455      * Object#wait(long, int) wait(long, int)} methods of the {@link Object}
456      * class, or of the {@link #join()}, {@link #join(long)}, {@link
457      * #join(long, int)}, {@link #sleep(long)}, or {@link #sleep(long, int)},
458      * methods of this class, then its interrupt status will be cleared and it
459      * will receive an {@link InterruptedException}.
460      *
461      * <p> If this thread is blocked in an I/O operation upon an {@link
462      * java.nio.channels.InterruptibleChannel InterruptibleChannel}
463      * then the channel will be closed, the thread's interrupt
464      * status will be set, and the thread will receive a {@link
465      * java.nio.channels.ClosedByInterruptException}.
466      *
467      * <p> If this thread is blocked in a {@link java.nio.channels.Selector}
468      * then the thread's interrupt status will be set and it will return
469      * immediately from the selection operation, possibly with a non-zero
470      * value, just as if the selector's {@link
471      * java.nio.channels.Selector#wakeup wakeup} method were invoked.
472      *
473      * <p> If none of the previous conditions hold then this thread's interrupt
474      * status will be set. </p>
475      *
476      * <p> Interrupting a thread that is not alive need not have any effect.
477      *
478      * @throws  SecurityException
479      *          if the current thread cannot modify this thread
480      *
481      * @revised 6.0
482      * @spec JSR-51
483      */
484     void interrupt() {
485         synchronized (blockerLock) {
486             Interruptible b = blocker;
487             if (b !is null) {
488                 interrupt0();           // Just to set the interrupt flag
489                 b.interrupt(this);
490                 return;
491             }
492         }
493         interrupt0();
494     }
495 
496     private void interrupt0() {
497         if(!_interrupted) {
498             _interrupted = true;
499             // More than one thread can get here with the same value of osthread,
500             // resulting in multiple notifications.  We do, however, want the store
501             // to interrupted() to be visible to other threads before we execute unpark().
502             // OrderAccess::fence();
503             // ParkEvent * const slp = thread->_SleepEvent ;
504             // if (slp != NULL) slp->unpark() ;
505         }
506 
507         // For JSR166. Unpark even if interrupt status already was set
508         _parker.unpark();
509         // LockSupport.unpark();
510 
511         // ParkEvent * ev = thread->_ParkEvent ;
512         // if (ev != NULL) ev->unpark() ;
513     }
514 
515     /**
516      * Tests whether this thread has been interrupted.  The <i>interrupted
517      * status</i> of the thread is unaffected by this method.
518      *
519      * <p>A thread interruption ignored because a thread was not alive
520      * at the time of the interrupt will be reflected by this method
521      * returning false.
522      *
523      * @return  <code>true</code> if this thread has been interrupted;
524      *          <code>false</code> otherwise.
525      * @see     #interrupted()
526      * @revised 6.0
527      */
528     bool isInterrupted() {
529         return isInterrupted(false);
530     }
531 
532 
533     /**
534      * Tests whether the current thread has been interrupted.  The
535      * <i>interrupted status</i> of the thread is cleared by this method.  In
536      * other words, if this method were to be called twice in succession, the
537      * second call would return false (unless the current thread were
538      * interrupted again, after the first call had cleared its interrupted
539      * status and before the second call had examined it).
540      *
541      * <p>A thread interruption ignored because a thread was not alive
542      * at the time of the interrupt will be reflected by this method
543      * returning false.
544      *
545      * @return  <code>true</code> if the current thread has been interrupted;
546      *          <code>false</code> otherwise.
547      * @see #isInterrupted()
548      * @revised 6.0
549      */
550     static bool interrupted() {
551         ThreadEx tex = cast(ThreadEx) Thread.getThis();
552         if(tex is null)
553             return false;
554 
555         return tex.isInterrupted(true);
556     }
557 
558     /**
559      * Tests if some Thread has been interrupted.  The interrupted state
560      * is reset or not based on the value of ClearInterrupted that is
561      * passed.
562      */
563     private bool isInterrupted(bool canClear) {
564         // bool interrupted = osthread->interrupted();
565 
566         // NOTE that since there is no "lock" around the interrupt and
567         // is_interrupted operations, there is the possibility that the
568         // interrupted flag (in osThread) will be "false" but that the
569         // low-level events will be in the signaled state. This is
570         // intentional. The effect of this is that Object.wait() and
571         // LockSupport.park() will appear to have a spurious wakeup, which
572         // is allowed and not harmful, and the possibility is so rare that
573         // it is not worth the added complexity to add yet another lock.
574         // For the sleep event an explicit reset is performed on entry
575         // to os::sleep, so there is no early return. It has also been
576         // recommended not to put the interrupted flag into the "event"
577         // structure because it hides the issue.
578         if (_interrupted && canClear) {
579             _interrupted = false;
580             // consider thread->_SleepEvent->reset() ... optional optimization
581         }
582 
583         return _interrupted;
584     }
585 
586     static ThreadEx currentThread() {
587         ThreadEx tex = cast(ThreadEx) Thread.getThis();
588         assert(tex !is null, "Must be a ThreadEx");
589         return tex;
590     }
591 
592 
593     Parker parker() {
594         return _parker;
595     }
596     private Parker _parker;
597 
598     // Short sleep, direct OS call.
599     static void nakedSleep(Duration timeout) {
600         Thread.sleep(timeout);
601     }
602 
603     // Sleep forever; naked call to OS-specific sleep; use with CAUTION
604     static void infiniteSleep() {
605         while (true) {    // sleep forever ...
606             Thread.sleep(100.seconds);   // ... 100 seconds at a time
607         }
608     }
609 
610     static void sleep(Duration timeout) {
611         // TODO: Tasks pending completion -@zxp at 11/6/2018, 12:29:22 PM
612         // using ParkEvent
613         LockSupport.park(timeout);
614     }
615 
616     // Low-level leaf-lock primitives used to implement synchronization
617     // and native monitor-mutex infrastructure.
618     // Not for general synchronization use.
619     private static void spinAcquire(shared(int)* adr, string name) nothrow  {
620         int last = *adr;
621         cas(adr, 0, 1);
622         if (last == 0) return; // normal fast-path return
623 
624         // Slow-path : We've encountered contention -- Spin/Yield/Block strategy.
625         //   TEVENT(SpinAcquire - ctx);
626         int ctr = 0;
627         int yields = 0;
628         for (;;) {
629             while (*adr != 0) {
630                 ++ctr;
631                 if ((ctr & 0xFFF) == 0 && !is_MP()) {
632                     if (yields > 5) {
633                         Thread.sleep(1.msecs);
634                     } else {
635                         Thread.yield();
636                         ++yields;
637                     }
638                 } else {
639                     spinPause();
640                 }
641             }
642             last = *adr;
643             cas(adr, 1, 0);
644             if (last == 0) return;
645         }
646     }
647 
648     private static void spinRelease(shared(int)* adr) @safe nothrow @nogc {
649         assert(*adr != 0, "invariant");
650         atomicFence(); // guarantee at least release consistency.
651         // Roach-motel semantics.
652         // It's safe if subsequent LDs and STs float "up" into the critical section,
653         // but prior LDs and STs within the critical section can't be allowed
654         // to reorder or float past the ST that releases the lock.
655         // Loads and stores in the critical section - which appear in program
656         // order before the store that releases the lock - must also appear
657         // before the store that releases the lock in memory visibility order.
658         // Conceptually we need a #loadstore|#storestore "release" MEMBAR before
659         // the ST of 0 into the lock-word which releases the lock, so fence
660         // more than covers this on all platforms.
661         *adr = 0;
662     }
663 
664     //   static void muxAcquire(shared intptr_t * Lock, string Name);
665     // //   static void muxAcquireW(shared intptr_t * Lock, ParkEvent * ev);
666     //   static void muxRelease(shared intptr_t * Lock);
667 
668     private static int spinPause() @safe nothrow @nogc {
669         version (X86_64) {
670             return 0;
671         }
672         else version (AsmX86_Windows) {
673             asm pure nothrow @nogc {
674                 pause;
675             }
676             return 1;
677         }
678         else {
679             return -1;
680         }
681     }
682 
683     private static bool is_MP() @safe pure nothrow @nogc {
684         // During bootstrap if _processor_count is not yet initialized
685         // we claim to be MP as that is safest. If any platform has a
686         // stub generator that might be triggered in this phase and for
687         // which being declared MP when in fact not, is a problem - then
688         // the bootstrap routine for the stub generator needs to check
689         // the processor count directly and leave the bootstrap routine
690         // in place until called after initialization has ocurred.
691         // return (_processor_count != 1); // AssumeMP || 
692         return totalCPUs != 1;
693     }
694 
695     
696     
697     // null unless explicitly set
698     private UncaughtExceptionHandler uncaughtExceptionHandler;
699 
700     // null unless explicitly set
701     private __gshared UncaughtExceptionHandler defaultUncaughtExceptionHandler;
702 
703     /**
704      * Set the default handler invoked when a thread abruptly terminates
705      * due to an uncaught exception, and no other handler has been defined
706      * for that thread.
707      *
708      * <p>Uncaught exception handling is controlled first by the thread, then
709      * by the thread's {@link ThreadGroup} object and finally by the default
710      * uncaught exception handler. If the thread does not have an explicit
711      * uncaught exception handler set, and the thread's thread group
712      * (including parent thread groups)  does not specialize its
713      * {@code uncaughtException} method, then the default handler's
714      * {@code uncaughtException} method will be invoked.
715      * <p>By setting the default uncaught exception handler, an application
716      * can change the way in which uncaught exceptions are handled (such as
717      * logging to a specific device, or file) for those threads that would
718      * already accept whatever &quot;default&quot; behavior the system
719      * provided.
720      *
721      * <p>Note that the default uncaught exception handler should not usually
722      * defer to the thread's {@code ThreadGroup} object, as that could cause
723      * infinite recursion.
724      *
725      * @param eh the object to use as the default uncaught exception handler.
726      * If {@code null} then there is no default handler.
727      *
728      * @throws SecurityException if a security manager is present and it denies
729      *         {@link RuntimePermission}{@code ("setDefaultUncaughtExceptionHandler")}
730      *
731      * @see #setUncaughtExceptionHandler
732      * @see #getUncaughtExceptionHandler
733      * @see ThreadGroup#uncaughtException
734      */
735     static void setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler eh) {
736         // SecurityManager sm = System.getSecurityManager();
737         // if (sm != null) {
738         //     sm.checkPermission(
739         //         new RuntimePermission("setDefaultUncaughtExceptionHandler")
740         //             );
741         // }
742 
743          defaultUncaughtExceptionHandler = eh;
744      }
745 
746     /**
747      * Returns the default handler invoked when a thread abruptly terminates
748      * due to an uncaught exception. If the returned value is {@code null},
749      * there is no default.
750      * @see #setDefaultUncaughtExceptionHandler
751      * @return the default uncaught exception handler for all threads
752      */
753     static UncaughtExceptionHandler getDefaultUncaughtExceptionHandler(){
754         return defaultUncaughtExceptionHandler;
755     }
756 
757     /**
758      * Returns the handler invoked when this thread abruptly terminates
759      * due to an uncaught exception. If this thread has not had an
760      * uncaught exception handler explicitly set then this thread's
761      * {@code ThreadGroup} object is returned, unless this thread
762      * has terminated, in which case {@code null} is returned.
763      * @return the uncaught exception handler for this thread
764      */
765     UncaughtExceptionHandler getUncaughtExceptionHandler() {
766         return uncaughtExceptionHandler !is null ?
767             uncaughtExceptionHandler : group;
768     }
769 
770     /**
771      * Set the handler invoked when this thread abruptly terminates
772      * due to an uncaught exception.
773      * <p>A thread can take full control of how it responds to uncaught
774      * exceptions by having its uncaught exception handler explicitly set.
775      * If no such handler is set then the thread's {@code ThreadGroup}
776      * object acts as its handler.
777      * @param eh the object to use as this thread's uncaught exception
778      * handler. If {@code null} then this thread has no explicit handler.
779      * @throws  SecurityException  if the current thread is not allowed to
780      *          modify this thread.
781      * @see #setDefaultUncaughtExceptionHandler
782      * @see ThreadGroup#uncaughtException
783      */
784     void setUncaughtExceptionHandler(UncaughtExceptionHandler eh) {
785         checkAccess();
786         uncaughtExceptionHandler = eh;
787     }
788 
789     void checkAccess() {
790 
791     }
792 }
793 
794 
795 /*
796  * Per-thread blocking support for JSR166. See the Java-level
797  * Documentation for rationale. Basically, park acts like wait, unpark
798  * like notify.
799  *
800  * 6271289 --
801  * To avoid errors where an os thread expires but the JavaThread still
802  * exists, Parkers are immortal (type-stable) and are recycled across
803  * new threads.  This parallels the ParkEvent implementation.
804  * Because park-unpark allow spurious wakeups it is harmless if an
805  * unpark call unparks a new thread using the old Parker reference.
806  *
807  * In the future we'll want to think about eliminating Parker and using
808  * ParkEvent instead.  There's considerable duplication between the two
809  * services.
810  *
811  */
812 class Parker {
813 
814     enum int REL_INDEX = 0;
815     enum int ABS_INDEX = 1;
816 
817     private Object parkBlocker;
818 
819     private shared int _counter;
820     private int _nParked;
821     private Parker freeNext;
822     private Thread associatedWith; // Current association
823 
824     private  int _cur_index;  // which cond is in use: -1, 0, 1
825     private Mutex _mutex;
826     private Condition[2]  _cond; // one for relative times and one for absolute
827 
828     this() @safe nothrow {
829         _counter = 0;
830         _mutex = new Mutex();
831         _cond[REL_INDEX] = new Condition(_mutex);
832         _cond[ABS_INDEX] = new Condition(_mutex);
833         _cur_index = -1; // mark as unused
834     }
835 
836     // For simplicity of interface, all forms of park (indefinite,
837     // relative, and absolute) are multiplexed into one call.
838     // park decrements count if > 0, else does a condvar wait.  Unpark
839     // sets count to 1 and signals condvar.  Only one thread ever waits
840     // on the condvar. Contention seen when trying to park implies that someone
841     // is unparking you, so don't wait. And spurious returns are fine, so there
842     // is no need to track notifications.
843     void park(Duration time) {
844         debug(HUNT_CONCURRENCY_DEBUG) {
845             tracef("try to park a thread %s",
846                 time <= Duration.zero ? "forever" : "in " ~ time.toString());
847         }
848         // Optional fast-path check:
849         // Return immediately if a permit is available.
850         // We depend on Atomic::xchg() having full barrier semantics
851         // since we are doing a lock-free update to _counter.
852         const int c = _counter;
853         if(c > 0) {
854             atomicStore(_counter, 0);
855             debug(HUNT_CONCURRENCY_DEBUG) infof("no need to park, counter=%s", c);
856             return;
857         }
858 
859         // Next, demultiplex/decode time arguments
860         if (time < Duration.zero) { // don't wait at all
861             return;
862         }
863 
864         ThreadEx thread = cast(ThreadEx) Thread.getThis();
865 
866         // Enter safepoint region
867         // Beware of deadlocks such as 6317397.
868         // The per-thread Parker. mutex is a classic leaf-lock.
869         // In particular a thread must never block on the Threads_lock while
870         // holding the Parker.mutex. 
871 
872         // Don't wait if cannot get lock since interference arises from
873         // unparking. Also re-check interrupt before trying wait.
874         if((thread !is null && thread.isInterrupted()) || !_mutex.tryLock())
875             return;
876 
877         if (_counter > 0) { // no wait needed
878             return;
879         }
880 
881         scope(exit) {
882             _counter = 0;
883             _mutex.unlock();
884             // Paranoia to ensure our locked and lock-free paths interact
885             // correctly with each other and Java-level accesses.
886             atomicFence();
887         }
888 
889         // OSThreadWaitState osts(thread.osthread(), false  /* not Object.wait() */ );
890         // jt.set_suspend_equivalent();
891         // // cleared by handle_special_suspend_equivalent_condition() or java_suspend_self()
892 
893         assert(_cur_index == -1, "invariant");
894         if (time == Duration.zero) {
895             _cur_index = REL_INDEX; // arbitrary choice when not timed
896             _cond[_cur_index].wait();
897         }
898         else {
899             _cur_index = REL_INDEX;
900             _cond[REL_INDEX].wait(time);
901         }
902         _cur_index = -1;
903     }
904 
905     void park(MonoTime time) {
906         debug(HUNT_CONCURRENCY_DEBUG) {
907             Duration d = time - MonoTime.currTime;
908             tracef("try to park a thread %s",  
909                 d <= Duration.zero ? "forever" : "in " ~ d.toString());
910         }
911         // Optional fast-path check:
912         // Return immediately if a permit is available.
913         // We depend on Atomic::xchg() having full barrier semantics
914         // since we are doing a lock-free update to _counter.
915         const int c = _counter;
916         if(c > 0) {
917             atomicStore(_counter, 0);
918             debug(HUNT_CONCURRENCY_DEBUG) infof("no need to park, counter=%s", c);
919             return;
920         }
921 
922         // Next, demultiplex/decode time arguments
923         if (time <= MonoTime.zero) { // don't wait at all
924             return;
925         }
926 
927         ThreadEx thread = cast(ThreadEx) Thread.getThis();
928 
929         // Enter safepoint region
930         // Beware of deadlocks such as 6317397.
931         // The per-thread Parker. mutex is a classic leaf-lock.
932         // In particular a thread must never block on the Threads_lock while
933         // holding the Parker.mutex. 
934 
935         // Don't wait if cannot get lock since interference arises from
936         // unparking. Also re-check interrupt before trying wait.
937         if((thread !is null && thread.isInterrupted()) || !_mutex.tryLock())
938             return;
939 
940         if (_counter > 0) { // no wait needed
941             return;
942         }
943 
944         scope(exit) {
945             _counter = 0;
946             _mutex.unlock();
947             // Paranoia to ensure our locked and lock-free paths interact
948             // correctly with each other and Java-level accesses.
949             atomicFence();
950         }
951 
952         // OSThreadWaitState osts(thread.osthread(), false  /* not Object.wait() */ );
953         // jt.set_suspend_equivalent();
954         // // cleared by handle_special_suspend_equivalent_condition() or java_suspend_self()
955 
956         assert(_cur_index == -1, "invariant");
957         if (time == MonoTime.zero) {
958             _cur_index = REL_INDEX; // arbitrary choice when not timed
959             _cond[_cur_index].wait();
960         }
961         else {
962             _cur_index = ABS_INDEX;
963             Duration t = time - MonoTime.currTime;
964             if(t > Duration.zero)
965                 _cond[ABS_INDEX].wait(t);
966         }
967         _cur_index = -1;
968     }
969 
970     void unpark() {
971         debug(HUNT_CONCURRENCY_DEBUG) {
972             tracef("try to unpark a thread");
973         }
974         _mutex.lock();
975         const int s = _counter;
976         _counter = 1;
977         // must capture correct index before unlocking
978         int index = _cur_index;
979         _mutex.unlock();
980 
981         // Note that we signal() *after* dropping the lock for "immortal" Events.
982         // This is safe and avoids a common class of futile wakeups.  In rare
983         // circumstances this can cause a thread to return prematurely from
984         // cond_{timed}wait() but the spurious wakeup is benign and the victim
985         // will simply re-test the condition and re-park itself.
986         // This provides particular benefit if the underlying platform does not
987         // provide wait morphing.
988 
989         if (s < 1 && index != -1) {
990             // thread is definitely parked
991             _cond[index].notify();
992         }
993     }
994 
995     Object getBlocker() {
996         return parkBlocker;
997     }
998 
999     void setBlocker(Object arg) {
1000         parkBlocker = arg;
1001     }
1002 
1003     // Lifecycle operators
1004     static Parker allocate(Thread t) nothrow {
1005         assert(t !is null, "invariant");
1006         Parker p;
1007 
1008         // Start by trying to recycle an existing but unassociated
1009         // Parker from the global free list.
1010         // 8028280: using concurrent free list without memory management can leak
1011         // pretty badly it turns out.
1012         ThreadEx.spinAcquire(&listLock, "ParkerFreeListAllocate");
1013         {
1014             p = freeList;
1015             if (p !is null) {
1016                 freeList = p.freeNext;
1017             }
1018         }
1019         ThreadEx.spinRelease(&listLock);
1020 
1021         if (p !is null) {
1022             assert(p.associatedWith is null, "invariant");
1023         }
1024         else {
1025             // Do this the hard way -- materialize a new Parker..
1026             p = new Parker();
1027         }
1028         p.associatedWith = t; // Associate p with t
1029         p.freeNext = null;
1030         return p;
1031     }
1032 
1033     static void release(Parker p) {
1034         if (p is null)
1035             return;
1036         assert(p.associatedWith !is null, "invariant");
1037         assert(p.freeNext is null, "invariant");
1038         p.associatedWith = null;
1039 
1040         ThreadEx.spinAcquire(&listLock, "ParkerFreeListRelease");
1041         {
1042             p.freeNext = freeList;
1043             freeList = p;
1044         }
1045         ThreadEx.spinRelease(&listLock);
1046     }
1047 
1048     private static Parker freeList;
1049     private static shared int listLock;
1050 }
1051 
1052 
1053 /**
1054  * A thread group represents a set of threads. In addition, a thread
1055  * group can also include other thread groups. The thread groups form
1056  * a tree in which every thread group except the initial thread group
1057  * has a parent.
1058  * <p>
1059  * A thread is allowed to access information about its own thread
1060  * group, but not to access information about its thread group's
1061  * parent thread group or any other thread groups.
1062  *
1063  * @author  unascribed
1064  */
1065 /* The locking strategy for this code is to try to lock only one level of the
1066  * tree wherever possible, but otherwise to lock from the bottom up.
1067  * That is, from child thread groups to parents.
1068  * This has the advantage of limiting the number of locks that need to be held
1069  * and in particular avoids having to grab the lock for the root thread group,
1070  * (or a global lock) which would be a source of contention on a
1071  * multi-processor system with many thread groups.
1072  * This policy often leads to taking a snapshot of the state of a thread group
1073  * and working off of that snapshot, rather than holding the thread group locked
1074  * while we work on the children.
1075  */
1076 class ThreadGroupEx : UncaughtExceptionHandler { 
1077     private ThreadGroupEx parent;
1078     string name;
1079     int maxPriority;
1080     bool destroyed;
1081     bool daemon;
1082 
1083     int nUnstartedThreads = 0;
1084     int nthreads;
1085     Thread[] threads;
1086 
1087     int ngroups;
1088     ThreadGroupEx[] groups;
1089 
1090     /**
1091      * Creates an empty Thread group that is not in any Thread group.
1092      * This method is used to create the system Thread group.
1093      */
1094     private this() {     // called from C code
1095         this.name = "system";
1096         this.maxPriority = Thread.PRIORITY_MAX;
1097         this.parent = null;
1098     }
1099 
1100     /**
1101      * Constructs a new thread group. The parent of this new group is
1102      * the thread group of the currently running thread.
1103      * <p>
1104      * The {@code checkAccess} method of the parent thread group is
1105      * called with no arguments; this may result in a security exception.
1106      *
1107      * @param   name   the name of the new thread group.
1108      * @throws  SecurityException  if the current thread cannot create a
1109      *               thread in the specified thread group.
1110      * @see     java.lang.ThreadGroupEx#checkAccess()
1111      */
1112     this(string name) {
1113         ThreadEx t = cast(ThreadEx)Thread.getThis();
1114         if(t is null)
1115             this(null, name);
1116         else
1117             this(t.getThreadGroup(), name);
1118     }
1119 
1120     /**
1121      * Creates a new thread group. The parent of this new group is the
1122      * specified thread group.
1123      * <p>
1124      * The {@code checkAccess} method of the parent thread group is
1125      * called with no arguments; this may result in a security exception.
1126      *
1127      * @param     parent   the parent thread group.
1128      * @param     name     the name of the new thread group.
1129      * @throws    NullPointerException  if the thread group argument is
1130      *               {@code null}.
1131      * @throws    SecurityException  if the current thread cannot create a
1132      *               thread in the specified thread group.
1133      * @see     java.lang.SecurityException
1134      * @see     java.lang.ThreadGroupEx#checkAccess()
1135      */
1136     this(ThreadGroupEx parent, string name) {
1137         // this(checkParentAccess(parent), parent, name);
1138         
1139         this.name = name;
1140         if(parent !is null) {
1141             parent.checkAccess();
1142             this.maxPriority = parent.maxPriority;
1143             this.daemon = parent.daemon;
1144             this.parent = parent;
1145             parent.add(this);
1146         }
1147     }
1148 
1149     // private ThreadGroupEx(Void unused, ThreadGroupEx parent, string name) {
1150     //     this.name = name;
1151     //     this.maxPriority = parent.maxPriority;
1152     //     this.daemon = parent.daemon;
1153     //     this.parent = parent;
1154     //     parent.add(this);
1155     // }
1156 
1157     /*
1158      * @throws  NullPointerException  if the parent argument is {@code null}
1159      * @throws  SecurityException     if the current thread cannot create a
1160      *                                thread in the specified thread group.
1161      */
1162     // private static void checkParentAccess(ThreadGroupEx parent) {
1163     //     parent.checkAccess();
1164     //     // return null;
1165     // }
1166 
1167     /**
1168      * Returns the name of this thread group.
1169      *
1170      * @return  the name of this thread group.
1171      */
1172     final string getName() {
1173         return name;
1174     }
1175 
1176     /**
1177      * Returns the parent of this thread group.
1178      * <p>
1179      * First, if the parent is not {@code null}, the
1180      * {@code checkAccess} method of the parent thread group is
1181      * called with no arguments; this may result in a security exception.
1182      *
1183      * @return  the parent of this thread group. The top-level thread group
1184      *          is the only thread group whose parent is {@code null}.
1185      * @throws  SecurityException  if the current thread cannot modify
1186      *               this thread group.
1187      * @see        java.lang.ThreadGroupEx#checkAccess()
1188      * @see        java.lang.SecurityException
1189      * @see        java.lang.RuntimePermission
1190      */
1191     final ThreadGroupEx getParent() {
1192         if (parent !is null)
1193             parent.checkAccess();
1194         return parent;
1195     }
1196 
1197     /**
1198      * Returns the maximum priority of this thread group. Threads that are
1199      * part of this group cannot have a higher priority than the maximum
1200      * priority.
1201      *
1202      * @return  the maximum priority that a thread in this thread group
1203      *          can have.
1204      * @see     #setMaxPriority
1205      */
1206     final int getMaxPriority() {
1207         return maxPriority;
1208     }
1209 
1210     /**
1211      * Tests if this thread group is a daemon thread group. A
1212      * daemon thread group is automatically destroyed when its last
1213      * thread is stopped or its last thread group is destroyed.
1214      *
1215      * @return  {@code true} if this thread group is a daemon thread group;
1216      *          {@code false} otherwise.
1217      */
1218     final bool isDaemon() {
1219         return daemon;
1220     }
1221 
1222     /**
1223      * Tests if this thread group has been destroyed.
1224      *
1225      * @return  true if this object is destroyed
1226      */
1227     bool isDestroyed() {
1228         return destroyed;
1229     }
1230 
1231     /**
1232      * Changes the daemon status of this thread group.
1233      * <p>
1234      * First, the {@code checkAccess} method of this thread group is
1235      * called with no arguments; this may result in a security exception.
1236      * <p>
1237      * A daemon thread group is automatically destroyed when its last
1238      * thread is stopped or its last thread group is destroyed.
1239      *
1240      * @param      daemon   if {@code true}, marks this thread group as
1241      *                      a daemon thread group; otherwise, marks this
1242      *                      thread group as normal.
1243      * @throws     SecurityException  if the current thread cannot modify
1244      *               this thread group.
1245      * @see        java.lang.SecurityException
1246      * @see        java.lang.ThreadGroupEx#checkAccess()
1247      */
1248     final void setDaemon(bool daemon) {
1249         // checkAccess();
1250         this.daemon = daemon;
1251     }
1252 
1253     /**
1254      * Sets the maximum priority of the group. Threads in the thread
1255      * group that already have a higher priority are not affected.
1256      * <p>
1257      * First, the {@code checkAccess} method of this thread group is
1258      * called with no arguments; this may result in a security exception.
1259      * <p>
1260      * If the {@code pri} argument is less than
1261      * {@link Thread#PRIORITY_MIN} or greater than
1262      * {@link Thread#PRIORITY_MAX}, the maximum priority of the group
1263      * remains unchanged.
1264      * <p>
1265      * Otherwise, the priority of this ThreadGroupEx object is set to the
1266      * smaller of the specified {@code pri} and the maximum permitted
1267      * priority of the parent of this thread group. (If this thread group
1268      * is the system thread group, which has no parent, then its maximum
1269      * priority is simply set to {@code pri}.) Then this method is
1270      * called recursively, with {@code pri} as its argument, for
1271      * every thread group that belongs to this thread group.
1272      *
1273      * @param      pri   the new priority of the thread group.
1274      * @throws     SecurityException  if the current thread cannot modify
1275      *               this thread group.
1276      * @see        #getMaxPriority
1277      * @see        java.lang.SecurityException
1278      * @see        java.lang.ThreadGroupEx#checkAccess()
1279      */
1280     final void setMaxPriority(int pri) {
1281         int ngroupsSnapshot;
1282         ThreadGroupEx[] groupsSnapshot;
1283         synchronized (this) {
1284             checkAccess();
1285             if (pri < Thread.PRIORITY_MIN || pri > Thread.PRIORITY_MAX) {
1286                 return;
1287             }
1288             maxPriority = (parent !is null) ? min(pri, parent.maxPriority) : pri;
1289             ngroupsSnapshot = ngroups;
1290             if (groups !is null) {
1291                 // groupsSnapshot = Arrays.copyOf(groups, ngroupsSnapshot);
1292                 size_t limit = min(ngroupsSnapshot, groups.length);
1293                 groupsSnapshot = groups[0..limit].dup;
1294             } else {
1295                 groupsSnapshot = null;
1296             }
1297         }
1298         for (int i = 0 ; i < ngroupsSnapshot ; i++) {
1299             groupsSnapshot[i].setMaxPriority(pri);
1300         }
1301     }
1302 
1303     /**
1304      * Tests if this thread group is either the thread group
1305      * argument or one of its ancestor thread groups.
1306      *
1307      * @param   g   a thread group.
1308      * @return  {@code true} if this thread group is the thread group
1309      *          argument or one of its ancestor thread groups;
1310      *          {@code false} otherwise.
1311      */
1312     final bool parentOf(ThreadGroupEx g) {
1313         for (; g !is null ; g = g.parent) {
1314             if (g is this) {
1315                 return true;
1316             }
1317         }
1318         return false;
1319     }
1320 
1321     /**
1322      * Determines if the currently running thread has permission to
1323      * modify this thread group.
1324      * <p>
1325      * If there is a security manager, its {@code checkAccess} method
1326      * is called with this thread group as its argument. This may result
1327      * in throwing a {@code SecurityException}.
1328      *
1329      * @throws     SecurityException  if the current thread is not allowed to
1330      *               access this thread group.
1331      * @see        java.lang.SecurityManager#checkAccess(java.lang.ThreadGroupEx)
1332      */
1333     final void checkAccess() {
1334         // SecurityManager security = System.getSecurityManager();
1335         // if (security !is null) {
1336         //     security.checkAccess(this);
1337         // }
1338     }
1339 
1340     /**
1341      * Returns an estimate of the number of active threads in this thread
1342      * group and its subgroups. Recursively iterates over all subgroups in
1343      * this thread group.
1344      *
1345      * <p> The value returned is only an estimate because the number of
1346      * threads may change dynamically while this method traverses internal
1347      * data structures, and might be affected by the presence of certain
1348      * system threads. This method is intended primarily for debugging
1349      * and monitoring purposes.
1350      *
1351      * @return  an estimate of the number of active threads in this thread
1352      *          group and in any other thread group that has this thread
1353      *          group as an ancestor
1354      *
1355      */
1356     int activeCount() {
1357         int result;
1358         // Snapshot sub-group data so we don't hold this lock
1359         // while our children are computing.
1360         int ngroupsSnapshot;
1361         ThreadGroupEx[] groupsSnapshot;
1362         synchronized (this) {
1363             if (destroyed) {
1364                 return 0;
1365             }
1366             result = nthreads;
1367             ngroupsSnapshot = ngroups;
1368             if (groups !is null) {
1369                 size_t limit = min(ngroupsSnapshot, groups.length);
1370                 groupsSnapshot = groups[0..limit].dup;
1371             } else {
1372                 groupsSnapshot = null;
1373             }
1374         }
1375         for (int i = 0 ; i < ngroupsSnapshot ; i++) {
1376             result += groupsSnapshot[i].activeCount();
1377         }
1378         return result;
1379     }
1380 
1381     /**
1382      * Copies into the specified array every active thread in this
1383      * thread group and its subgroups.
1384      *
1385      * <p> An invocation of this method behaves in exactly the same
1386      * way as the invocation
1387      *
1388      * <blockquote>
1389      * {@linkplain #enumerate(Thread[], bool) enumerate}{@code (list, true)}
1390      * </blockquote>
1391      *
1392      * @param  list
1393      *         an array into which to put the list of threads
1394      *
1395      * @return  the number of threads put into the array
1396      *
1397      * @throws  SecurityException
1398      *          if {@linkplain #checkAccess checkAccess} determines that
1399      *          the current thread cannot access this thread group
1400      *
1401      */
1402     int enumerate(Thread[] list) {
1403         checkAccess();
1404         return enumerate(list, 0, true);
1405     }
1406 
1407     /**
1408      * Copies into the specified array every active thread in this
1409      * thread group. If {@code recurse} is {@code true},
1410      * this method recursively enumerates all subgroups of this
1411      * thread group and references to every active thread in these
1412      * subgroups are also included. If the array is too short to
1413      * hold all the threads, the extra threads are silently ignored.
1414      *
1415      * <p> An application might use the {@linkplain #activeCount activeCount}
1416      * method to get an estimate of how big the array should be, however
1417      * <i>if the array is too short to hold all the threads, the extra threads
1418      * are silently ignored.</i>  If it is critical to obtain every active
1419      * thread in this thread group, the caller should verify that the returned
1420      * int value is strictly less than the length of {@code list}.
1421      *
1422      * <p> Due to the inherent race condition in this method, it is recommended
1423      * that the method only be used for debugging and monitoring purposes.
1424      *
1425      * @param  list
1426      *         an array into which to put the list of threads
1427      *
1428      * @param  recurse
1429      *         if {@code true}, recursively enumerate all subgroups of this
1430      *         thread group
1431      *
1432      * @return  the number of threads put into the array
1433      *
1434      * @throws  SecurityException
1435      *          if {@linkplain #checkAccess checkAccess} determines that
1436      *          the current thread cannot access this thread group
1437      *
1438      */
1439     int enumerate(Thread[] list, bool recurse) {
1440         checkAccess();
1441         return enumerate(list, 0, recurse);
1442     }
1443 
1444     private int enumerate(Thread[] list, int n, bool recurse) {
1445         int ngroupsSnapshot = 0;
1446         ThreadGroupEx[] groupsSnapshot = null;
1447         synchronized (this) {
1448             if (destroyed) {
1449                 return 0;
1450             }
1451             int nt = nthreads;
1452             if (nt > cast(int)list.length - n) {
1453                 nt = cast(int)list.length - n;
1454             }
1455             for (int i = 0; i < nt; i++) {
1456                 // TODO: Tasks pending completion -@zxp at 10/14/2018, 9:11:46 AM
1457                 // 
1458                 implementationMissing(false);
1459                 // if (threads[i].isAlive()) {
1460                 //     list[n++] = threads[i];
1461                 // }
1462             }
1463             if (recurse) {
1464                 ngroupsSnapshot = ngroups;
1465                 if (groups !is null) {
1466                     size_t limit = min(ngroupsSnapshot, groups.length);
1467                     groupsSnapshot = groups[0..limit].dup;
1468                 } else {
1469                     groupsSnapshot = null;
1470                 }
1471             }
1472         }
1473         if (recurse) {
1474             for (int i = 0 ; i < ngroupsSnapshot ; i++) {
1475                 n = groupsSnapshot[i].enumerate(list, n, true);
1476             }
1477         }
1478         return n;
1479     }
1480 
1481     /**
1482      * Returns an estimate of the number of active groups in this
1483      * thread group and its subgroups. Recursively iterates over
1484      * all subgroups in this thread group.
1485      *
1486      * <p> The value returned is only an estimate because the number of
1487      * thread groups may change dynamically while this method traverses
1488      * internal data structures. This method is intended primarily for
1489      * debugging and monitoring purposes.
1490      *
1491      * @return  the number of active thread groups with this thread group as
1492      *          an ancestor
1493      *
1494      */
1495     int activeGroupCount() {
1496         int ngroupsSnapshot;
1497         ThreadGroupEx[] groupsSnapshot;
1498         synchronized (this) {
1499             if (destroyed) {
1500                 return 0;
1501             }
1502             ngroupsSnapshot = ngroups;
1503             if (groups !is null) {
1504                 size_t limit = min(ngroupsSnapshot, groups.length);
1505                 groupsSnapshot = groups[0..limit].dup;
1506             } else {
1507                 groupsSnapshot = null;
1508             }
1509         }
1510         int n = ngroupsSnapshot;
1511         for (int i = 0 ; i < ngroupsSnapshot ; i++) {
1512             n += groupsSnapshot[i].activeGroupCount();
1513         }
1514         return n;
1515     }
1516 
1517     /**
1518      * Copies into the specified array references to every active
1519      * subgroup in this thread group and its subgroups.
1520      *
1521      * <p> An invocation of this method behaves in exactly the same
1522      * way as the invocation
1523      *
1524      * <blockquote>
1525      * {@linkplain #enumerate(ThreadGroupEx[], bool) enumerate}{@code (list, true)}
1526      * </blockquote>
1527      *
1528      * @param  list
1529      *         an array into which to put the list of thread groups
1530      *
1531      * @return  the number of thread groups put into the array
1532      *
1533      * @throws  SecurityException
1534      *          if {@linkplain #checkAccess checkAccess} determines that
1535      *          the current thread cannot access this thread group
1536      *
1537      */
1538     int enumerate(ThreadGroupEx[] list) {
1539         checkAccess();
1540         return enumerate(list, 0, true);
1541     }
1542 
1543     /**
1544      * Copies into the specified array references to every active
1545      * subgroup in this thread group. If {@code recurse} is
1546      * {@code true}, this method recursively enumerates all subgroups of this
1547      * thread group and references to every active thread group in these
1548      * subgroups are also included.
1549      *
1550      * <p> An application might use the
1551      * {@linkplain #activeGroupCount activeGroupCount} method to
1552      * get an estimate of how big the array should be, however <i>if the
1553      * array is too short to hold all the thread groups, the extra thread
1554      * groups are silently ignored.</i>  If it is critical to obtain every
1555      * active subgroup in this thread group, the caller should verify that
1556      * the returned int value is strictly less than the length of
1557      * {@code list}.
1558      *
1559      * <p> Due to the inherent race condition in this method, it is recommended
1560      * that the method only be used for debugging and monitoring purposes.
1561      *
1562      * @param  list
1563      *         an array into which to put the list of thread groups
1564      *
1565      * @param  recurse
1566      *         if {@code true}, recursively enumerate all subgroups
1567      *
1568      * @return  the number of thread groups put into the array
1569      *
1570      * @throws  SecurityException
1571      *          if {@linkplain #checkAccess checkAccess} determines that
1572      *          the current thread cannot access this thread group
1573      *
1574      */
1575     int enumerate(ThreadGroupEx[] list, bool recurse) {
1576         checkAccess();
1577         return enumerate(list, 0, recurse);
1578     }
1579 
1580     private int enumerate(ThreadGroupEx[] list, int n, bool recurse) {
1581         int ngroupsSnapshot = 0;
1582         ThreadGroupEx[] groupsSnapshot = null;
1583         synchronized (this) {
1584             if (destroyed) {
1585                 return 0;
1586             }
1587             int ng = ngroups;
1588             if (ng > cast(int)list.length - n) {
1589                 ng = cast(int)list.length - n;
1590             }
1591             if (ng > 0) {
1592                 // System.arraycopy(groups, 0, list, n, ng);
1593                 list[n .. n+ng] = groups[0..ng];
1594                 n += ng;
1595             }
1596             if (recurse) {
1597                 ngroupsSnapshot = ngroups;
1598                 if (groups !is null) {
1599                     size_t limit = min(ngroupsSnapshot, groups.length);
1600                     groupsSnapshot = groups[0..limit].dup;
1601                 } else {
1602                     groupsSnapshot = null;
1603                 }
1604             }
1605         }
1606         if (recurse) {
1607             for (int i = 0 ; i < ngroupsSnapshot ; i++) {
1608                 n = groupsSnapshot[i].enumerate(list, n, true);
1609             }
1610         }
1611         return n;
1612     }
1613 
1614     /**
1615      * Stops all threads in this thread group.
1616      * <p>
1617      * First, the {@code checkAccess} method of this thread group is
1618      * called with no arguments; this may result in a security exception.
1619      * <p>
1620      * This method then calls the {@code stop} method on all the
1621      * threads in this thread group and in all of its subgroups.
1622      *
1623      * @throws     SecurityException  if the current thread is not allowed
1624      *               to access this thread group or any of the threads in
1625      *               the thread group.
1626      * @see        java.lang.SecurityException
1627      * @see        java.lang.Thread#stop()
1628      * @see        java.lang.ThreadGroupEx#checkAccess()
1629      * @deprecated    This method is inherently unsafe.  See
1630      *     {@link Thread#stop} for details.
1631      */
1632     // @Deprecated(since="1.2")
1633     // final void stop() {
1634     //     if (stopOrSuspend(false))
1635     //         Thread.getThis().stop();
1636     // }
1637 
1638     /**
1639      * Interrupts all threads in this thread group.
1640      * <p>
1641      * First, the {@code checkAccess} method of this thread group is
1642      * called with no arguments; this may result in a security exception.
1643      * <p>
1644      * This method then calls the {@code interrupt} method on all the
1645      * threads in this thread group and in all of its subgroups.
1646      *
1647      * @throws     SecurityException  if the current thread is not allowed
1648      *               to access this thread group or any of the threads in
1649      *               the thread group.
1650      * @see        java.lang.Thread#interrupt()
1651      * @see        java.lang.SecurityException
1652      * @see        java.lang.ThreadGroupEx#checkAccess()
1653      */
1654     final void interrupt() {
1655         int ngroupsSnapshot;
1656         ThreadGroupEx[] groupsSnapshot;
1657         synchronized (this) {
1658             checkAccess();
1659             // for (int i = 0 ; i < nthreads ; i++) {
1660             //     threads[i].interrupt();
1661             // }
1662             ngroupsSnapshot = ngroups;
1663             if (groups !is null) {
1664                 size_t limit = min(ngroupsSnapshot, groups.length);
1665                 groupsSnapshot = groups[0..limit].dup;
1666             } else {
1667                 groupsSnapshot = null;
1668             }
1669         }
1670         for (int i = 0 ; i < ngroupsSnapshot ; i++) {
1671             groupsSnapshot[i].interrupt();
1672         }
1673     }
1674 
1675     /**
1676      * Suspends all threads in this thread group.
1677      * <p>
1678      * First, the {@code checkAccess} method of this thread group is
1679      * called with no arguments; this may result in a security exception.
1680      * <p>
1681      * This method then calls the {@code suspend} method on all the
1682      * threads in this thread group and in all of its subgroups.
1683      *
1684      * @throws     SecurityException  if the current thread is not allowed
1685      *               to access this thread group or any of the threads in
1686      *               the thread group.
1687      * @see        java.lang.Thread#suspend()
1688      * @see        java.lang.SecurityException
1689      * @see        java.lang.ThreadGroupEx#checkAccess()
1690      * @deprecated    This method is inherently deadlock-prone.  See
1691      *     {@link Thread#suspend} for details.
1692      */
1693     // @Deprecated(since="1.2")
1694     // @SuppressWarnings("deprecation")
1695     // final void suspend() {
1696     //     if (stopOrSuspend(true))
1697     //         Thread.getThis().suspend();
1698     // }
1699 
1700     /**
1701      * Helper method: recursively stops or suspends (as directed by the
1702      * bool argument) all of the threads in this thread group and its
1703      * subgroups, except the current thread.  This method returns true
1704      * if (and only if) the current thread is found to be in this thread
1705      * group or one of its subgroups.
1706      */
1707     // @SuppressWarnings("deprecation")
1708     // private bool stopOrSuspend(bool suspend) {
1709     //     bool suicide = false;
1710     //     Thread us = Thread.getThis();
1711     //     int ngroupsSnapshot;
1712     //     ThreadGroupEx[] groupsSnapshot = null;
1713     //     synchronized (this) {
1714     //         checkAccess();
1715     //         for (int i = 0 ; i < nthreads ; i++) {
1716     //             if (threads[i]==us)
1717     //                 suicide = true;
1718     //             else if (suspend)
1719     //                 threads[i].suspend();
1720     //             else
1721     //                 threads[i].stop();
1722     //         }
1723 
1724     //         ngroupsSnapshot = ngroups;
1725     //         if (groups !is null) {
1726     //             groupsSnapshot = Arrays.copyOf(groups, ngroupsSnapshot);
1727     //         }
1728     //     }
1729     //     for (int i = 0 ; i < ngroupsSnapshot ; i++)
1730     //         suicide = groupsSnapshot[i].stopOrSuspend(suspend) || suicide;
1731 
1732     //     return suicide;
1733     // }
1734 
1735     /**
1736      * Resumes all threads in this thread group.
1737      * <p>
1738      * First, the {@code checkAccess} method of this thread group is
1739      * called with no arguments; this may result in a security exception.
1740      * <p>
1741      * This method then calls the {@code resume} method on all the
1742      * threads in this thread group and in all of its sub groups.
1743      *
1744      * @throws     SecurityException  if the current thread is not allowed to
1745      *               access this thread group or any of the threads in the
1746      *               thread group.
1747      * @see        java.lang.SecurityException
1748      * @see        java.lang.Thread#resume()
1749      * @see        java.lang.ThreadGroupEx#checkAccess()
1750      * @deprecated    This method is used solely in conjunction with
1751      *       {@code Thread.suspend} and {@code ThreadGroupEx.suspend},
1752      *       both of which have been deprecated, as they are inherently
1753      *       deadlock-prone.  See {@link Thread#suspend} for details.
1754      */
1755     // @Deprecated(since="1.2")
1756     // @SuppressWarnings("deprecation")
1757     // final void resume() {
1758     //     int ngroupsSnapshot;
1759     //     ThreadGroupEx[] groupsSnapshot;
1760     //     synchronized (this) {
1761     //         checkAccess();
1762     //         for (int i = 0 ; i < nthreads ; i++) {
1763     //             threads[i].resume();
1764     //         }
1765     //         ngroupsSnapshot = ngroups;
1766     //         if (groups !is null) {
1767     //             groupsSnapshot = Arrays.copyOf(groups, ngroupsSnapshot);
1768     //         } else {
1769     //             groupsSnapshot = null;
1770     //         }
1771     //     }
1772     //     for (int i = 0 ; i < ngroupsSnapshot ; i++) {
1773     //         groupsSnapshot[i].resume();
1774     //     }
1775     // }
1776 
1777     /**
1778      * Destroys this thread group and all of its subgroups. This thread
1779      * group must be empty, indicating that all threads that had been in
1780      * this thread group have since stopped.
1781      * <p>
1782      * First, the {@code checkAccess} method of this thread group is
1783      * called with no arguments; this may result in a security exception.
1784      *
1785      * @throws     IllegalThreadStateException  if the thread group is not
1786      *               empty or if the thread group has already been destroyed.
1787      * @throws     SecurityException  if the current thread cannot modify this
1788      *               thread group.
1789      * @see        java.lang.ThreadGroupEx#checkAccess()
1790      */
1791     final void destroy() {
1792         int ngroupsSnapshot;
1793         ThreadGroupEx[] groupsSnapshot;
1794         synchronized (this) {
1795             checkAccess();
1796             if (destroyed || (nthreads > 0)) {
1797                 throw new IllegalThreadStateException();
1798             }
1799             ngroupsSnapshot = ngroups;
1800             if (groups !is null) {
1801                 size_t limit = min(ngroupsSnapshot, groups.length);
1802                 groupsSnapshot = groups[0..limit].dup;
1803             } else {
1804                 groupsSnapshot = null;
1805             }
1806             if (parent !is null) {
1807                 destroyed = true;
1808                 ngroups = 0;
1809                 groups = null;
1810                 nthreads = 0;
1811                 threads = null;
1812             }
1813         }
1814         for (int i = 0 ; i < ngroupsSnapshot ; i += 1) {
1815             groupsSnapshot[i].destroy();
1816         }
1817         if (parent !is null) {
1818             parent.remove(this);
1819         }
1820     }
1821 
1822     /**
1823      * Adds the specified Thread group to this group.
1824      * @param g the specified Thread group to be added
1825      * @throws  IllegalThreadStateException If the Thread group has been destroyed.
1826      */
1827     private final void add(ThreadGroupEx g){
1828         synchronized (this) {
1829             if (destroyed) {
1830                 throw new IllegalThreadStateException();
1831             }
1832             if (groups == null) {
1833                 groups = new ThreadGroupEx[4];
1834             } else if (ngroups == groups.length) {
1835                 size_t limit = min(ngroups * 2, groups.length);
1836                 groups = groups[0..limit].dup;
1837             }
1838             groups[ngroups] = g;
1839 
1840             // This is done last so it doesn't matter in case the
1841             // thread is killed
1842             ngroups++;
1843         }
1844     }
1845 
1846     /**
1847      * Removes the specified Thread group from this group.
1848      * @param g the Thread group to be removed
1849      * @return if this Thread has already been destroyed.
1850      */
1851     private void remove(ThreadGroupEx g) {
1852         synchronized (this) {
1853             if (destroyed) {
1854                 return;
1855             }
1856             for (int i = 0 ; i < ngroups ; i++) {
1857                 if (groups[i] == g) {
1858                     ngroups -= 1;
1859                     // System.arraycopy(groups, i + 1, groups, i, ngroups - i);
1860                     for(int j=i; j<ngroups; j++)
1861                         groups[j] = groups[j+1];                    
1862                     // Zap dangling reference to the dead group so that
1863                     // the garbage collector will collect it.
1864                     groups[ngroups] = null;
1865                     break;
1866                 }
1867             }
1868             if (nthreads == 0) {
1869                 // TODO: Tasks pending completion -@zxp at 12/19/2018, 4:57:38 PM
1870                 // 
1871                 // notifyAll();
1872             }
1873             if (daemon && (nthreads == 0) &&
1874                 (nUnstartedThreads == 0) && (ngroups == 0))
1875             {
1876                 // TODO: Tasks pending completion -@zxp at 12/19/2018, 4:57:42 PM
1877                 // 
1878                 // destroy();
1879             }
1880         }
1881     }
1882 
1883 
1884     /**
1885      * Increments the count of unstarted threads in the thread group.
1886      * Unstarted threads are not added to the thread group so that they
1887      * can be collected if they are never started, but they must be
1888      * counted so that daemon thread groups with unstarted threads in
1889      * them are not destroyed.
1890      */
1891     void addUnstarted() {
1892         synchronized(this) {
1893             if (destroyed) {
1894                 throw new IllegalThreadStateException();
1895             }
1896             nUnstartedThreads++;
1897         }
1898     }
1899 
1900     /**
1901      * Adds the specified thread to this thread group.
1902      *
1903      * <p> Note: This method is called from both library code
1904      * and the Virtual Machine. It is called from VM to add
1905      * certain system threads to the system thread group.
1906      *
1907      * @param  t
1908      *         the Thread to be added
1909      *
1910      * @throws IllegalThreadStateException
1911      *          if the Thread group has been destroyed
1912      */
1913     void add(Thread t) {
1914         synchronized (this) {
1915             if (destroyed) {
1916                 throw new IllegalThreadStateException();
1917             }
1918             if (threads == null) {
1919                 threads = new Thread[4];
1920             } else if (nthreads == threads.length) {
1921                 size_t limit = min(nthreads * 2, threads.length);
1922                 threads = threads[0..limit].dup;
1923             }
1924             threads[nthreads] = t;
1925 
1926             // This is done last so it doesn't matter in case the
1927             // thread is killed
1928             nthreads++;
1929 
1930             // The thread is now a fully fledged member of the group, even
1931             // though it may, or may not, have been started yet. It will prevent
1932             // the group from being destroyed so the unstarted Threads count is
1933             // decremented.
1934             nUnstartedThreads--;
1935         }
1936     }
1937 
1938     /**
1939      * Notifies the group that the thread {@code t} has failed
1940      * an attempt to start.
1941      *
1942      * <p> The state of this thread group is rolled back as if the
1943      * attempt to start the thread has never occurred. The thread is again
1944      * considered an unstarted member of the thread group, and a subsequent
1945      * attempt to start the thread is permitted.
1946      *
1947      * @param  t
1948      *         the Thread whose start method was invoked
1949      */
1950     void threadStartFailed(Thread t) {
1951         synchronized(this) {
1952             remove(t);
1953             nUnstartedThreads++;
1954         }
1955     }
1956 
1957     /**
1958      * Notifies the group that the thread {@code t} has terminated.
1959      *
1960      * <p> Destroy the group if all of the following conditions are
1961      * true: this is a daemon thread group; there are no more alive
1962      * or unstarted threads in the group; there are no subgroups in
1963      * this thread group.
1964      *
1965      * @param  t
1966      *         the Thread that has terminated
1967      */
1968     void threadTerminated(Thread t) {
1969         synchronized (this) {
1970             remove(t);
1971 
1972             if (nthreads == 0) {
1973                 // TODO: Tasks pending completion -@zxp at 12/19/2018, 4:57:55 PM
1974                 // 
1975                 // notifyAll();
1976             }
1977             if (daemon && (nthreads == 0) &&
1978                 (nUnstartedThreads == 0) && (ngroups == 0))
1979             {
1980                 destroy();
1981             }
1982         }
1983     }
1984 
1985     /**
1986      * Removes the specified Thread from this group. Invoking this method
1987      * on a thread group that has been destroyed has no effect.
1988      *
1989      * @param  t
1990      *         the Thread to be removed
1991      */
1992     private void remove(Thread t) {
1993         synchronized (this) {
1994             if (destroyed) {
1995                 return;
1996             }
1997             for (int i = 0 ; i < nthreads ; i++) {
1998                 if (threads[i] == t) {
1999                     // System.arraycopy(threads, i + 1, threads, i, --nthreads - i);
2000                     for(int j=i; j<ngroups; j++)
2001                         groups[j] = groups[j+1];                    
2002                     // Zap dangling reference to the dead thread so that
2003                     // the garbage collector will collect it.
2004                     threads[nthreads] = null;
2005                     break;
2006                 }
2007             }
2008         }
2009     }
2010 
2011     /**
2012      * Prints information about this thread group to the standard
2013      * output. This method is useful only for debugging.
2014      *
2015      */
2016     void list() {
2017         // list(System.out, 0);
2018     }
2019     // void list(PrintStream out, int indent) {
2020     //     int ngroupsSnapshot;
2021     //     ThreadGroupEx[] groupsSnapshot;
2022     //     synchronized (this) {
2023     //         for (int j = 0 ; j < indent ; j++) {
2024     //             out.print(" ");
2025     //         }
2026     //         out.println(this);
2027     //         indent += 4;
2028     //         for (int i = 0 ; i < nthreads ; i++) {
2029     //             for (int j = 0 ; j < indent ; j++) {
2030     //                 out.print(" ");
2031     //             }
2032     //             out.println(threads[i]);
2033     //         }
2034     //         ngroupsSnapshot = ngroups;
2035     //         if (groups !is null) {
2036     //             groupsSnapshot = Arrays.copyOf(groups, ngroupsSnapshot);
2037     //         } else {
2038     //             groupsSnapshot = null;
2039     //         }
2040     //     }
2041     //     for (int i = 0 ; i < ngroupsSnapshot ; i++) {
2042     //         groupsSnapshot[i].list(out, indent);
2043     //     }
2044     // }
2045 
2046     /**
2047      * Called by the Java Virtual Machine when a thread in this
2048      * thread group stops because of an uncaught exception, and the thread
2049      * does not have a specific {@link Thread.UncaughtExceptionHandler}
2050      * installed.
2051      * <p>
2052      * The {@code uncaughtException} method of
2053      * {@code ThreadGroupEx} does the following:
2054      * <ul>
2055      * <li>If this thread group has a parent thread group, the
2056      *     {@code uncaughtException} method of that parent is called
2057      *     with the same two arguments.
2058      * <li>Otherwise, this method checks to see if there is a
2059      *     {@linkplain Thread#getDefaultUncaughtExceptionHandler default
2060      *     uncaught exception handler} installed, and if so, its
2061      *     {@code uncaughtException} method is called with the same
2062      *     two arguments.
2063      * <li>Otherwise, this method determines if the {@code Throwable}
2064      *     argument is an instance of {@link ThreadDeath}. If so, nothing
2065      *     special is done. Otherwise, a message containing the
2066      *     thread's name, as returned from the thread's {@link
2067      *     Thread#getName getName} method, and a stack backtrace,
2068      *     using the {@code Throwable}'s {@link
2069      *     Throwable#printStackTrace printStackTrace} method, is
2070      *     printed to the {@linkplain System#err standard error stream}.
2071      * </ul>
2072      * <p>
2073      * Applications can override this method in subclasses of
2074      * {@code ThreadGroupEx} to provide alternative handling of
2075      * uncaught exceptions.
2076      *
2077      * @param   t   the thread that is about to exit.
2078      * @param   e   the uncaught exception.
2079      */
2080     void uncaughtException(Thread t, Throwable e) {
2081         if (parent !is null) {
2082             parent.uncaughtException(t, e);
2083         } else {
2084             // Thread.UncaughtExceptionHandler ueh =
2085             //     Thread.getDefaultUncaughtExceptionHandler();
2086             // if (ueh !is null) {
2087             //     ueh.uncaughtException(t, e);
2088             // } else if (!(e instanceof ThreadDeath)) {
2089             //     System.err.print("Exception in thread \""
2090             //                      + t.getName() + "\" ");
2091             //     e.printStackTrace(System.err);
2092             // }
2093         }
2094     }
2095 
2096     /**
2097      * Used by VM to control lowmem implicit suspension.
2098      *
2099      * @param b bool to allow or disallow suspension
2100      * @return true on success
2101      * @deprecated The definition of this call depends on {@link #suspend},
2102      *             which is deprecated.  Further, the behavior of this call
2103      *             was never specified.
2104      */
2105     // @Deprecated(since="1.2")
2106     // bool allowThreadSuspension(bool b) {
2107     //     return true;
2108     // }
2109 
2110     /**
2111      * Returns a string representation of this Thread group.
2112      *
2113      * @return  a string representation of this thread group.
2114      */
2115     // string toString() {
2116     //     return getClass().getName() + "[name=" + getName() + ",maxpri=" + maxPriority + "]";
2117     // }
2118 }