Panda3D

threadSimpleManager.h

00001 // Filename: threadSimpleManager.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 THREADSIMPLEMANAGER_H
00016 #define THREADSIMPLEMANAGER_H
00017 
00018 #include "pandabase.h"
00019 #include "selectThreadImpl.h"
00020 
00021 #ifdef THREAD_SIMPLE_IMPL
00022 
00023 #include "pdeque.h"
00024 #include "pmap.h"
00025 #include "pvector.h"
00026 #include "trueClock.h"
00027 #include "configVariableDouble.h"
00028 #include <algorithm>
00029 
00030 #ifdef HAVE_POSIX_THREADS
00031 #include <pthread.h>  // for pthread_t, below
00032 #endif
00033 #ifdef WIN32
00034 #define WIN32_LEAN_AND_MEAN
00035 #include <windows.h>  // for DWORD, below
00036 #endif
00037 
00038 class Thread;
00039 class ThreadSimpleImpl;
00040 class BlockerSimple;
00041 struct ThreadContext;
00042 
00043 ////////////////////////////////////////////////////////////////////
00044 //       Class : ThreadSimpleManager
00045 // Description : This is the global object that selects the
00046 //               currently-active thread of the various
00047 //               ThreadSimpleImpl objects running, when the
00048 //               currently-active thread yields.
00049 //
00050 //               This class only exists when we are using the
00051 //               ThreadSimple implementation, which is to say, we are
00052 //               not using "real" threads.
00053 //
00054 //               Generally, you shouldn't be calling these methods
00055 //               directly.  Call the interfaces on Thread instead.
00056 ////////////////////////////////////////////////////////////////////
00057 class EXPCL_PANDA_PIPELINE ThreadSimpleManager {
00058 private:
00059   ThreadSimpleManager();
00060 
00061 public:
00062   void enqueue_ready(ThreadSimpleImpl *thread, bool volunteer);
00063   void enqueue_sleep(ThreadSimpleImpl *thread, double seconds);
00064   void enqueue_block(ThreadSimpleImpl *thread, BlockerSimple *blocker);
00065   bool unblock_one(BlockerSimple *blocker);
00066   bool unblock_all(BlockerSimple *blocker);
00067   void enqueue_finished(ThreadSimpleImpl *thread);
00068   void preempt(ThreadSimpleImpl *thread);
00069   void next_context();
00070 
00071   void prepare_for_exit();
00072 
00073   INLINE ThreadSimpleImpl *get_current_thread();
00074   void set_current_thread(ThreadSimpleImpl *current_thread);
00075   INLINE bool is_same_system_thread() const;
00076   void remove_thread(ThreadSimpleImpl *thread);
00077   static void system_sleep(double seconds);
00078   static void system_yield();
00079 
00080   double get_current_time() const;
00081   INLINE static ThreadSimpleManager *get_global_ptr();
00082 
00083   void write_status(ostream &out) const;
00084 
00085 private:
00086   static void init_pointers();
00087 
00088   typedef pdeque<ThreadSimpleImpl *> FifoThreads;
00089   typedef pvector<ThreadSimpleImpl *> Sleeping;
00090 
00091   static void st_choose_next_context(struct ThreadContext *from_context, void *data);
00092   void choose_next_context(struct ThreadContext *from_context);
00093   void do_timeslice_accounting(ThreadSimpleImpl *thread, double now);
00094   void wake_sleepers(Sleeping &sleepers, double now);
00095   void wake_all_sleepers(Sleeping &sleepers);
00096   void report_deadlock();
00097   double determine_timeslice(ThreadSimpleImpl *chosen_thread);
00098   void kill_non_joinable(FifoThreads &threads);
00099   void kill_non_joinable(Sleeping &threads);
00100 
00101   // STL function object to sort the priority queue of sleeping threads.
00102   class CompareStartTime {
00103   public:
00104     INLINE bool operator ()(ThreadSimpleImpl *a, ThreadSimpleImpl *b) const;
00105   };
00106 
00107 public:
00108   // Defined within the class to avoid static-init ordering problems.
00109   ConfigVariableDouble _simple_thread_epoch_timeslice;
00110   ConfigVariableDouble _simple_thread_volunteer_delay;
00111   ConfigVariableDouble _simple_thread_yield_sleep;
00112   ConfigVariableDouble _simple_thread_window;
00113   ConfigVariableDouble _simple_thread_low_weight;
00114   ConfigVariableDouble _simple_thread_normal_weight;
00115   ConfigVariableDouble _simple_thread_high_weight;
00116   ConfigVariableDouble _simple_thread_urgent_weight;
00117 
00118 private:
00119   ThreadSimpleImpl *volatile _current_thread;
00120 
00121   // The list of ready threads: threads that are ready to execute
00122   // right now.
00123   FifoThreads _ready;
00124 
00125   // The list of threads that are ready, but will not be executed
00126   // until next epoch (for instance, because they exceeded their
00127   // timeslice budget this epoch).
00128   FifoThreads _next_ready;
00129 
00130   // The list of threads that are blocked on some ConditionVar or
00131   // Mutex.
00132   typedef pmap<BlockerSimple *, FifoThreads> Blocked;
00133   Blocked _blocked;
00134 
00135   // Priority queue (partially-ordered heap) of sleeping threads,
00136   // based on wakeup time.
00137   Sleeping _sleeping;
00138 
00139   // Priority queue (partially-ordered heap) of volunteer threads,
00140   // based on wakeup time.  This are threads that have voluntarily
00141   // yielded a timeslice.  They are treated the same as sleeping
00142   // threads, unless all threads are sleeping.
00143   Sleeping _volunteers;
00144 
00145   // Threads which have finished execution and are awaiting cleanup.
00146   FifoThreads _finished;
00147 
00148   ThreadSimpleImpl *_waiting_for_exit;
00149 
00150   TrueClock *_clock;
00151 
00152   double _tick_scale;
00153 
00154   class TickRecord {
00155   public:
00156     unsigned int _tick_count;
00157     ThreadSimpleImpl *_thread;
00158   };
00159   typedef pdeque<TickRecord> TickRecords;
00160   TickRecords _tick_records;
00161   unsigned int _total_ticks;
00162 
00163   static bool _pointers_initialized;
00164   static ThreadSimpleManager *_global_ptr;
00165 };
00166 
00167 // We include this down here to avoid the circularity problem.
00168 /* okcircular */
00169 #include "threadSimpleImpl.h"
00170 
00171 #include "threadSimpleManager.I"
00172 
00173 #endif // THREAD_SIMPLE_IMPL
00174 
00175 #endif
 All Classes Functions Variables Enumerations