Panda3D
 All Classes Functions Variables Enumerations
threadSimpleImpl.h
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
 All Classes Functions Variables Enumerations