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.ThreadFactory;
13 
14 import hunt.concurrency.atomic.AtomicHelper;
15 import hunt.concurrency.thread.ThreadEx;
16 
17 import hunt.Functions;
18 import hunt.util.Common;
19 
20 import core.thread;
21 import std.conv;
22 
23 /**
24  * An object that creates new threads on demand.  Using thread factories
25  * removes hardwiring of calls to {@link Thread#Thread(Runnable) new Thread},
26  * enabling applications to use special thread subclasses, priorities, etc.
27  *
28  * <p>
29  * The simplest implementation of this interface is just:
30  * <pre> {@code
31  * class SimpleThreadFactory implements ThreadFactory {
32  *   public Thread newThread(Runnable r) {
33  *     return new Thread(r);
34  *   }
35  * }}</pre>
36  *
37  * The {@link Executors#defaultThreadFactory} method provides a more
38  * useful simple implementation, that sets the created thread context
39  * to known values before returning it.
40  * @since 1.5
41  * @author Doug Lea
42  */
43 interface ThreadFactory {
44 
45     /**
46      * Returns a default thread factory used to create new threads.
47      * This factory creates all new threads used by an Executor in the
48      * same {@link ThreadGroupEx}. If there is a {@link
49      * java.lang.SecurityManager}, it uses the group of {@link
50      * System#getSecurityManager}, else the group of the thread
51      * invoking this {@code defaultThreadFactory} method. Each new
52      * thread is created as a non-daemon thread with priority set to
53      * the smaller of {@code Thread.PRIORITY_DEFAULT} and the maximum
54      * priority permitted in the thread group.  New threads have names
55      * accessible via {@link Thread#getName} of
56      * <em>pool-N-thread-M</em>, where <em>N</em> is the sequence
57      * number of this factory, and <em>M</em> is the sequence number
58      * of the thread created by this factory.
59      * @return a thread factory
60      */
61     static ThreadFactory defaultThreadFactory() {
62         return new DefaultThreadFactory();
63     }
64 
65     /**
66      * Constructs a new {@code Thread}.  Implementations may also initialize
67      * priority, name, daemon status, {@code ThreadGroupEx}, etc.
68      *
69      * @param r a runnable to be executed by new thread instance
70      * @return constructed thread, or {@code null} if the request to
71      *         create a thread is rejected
72      */
73     final Thread newThread(Runnable r) {
74         return newThread({ r.run(); });
75     }
76 
77     Thread newThread(Action dg );
78 }
79 
80 
81 /**
82  * The default thread factory.
83  */
84 private class DefaultThreadFactory : ThreadFactory {
85     private static shared(int) poolNumber = 1;
86     private ThreadGroupEx group;
87     private shared(int) threadNumber = 1;
88     private string namePrefix;
89 
90     this() {
91         // SecurityManager s = System.getSecurityManager();
92         // group = (s !is null) ? s.getThreadGroup() :
93         //                       Thread.getThis().getThreadGroup();
94         int n = AtomicHelper.getAndIncrement(poolNumber);
95         namePrefix = "pool-" ~ n.to!string() ~ "-thread-";
96     }
97 
98     
99     Thread newThread(Action dg ) {
100         int n = AtomicHelper.getAndIncrement(threadNumber);
101 
102         Thread t = new ThreadEx(dg);
103         t.name = namePrefix ~ n.to!string();
104         t.isDaemon = false;
105         // version(Posix) {
106         //     t.priority = Thread.PRIORITY_DEFAULT;
107         // }
108 
109         return t;
110     }
111 }
112 
113 
114 /**
115  * Thread factory capturing access control context and class loader.
116  */
117 // private class PrivilegedThreadFactory : DefaultThreadFactory {
118 //     // AccessControlContext acc;
119 //     // ClassLoader ccl;
120 
121 //     this() {
122 //         super();
123 //         SecurityManager sm = System.getSecurityManager();
124 //         if (sm !is null) {
125 //             // Calls to getContextClassLoader from this class
126 //             // never trigger a security check, but we check
127 //             // whether our callers have this permission anyways.
128 //             sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
129 
130 //             // Fail fast
131 //             sm.checkPermission(new RuntimePermission("setContextClassLoader"));
132 //         }
133 //         this.acc = AccessController.getContext();
134 //         this.ccl = Thread.getThis().getContextClassLoader();
135 //     }
136 
137 //     Thread newThread(Runnable r) {
138 //         return super.newThread(new Runnable() {
139 //             void run() {
140 //                 AccessController.doPrivileged(new PrivilegedAction<>() {
141 //                     Void run() {
142 //                         Thread.getThis().setContextClassLoader(ccl);
143 //                         r.run();
144 //                         return null;
145 //                     }
146 //                 }, acc);
147 //             }
148 //         });
149 //     }
150 // }