00001 /* 00002 * Copyright (c) 2000, 2020, Oracle and/or its affiliates. 00003 * 00004 * Licensed under the Universal Permissive License v 1.0 as shown at 00005 * http://oss.oracle.com/licenses/upl. 00006 */ 00007 #ifndef COH_THREAD_HPP 00008 #define COH_THREAD_HPP 00009 00010 #include "coherence/lang/compatibility.hpp" 00011 00012 #include "coherence/lang/FinalHandle.hpp" 00013 #include "coherence/lang/FinalView.hpp" 00014 #include "coherence/lang/Object.hpp" 00015 #include "coherence/lang/ObjectArray.hpp" 00016 #include "coherence/lang/MemberView.hpp" 00017 #include "coherence/lang/Runnable.hpp" 00018 #include "coherence/lang/String.hpp" 00019 #include "coherence/lang/ThreadGroup.hpp" 00020 #include "coherence/lang/TypedHandle.hpp" 00021 #include "coherence/lang/Volatile.hpp" 00022 00023 COH_OPEN_NAMESPACE2(coherence,lang) 00024 00025 class TimeoutBlock; 00026 00027 /** 00028 * An Object representing a thread of execution. 00029 * 00030 * @author mf 2007.12.10 00031 */ 00032 class COH_EXPORT Thread 00033 : public class_spec<Thread, 00034 extends<Object>, 00035 implements<Runnable> > 00036 { 00037 friend class factory<Thread>; 00038 00039 // ----- State definition ----------------------------------------------- 00040 00041 public: 00042 typedef enum 00043 { 00044 state_initial = 0, // the thread has not yet started 00045 state_runnable = 1, // the thread has started 00046 state_interrupted = 2, // the thread has been interrupted 00047 state_terminated = 3 // the thread has completed execution 00048 } State; 00049 00050 00051 // ----- Maintenance definition ------------------------------------------ 00052 00053 protected: 00054 /** 00055 * Defines various thread maintenance tasks. 00056 */ 00057 typedef enum 00058 { 00059 none = 0, 00060 collect_stack = 1, 00061 compact_tls = 2 00062 } Maintenance; 00063 00064 00065 // ----- constructors --------------------------------------------------- 00066 00067 private: 00068 /** 00069 * Create a Thread. 00070 * 00071 * @param hRunnable the Runnable to execute 00072 * @param vsName the thread's name, or NULL for default 00073 * @param hGroup the thread's group, or NULL for parent's 00074 * @param cBytesStack the stack size, or 0 for default 00075 * 00076 * @return the handle to the new Thread 00077 */ 00078 Thread(Runnable::Handle hRunnable, 00079 String::View vsName = String::null_string, 00080 ThreadGroup::Handle hGroup = NULL, 00081 size32_t cBytesStack = 0); 00082 00083 00084 // ----- Runnable interface --------------------------------------------- 00085 00086 public: 00087 /** 00088 * {@inheritDoc} 00089 */ 00090 virtual void run(); 00091 00092 00093 // ----- Thread interface ----------------------------------------------- 00094 00095 public: 00096 /** 00097 * Return the Thread's unique ID. 00098 * 00099 * No two live thread's will have the same ID and no thread will have 00100 * an id of 0. 00101 * 00102 * @return the Thread's unique ID. 00103 */ 00104 virtual int64_t getId() const; 00105 00106 /** 00107 * Return the Thread's current state. 00108 * 00109 * @return the Thread's current state 00110 */ 00111 virtual State getState() const; 00112 00113 /** 00114 * Return the Thread's name. 00115 * 00116 * @return the Thread's name 00117 */ 00118 virtual String::View getName() const; 00119 00120 /** 00121 * Return this thread's group, or NULL if the thread has terminated. 00122 * 00123 * @return this thread's group 00124 */ 00125 virtual ThreadGroup::Handle getThreadGroup(); 00126 00127 /** 00128 * Return this thread's group, or NULL if the thread has terminated. 00129 * 00130 * @return this thread's group 00131 */ 00132 virtual ThreadGroup::View getThreadGroup() const; 00133 00134 /** 00135 * Tests if this thread is alive. A thread is alive if it has 00136 * been started and has not yet died. 00137 * 00138 * @return <code>true</code> if this thread is alive; 00139 * <code>false</code> otherwise. 00140 */ 00141 virtual bool isAlive() const; 00142 00143 /** 00144 * Begin executing the Thread's runnable on a new system thread. 00145 * 00146 * This method may only be called once per Thread instance. 00147 * 00148 * @throw IllegalStateException if a called on a Thread which is not 00149 * in the state state_initial. 00150 */ 00151 virtual void start(); 00152 00153 /** 00154 * Request that the Thread stop executing. 00155 */ 00156 virtual void interrupt(); 00157 00158 /** 00159 * Return true iff the thread is interrupted. 00160 * 00161 * Note, Unlike Thread::interrupted() this does not check if the thread has timed-out. 00162 * 00163 * @return true iff the thread is interrupted 00164 */ 00165 virtual bool isInterrupted() const; 00166 00167 /** 00168 * Wait for the Thread to reach the state_terminated state. 00169 */ 00170 virtual void join() const; 00171 00172 /** 00173 * Wait for the Thread to reach the state_terminated state. 00174 * 00175 * @param cMillis the maximum duration to wait, or zero for infinite 00176 */ 00177 virtual void join(int64_t cMillis) const; 00178 00179 /** 00180 * Set the Thread's name. 00181 * 00182 * @param vsName the Thread's name 00183 */ 00184 virtual void setName(String::View vsName); 00185 00186 protected: 00187 /** 00188 * Called automatically on the thread prior to termination. 00189 * 00190 * Any class extending this Thread and overriding this method much 00191 * call this implementation to ensure that join() operations complete. 00192 */ 00193 virtual void onExit(); 00194 00195 /** 00196 * Instruct the thread to perform maintenance. 00197 */ 00198 virtual void scheduleMaintenance(Maintenance nMaintenance) const; 00199 00200 00201 // ----- static helper methods ------------------------------------------ 00202 00203 public: 00204 /** 00205 * Return the Thread on which the caller is executing. 00206 * 00207 * @return the caller's thread 00208 */ 00209 static Thread::Handle currentThread(); 00210 00211 /** 00212 * Return a stack trace for this thread. 00213 * 00214 * @param cTrim the number of frames to trim from the top of the stack 00215 * 00216 * @return an array of StackTraceElements describing as much of the 00217 * thread's stack as can be determined 00218 */ 00219 static ObjectArray::Handle getStackTrace(size32_t cTrim = 0); 00220 00221 /** 00222 * Format a stack trace. 00223 * 00224 * @param vaStack the array of StackTraceElements to output, or NULL 00225 * for the stack of the current thread 00226 */ 00227 static String::View formatStackTrace(ObjectArray::View vaStack); 00228 00229 /** 00230 * Return the stack trace of all known threads as a String. 00231 * 00232 * This is a blocking operation, while the calling thread waits for 00233 * all known threads to report their stack. 00234 * 00235 * @param cMillisTimeout the maximum amount of time to wait for all 00236 * threads to report their stacks, or -1 for 00237 * the system default of twice the interrupt 00238 * resolution 00239 * 00240 * @return the stack traces 00241 */ 00242 static String::View formatStacks(int64_t cMillisTimeout = -1); 00243 00244 /** 00245 * Return true iff the caller's thread has been interrupted, or timed out. 00246 * 00247 * The thread's interrupt state is reset as part of this operation. 00248 * 00249 * @return true iff the caller's thread has been interrupted 00250 */ 00251 static bool interrupted(); 00252 00253 /** 00254 * Pause the current thread for the specified duration. 00255 * 00256 * @param cMillis the duration to pause the thread for. 00257 * 00258 * @throw InterruptedException if the thread is interrupted while 00259 * sleeping. 00260 */ 00261 static void sleep(int64_t cMillis); 00262 00263 /** 00264 * Temporarily pause the current thread. 00265 */ 00266 static void yield(); 00267 00268 /** 00269 * Return the number of milliseconds before the calling thread will timeout. 00270 * 00271 * Note if the current thread is timed out then invoking this method will 00272 * also interrupt the thread. 00273 * 00274 * @return the number of remaining milliseconds, 0 if timed out, or Integer64::max_value if disabled. 00275 */ 00276 static int64_t remainingTimeoutMillis(); 00277 00278 /** 00279 * Return true if the calling thread is timed out. 00280 * 00281 * Note if the current thread is timed out then invoking this method will 00282 * also interrupt the thread. 00283 * 00284 * @return true if the calling thread is timed out 00285 */ 00286 static bool isTimedOut(); 00287 00288 protected: 00289 /** 00290 * Instruct all threads to perform maintenance. 00291 */ 00292 static void doGlobalMaintenance(Maintenance nMaintenance); 00293 00294 private: 00295 /** 00296 * Specify the thread's timeout 00297 */ 00298 void setTimeout(int64_t timeout); 00299 00300 /** 00301 * Return the thread's timeout. 00302 */ 00303 int64_t getTimeout() const; 00304 00305 00306 // ----- Object interface ----------------------------------------------- 00307 00308 public: 00309 /** 00310 * {@inheritDoc} 00311 * 00312 * If the associated Runnable implements the 00313 * coherence::util::Describable interface that content will be included 00314 * as well. 00315 */ 00316 virtual TypedHandle<const String> toString() const; 00317 00318 00319 // ----- data members --------------------------------------------------- 00320 00321 protected: 00322 /** 00323 * The thread's group. 00324 */ 00325 MemberHandle<ThreadGroup> m_hGroup; 00326 00327 /** 00328 * The inner runnable associated with this Thread. 00329 */ 00330 MemberHandle<Runnable> m_hRunnable; 00331 00332 /** 00333 * The thread's name. 00334 */ 00335 MemberView<String> m_vsName; 00336 00337 /** 00338 * The thread's description. 00339 */ 00340 FinalView<String> f_vsDescription; 00341 00342 /** 00343 * The configured stack size; 00344 */ 00345 size32_t m_cBytesStack; 00346 00347 /** 00348 * The current thread state. 00349 */ 00350 Volatile<int32_t> m_nState; 00351 00352 /** 00353 * Bit mask identifying required maintenance tasks. 00354 */ 00355 mutable int m_nMaintenanceMask; 00356 00357 /** 00358 * The thread's timeout value. Value which are greater or equal to zero are used to indicate 00359 * timeout timestamps. Negative values are relative timeouts which haven't yet been 00360 * realized into a timestamp. This allows for an optimization where we can avoid obtaining 00361 * the current time when "setting" the timeout, and defer it until we are about to block. 00362 */ 00363 int64_t m_lTimeout; 00364 00365 00366 // ----- friends -------------------------------------------------------- 00367 00368 friend void coh_thread_cleanup(Thread*); 00369 friend Thread* coh_thread_current(); 00370 friend class System; 00371 friend class TimeoutBlock; 00372 }; 00373 00374 COH_CLOSE_NAMESPACE2 00375 00376 #endif // COH_THREAD_HPP