Panda3D
|
00001 // Filename: threadSimpleImpl.h 00002 // Created by: drose (18Jun07) 00003 // 00004 //////////////////////////////////////////////////////////////////// 00005 // 00006 // PANDA 3D SOFTWARE 00007 // Copyright (c) Carnegie Mellon University. All rights reserved. 00008 // 00009 // All use of this software is subject to the terms of the revised BSD 00010 // license. You should have received a copy of this license along 00011 // with this source code in a file named "LICENSE." 00012 // 00013 //////////////////////////////////////////////////////////////////// 00014 00015 #ifndef THREADSIMPLEIMPL_H 00016 #define THREADSIMPLEIMPL_H 00017 00018 #include "pandabase.h" 00019 #include "selectThreadImpl.h" 00020 00021 #ifdef THREAD_SIMPLE_IMPL 00022 00023 #include "pnotify.h" 00024 #include "threadPriority.h" 00025 #include "pvector.h" 00026 #include "contextSwitch.h" 00027 00028 #ifdef HAVE_PYTHON 00029 00030 #undef _POSIX_C_SOURCE 00031 #include <Python.h> 00032 00033 #endif // HAVE_PYTHON 00034 00035 class Thread; 00036 class ThreadSimpleManager; 00037 class MutexSimpleImpl; 00038 00039 //////////////////////////////////////////////////////////////////// 00040 // Class : ThreadSimpleImpl 00041 // Description : This is a trivial threading implementation for 00042 // applications that don't desire full OS-managed 00043 // threading. It is a user-space implementation of 00044 // threads implemented via setjmp/longjmp, and therefore 00045 // it cannot take advantage of multiple CPU's (the 00046 // application will always run on a single CPU, 00047 // regardless of the number of threads you spawn). 00048 // 00049 // However, since context switching is entirely 00050 // cooperative, synchronization primitives like mutexes 00051 // and condition variables aren't necessary, and the 00052 // Mutex and ConditionVar classes are compiled into 00053 // trivial no-op classes, which can reduce overhead 00054 // substantially compared to a truly threaded 00055 // application. 00056 // 00057 // Be sure that every thread calls 00058 // Thread::consider_yield() occasionally, or it will 00059 // starve the rest of the running threads. 00060 //////////////////////////////////////////////////////////////////// 00061 class EXPCL_PANDA_PIPELINE ThreadSimpleImpl { 00062 public: 00063 ThreadSimpleImpl(Thread *parent_obj); 00064 ~ThreadSimpleImpl(); 00065 00066 void setup_main_thread(); 00067 bool start(ThreadPriority priority, bool joinable); 00068 void join(); 00069 void preempt(); 00070 00071 string get_unique_id() const; 00072 00073 static void prepare_for_exit(); 00074 00075 INLINE static Thread *get_current_thread(); 00076 INLINE bool is_same_system_thread() const; 00077 00078 INLINE static void bind_thread(Thread *thread); 00079 INLINE static bool is_threading_supported(); 00080 INLINE static bool is_true_threads(); 00081 INLINE static bool is_simple_threads(); 00082 INLINE static void sleep(double seconds); 00083 INLINE static void yield(); 00084 INLINE static void consider_yield(); 00085 00086 void sleep_this(double seconds); 00087 void yield_this(bool volunteer); 00088 INLINE void consider_yield_this(); 00089 00090 INLINE double get_wake_time() const; 00091 00092 INLINE static void write_status(ostream &out); 00093 00094 private: 00095 static void st_begin_thread(void *data); 00096 void begin_thread(); 00097 00098 private: 00099 enum ThreadStatus { 00100 TS_new, 00101 TS_running, 00102 TS_finished, 00103 TS_killed, 00104 }; 00105 00106 static int _next_unique_id; 00107 int _unique_id; 00108 Thread *_parent_obj; 00109 bool _joinable; 00110 ThreadStatus _status; 00111 ThreadPriority _priority; 00112 00113 // The relative weight of this thread, relative to other threads, in 00114 // priority. 00115 double _priority_weight; 00116 00117 // The amount of time this thread has run recently. 00118 unsigned int _run_ticks; 00119 00120 // This is the time at which the currently-running thread started 00121 // execution. 00122 double _start_time; 00123 00124 // This is the time at which the currently-running thread should 00125 // yield. 00126 double _stop_time; 00127 00128 // This records the time at which a sleeping thread should wake up. 00129 double _wake_time; 00130 00131 ThreadContext *_context; 00132 unsigned char *_stack; 00133 size_t _stack_size; 00134 00135 #ifdef HAVE_PYTHON 00136 // If we might be working with Python, we have to manage the Python 00137 // thread state as we switch contexts. 00138 PyThreadState *_python_state; 00139 #endif // HAVE_PYTHON 00140 00141 // Threads that are waiting for this thread to finish. 00142 typedef pvector<ThreadSimpleImpl *> JoiningThreads; 00143 JoiningThreads _joining_threads; 00144 00145 ThreadSimpleManager *_manager; 00146 static ThreadSimpleImpl *volatile _st_this; 00147 00148 // We may not mix-and-match OS threads with Panda's SIMPLE_THREADS. 00149 // If we ever get a Panda context switch request from a different OS 00150 // thread than the thread we think we should be in, that's a serious 00151 // error that may cause major consequences. For this reason, we 00152 // store the OS thread's current thread ID here when the thread is 00153 // constructed, and insist that it never changes during the lifetime 00154 // of the thread. 00155 #ifdef HAVE_POSIX_THREADS 00156 pthread_t _posix_system_thread_id; 00157 #endif 00158 #ifdef WIN32 00159 DWORD _win32_system_thread_id; 00160 #endif 00161 00162 friend class ThreadSimpleManager; 00163 }; 00164 00165 // We include this down here to avoid the circularity problem. 00166 /* okcircular */ 00167 #include "threadSimpleManager.h" 00168 00169 #include "threadSimpleImpl.I" 00170 00171 #endif // THREAD_SIMPLE_IMPL 00172 00173 #endif