Panda3D
threadSimpleManager.h
1 // Filename: threadSimpleManager.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 THREADSIMPLEMANAGER_H
16 #define THREADSIMPLEMANAGER_H
17 
18 #include "pandabase.h"
19 #include "selectThreadImpl.h"
20 
21 #ifdef THREAD_SIMPLE_IMPL
22 
23 #include "pdeque.h"
24 #include "pmap.h"
25 #include "pvector.h"
26 #include "trueClock.h"
27 #include "configVariableDouble.h"
28 #include <algorithm>
29 
30 #ifdef HAVE_POSIX_THREADS
31 #include <pthread.h> // for pthread_t, below
32 #endif
33 #ifdef WIN32
34 #ifndef WIN32_LEAN_AND_MEAN
35 #define WIN32_LEAN_AND_MEAN 1
36 #endif
37 #include <windows.h> // for DWORD, below
38 #endif
39 
40 class Thread;
41 class ThreadSimpleImpl;
42 class BlockerSimple;
43 struct ThreadContext;
44 
45 ////////////////////////////////////////////////////////////////////
46 // Class : ThreadSimpleManager
47 // Description : This is the global object that selects the
48 // currently-active thread of the various
49 // ThreadSimpleImpl objects running, when the
50 // currently-active thread yields.
51 //
52 // This class only exists when we are using the
53 // ThreadSimple implementation, which is to say, we are
54 // not using "real" threads.
55 //
56 // Generally, you shouldn't be calling these methods
57 // directly. Call the interfaces on Thread instead.
58 ////////////////////////////////////////////////////////////////////
59 class EXPCL_PANDA_PIPELINE ThreadSimpleManager {
60 private:
61  ThreadSimpleManager();
62 
63 public:
64  void enqueue_ready(ThreadSimpleImpl *thread, bool volunteer);
65  void enqueue_sleep(ThreadSimpleImpl *thread, double seconds);
66  void enqueue_block(ThreadSimpleImpl *thread, BlockerSimple *blocker);
67  bool unblock_one(BlockerSimple *blocker);
68  bool unblock_all(BlockerSimple *blocker);
69  void enqueue_finished(ThreadSimpleImpl *thread);
70  void preempt(ThreadSimpleImpl *thread);
71  void next_context();
72 
73  void prepare_for_exit();
74 
75  INLINE ThreadSimpleImpl *get_current_thread();
76  void set_current_thread(ThreadSimpleImpl *current_thread);
77  INLINE bool is_same_system_thread() const;
78  void remove_thread(ThreadSimpleImpl *thread);
79  static void system_sleep(double seconds);
80  static void system_yield();
81 
82  double get_current_time() const;
83  INLINE static ThreadSimpleManager *get_global_ptr();
84 
85  void write_status(ostream &out) const;
86 
87 private:
88  static void init_pointers();
89 
90  typedef pdeque<ThreadSimpleImpl *> FifoThreads;
91  typedef pvector<ThreadSimpleImpl *> Sleeping;
92 
93  static void st_choose_next_context(struct ThreadContext *from_context, void *data);
94  void choose_next_context(struct ThreadContext *from_context);
95  void do_timeslice_accounting(ThreadSimpleImpl *thread, double now);
96  void wake_sleepers(Sleeping &sleepers, double now);
97  void wake_all_sleepers(Sleeping &sleepers);
98  void report_deadlock();
99  double determine_timeslice(ThreadSimpleImpl *chosen_thread);
100  void kill_non_joinable(FifoThreads &threads);
101  void kill_non_joinable(Sleeping &threads);
102 
103  // STL function object to sort the priority queue of sleeping threads.
104  class CompareStartTime {
105  public:
106  INLINE bool operator ()(ThreadSimpleImpl *a, ThreadSimpleImpl *b) const;
107  };
108 
109 public:
110  // Defined within the class to avoid static-init ordering problems.
111  ConfigVariableDouble _simple_thread_epoch_timeslice;
112  ConfigVariableDouble _simple_thread_volunteer_delay;
113  ConfigVariableDouble _simple_thread_yield_sleep;
114  ConfigVariableDouble _simple_thread_window;
115  ConfigVariableDouble _simple_thread_low_weight;
116  ConfigVariableDouble _simple_thread_normal_weight;
117  ConfigVariableDouble _simple_thread_high_weight;
118  ConfigVariableDouble _simple_thread_urgent_weight;
119 
120 private:
121  ThreadSimpleImpl *volatile _current_thread;
122 
123  // The list of ready threads: threads that are ready to execute
124  // right now.
125  FifoThreads _ready;
126 
127  // The list of threads that are ready, but will not be executed
128  // until next epoch (for instance, because they exceeded their
129  // timeslice budget this epoch).
130  FifoThreads _next_ready;
131 
132  // The list of threads that are blocked on some ConditionVar or
133  // Mutex.
134  typedef pmap<BlockerSimple *, FifoThreads> Blocked;
135  Blocked _blocked;
136 
137  // Priority queue (partially-ordered heap) of sleeping threads,
138  // based on wakeup time.
139  Sleeping _sleeping;
140 
141  // Priority queue (partially-ordered heap) of volunteer threads,
142  // based on wakeup time. This are threads that have voluntarily
143  // yielded a timeslice. They are treated the same as sleeping
144  // threads, unless all threads are sleeping.
145  Sleeping _volunteers;
146 
147  // Threads which have finished execution and are awaiting cleanup.
148  FifoThreads _finished;
149 
150  ThreadSimpleImpl *_waiting_for_exit;
151 
152  TrueClock *_clock;
153 
154  double _tick_scale;
155 
156  class TickRecord {
157  public:
158  unsigned int _tick_count;
159  ThreadSimpleImpl *_thread;
160  };
161  typedef pdeque<TickRecord> TickRecords;
162  TickRecords _tick_records;
163  unsigned int _total_ticks;
164 
165  static bool _pointers_initialized;
166  static ThreadSimpleManager *_global_ptr;
167 };
168 
169 // We include this down here to avoid the circularity problem.
170 /* okcircular */
171 #include "threadSimpleImpl.h"
172 
173 #include "threadSimpleManager.I"
174 
175 #endif // THREAD_SIMPLE_IMPL
176 
177 #endif
This is our own Panda specialization on the default STL map.
Definition: pmap.h:52
This is our own Panda specialization on the default STL deque.
Definition: pdeque.h:38
This is our own Panda specialization on the default STL vector.
Definition: pvector.h:39
This is a convenience class to specialize ConfigVariable as a floating-point type.
An interface to whatever real-time clock we might have available in the current environment.
Definition: trueClock.h:38
A thread; that is, a lightweight process.
Definition: thread.h:51