Panda3D
threadSimpleImpl.h
1 // Filename: threadSimpleImpl.h
2 // Created by: drose (18Jun07)
3 //
4 ////////////////////////////////////////////////////////////////////
5 //
6 // PANDA 3D SOFTWARE
7 // Copyright (c) Carnegie Mellon University. All rights reserved.
8 //
9 // All use of this software is subject to the terms of the revised BSD
10 // license. You should have received a copy of this license along
11 // with this source code in a file named "LICENSE."
12 //
13 ////////////////////////////////////////////////////////////////////
14 
15 #ifndef THREADSIMPLEIMPL_H
16 #define THREADSIMPLEIMPL_H
17 
18 #include "pandabase.h"
19 #include "selectThreadImpl.h"
20 
21 #ifdef THREAD_SIMPLE_IMPL
22 
23 #include "pnotify.h"
24 #include "threadPriority.h"
25 #include "pvector.h"
26 #include "contextSwitch.h"
27 
28 #ifdef HAVE_PYTHON
29 
30 #undef _POSIX_C_SOURCE
31 #include <Python.h>
32 
33 #endif // HAVE_PYTHON
34 
35 class Thread;
36 class ThreadSimpleManager;
37 class MutexSimpleImpl;
38 
39 ////////////////////////////////////////////////////////////////////
40 // Class : ThreadSimpleImpl
41 // Description : This is a trivial threading implementation for
42 // applications that don't desire full OS-managed
43 // threading. It is a user-space implementation of
44 // threads implemented via setjmp/longjmp, and therefore
45 // it cannot take advantage of multiple CPU's (the
46 // application will always run on a single CPU,
47 // regardless of the number of threads you spawn).
48 //
49 // However, since context switching is entirely
50 // cooperative, synchronization primitives like mutexes
51 // and condition variables aren't necessary, and the
52 // Mutex and ConditionVar classes are compiled into
53 // trivial no-op classes, which can reduce overhead
54 // substantially compared to a truly threaded
55 // application.
56 //
57 // Be sure that every thread calls
58 // Thread::consider_yield() occasionally, or it will
59 // starve the rest of the running threads.
60 ////////////////////////////////////////////////////////////////////
61 class EXPCL_PANDA_PIPELINE ThreadSimpleImpl {
62 public:
63  ThreadSimpleImpl(Thread *parent_obj);
64  ~ThreadSimpleImpl();
65 
66  void setup_main_thread();
67  bool start(ThreadPriority priority, bool joinable);
68  void join();
69  void preempt();
70 
71  string get_unique_id() const;
72 
73  static void prepare_for_exit();
74 
75  INLINE static Thread *get_current_thread();
76  INLINE bool is_same_system_thread() const;
77 
78  INLINE static void bind_thread(Thread *thread);
79  INLINE static bool is_threading_supported();
80  INLINE static bool is_true_threads();
81  INLINE static bool is_simple_threads();
82  INLINE static void sleep(double seconds);
83  INLINE static void yield();
84  INLINE static void consider_yield();
85 
86  void sleep_this(double seconds);
87  void yield_this(bool volunteer);
88  INLINE void consider_yield_this();
89 
90  INLINE double get_wake_time() const;
91 
92  INLINE static void write_status(ostream &out);
93 
94 private:
95  static void st_begin_thread(void *data);
96  void begin_thread();
97 
98 private:
99  enum ThreadStatus {
100  TS_new,
101  TS_running,
102  TS_finished,
103  TS_killed,
104  };
105 
106  static int _next_unique_id;
107  int _unique_id;
108  Thread *_parent_obj;
109  bool _joinable;
110  ThreadStatus _status;
111  ThreadPriority _priority;
112 
113  // The relative weight of this thread, relative to other threads, in
114  // priority.
115  double _priority_weight;
116 
117  // The amount of time this thread has run recently.
118  unsigned int _run_ticks;
119 
120  // This is the time at which the currently-running thread started
121  // execution.
122  double _start_time;
123 
124  // This is the time at which the currently-running thread should
125  // yield.
126  double _stop_time;
127 
128  // This records the time at which a sleeping thread should wake up.
129  double _wake_time;
130 
131  ThreadContext *_context;
132  unsigned char *_stack;
133  size_t _stack_size;
134 
135 #ifdef HAVE_PYTHON
136  // If we might be working with Python, we have to manage the Python
137  // thread state as we switch contexts.
138  PyThreadState *_python_state;
139 #endif // HAVE_PYTHON
140 
141  // Threads that are waiting for this thread to finish.
142  typedef pvector<ThreadSimpleImpl *> JoiningThreads;
143  JoiningThreads _joining_threads;
144 
145  ThreadSimpleManager *_manager;
146  static ThreadSimpleImpl *volatile _st_this;
147 
148  // We may not mix-and-match OS threads with Panda's SIMPLE_THREADS.
149  // If we ever get a Panda context switch request from a different OS
150  // thread than the thread we think we should be in, that's a serious
151  // error that may cause major consequences. For this reason, we
152  // store the OS thread's current thread ID here when the thread is
153  // constructed, and insist that it never changes during the lifetime
154  // of the thread.
155 #ifdef HAVE_POSIX_THREADS
156  pthread_t _posix_system_thread_id;
157 #endif
158 #ifdef WIN32
159  DWORD _win32_system_thread_id;
160 #endif
161 
162  friend class ThreadSimpleManager;
163 };
164 
165 // We include this down here to avoid the circularity problem.
166 /* okcircular */
167 #include "threadSimpleManager.h"
168 
169 #include "threadSimpleImpl.I"
170 
171 #endif // THREAD_SIMPLE_IMPL
172 
173 #endif
This is our own Panda specialization on the default STL vector.
Definition: pvector.h:39
A thread; that is, a lightweight process.
Definition: thread.h:51