Panda3D
 All Classes Functions Variables Enumerations
asyncTaskChain.h
00001 // Filename: asyncTaskChain.h
00002 // Created by:  drose (23Aug06)
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 ASYNCTASKCHAIN_H
00016 #define ASYNCTASKCHAIN_H
00017 
00018 #include "pandabase.h"
00019 
00020 #include "asyncTask.h"
00021 #include "asyncTaskCollection.h"
00022 #include "typedReferenceCount.h"
00023 #include "thread.h"
00024 #include "conditionVarFull.h"
00025 #include "pvector.h"
00026 #include "pdeque.h"
00027 #include "pStatCollector.h"
00028 #include "clockObject.h"
00029 
00030 class AsyncTaskManager;
00031 
00032 ////////////////////////////////////////////////////////////////////
00033 //       Class : AsyncTaskChain
00034 // Description : The AsyncTaskChain is a subset of the
00035 //               AsyncTaskManager.  Each chain maintains a separate
00036 //               list of tasks, and will execute them with its own set
00037 //               of threads.  Each chain may thereby operate
00038 //               independently of the other chains.
00039 //
00040 //               The AsyncTaskChain will spawn a specified number of
00041 //               threads (possibly 0) to serve the tasks.  If there
00042 //               are no threads, you must call poll() from time to
00043 //               time to serve the tasks in the main thread.  Normally
00044 //               this is done by calling AsyncTaskManager::poll().
00045 //
00046 //               Each task will run exactly once each epoch.  Beyond
00047 //               that, the tasks' sort and priority values control the
00048 //               order in which they are run: tasks are run in
00049 //               increasing order by sort value, and within the same
00050 //               sort value, they are run roughly in decreasing order
00051 //               by priority value, with some exceptions for
00052 //               parallelism.  Tasks with different sort values are
00053 //               never run in parallel together, but tasks with
00054 //               different priority values might be (if there is more
00055 //               than one thread).
00056 ////////////////////////////////////////////////////////////////////
00057 class EXPCL_PANDA_EVENT AsyncTaskChain : public TypedReferenceCount, public Namable {
00058 public:
00059   AsyncTaskChain(AsyncTaskManager *manager, const string &name);
00060   ~AsyncTaskChain();
00061 
00062 PUBLISHED:
00063   void set_tick_clock(bool tick_clock);
00064   bool get_tick_clock() const;
00065 
00066   BLOCKING void set_num_threads(int num_threads);
00067   int get_num_threads() const;
00068   int get_num_running_threads() const;
00069 
00070   BLOCKING void set_thread_priority(ThreadPriority priority);
00071   ThreadPriority get_thread_priority() const;
00072 
00073   void set_frame_budget(double frame_budget);
00074   double get_frame_budget() const;
00075 
00076   void set_frame_sync(bool frame_sync);
00077   bool get_frame_sync() const;
00078 
00079   void set_timeslice_priority(bool timeslice_priority);
00080   bool get_timeslice_priority() const;
00081 
00082   BLOCKING void stop_threads();
00083   void start_threads();
00084   INLINE bool is_started() const;
00085 
00086   bool has_task(AsyncTask *task) const;
00087 
00088   BLOCKING void wait_for_tasks();
00089 
00090   int get_num_tasks() const;
00091   AsyncTaskCollection get_tasks() const;
00092   AsyncTaskCollection get_active_tasks() const;
00093   AsyncTaskCollection get_sleeping_tasks() const;
00094 
00095   void poll();
00096   double get_next_wake_time() const;
00097 
00098   virtual void output(ostream &out) const;
00099   virtual void write(ostream &out, int indent_level = 0) const;
00100 
00101 protected:
00102   class AsyncTaskChainThread;
00103   typedef pvector< PT(AsyncTask) > TaskHeap;
00104 
00105   void do_add(AsyncTask *task);
00106   bool do_remove(AsyncTask *task);
00107   void do_wait_for_tasks();
00108   void do_cleanup();
00109 
00110   bool do_has_task(AsyncTask *task) const;
00111   int find_task_on_heap(const TaskHeap &heap, AsyncTask *task) const;
00112 
00113   void service_one_task(AsyncTaskChainThread *thread);
00114   void cleanup_task(AsyncTask *task, bool upon_death, bool clean_exit);
00115   bool finish_sort_group();
00116   void filter_timeslice_priority();
00117   void do_stop_threads();
00118   void do_start_threads();
00119   AsyncTaskCollection do_get_active_tasks() const;
00120   AsyncTaskCollection do_get_sleeping_tasks() const;
00121   void do_poll();
00122   void cleanup_pickup_mode();
00123   INLINE double do_get_next_wake_time() const;
00124   static INLINE double get_wake_time(AsyncTask *task);
00125   void do_output(ostream &out) const;
00126   void do_write(ostream &out, int indent_level) const;
00127 
00128   void write_task_line(ostream &out, int indent_level, AsyncTask *task, double now) const;
00129 
00130 protected:
00131   class AsyncTaskChainThread : public Thread {
00132   public:
00133     AsyncTaskChainThread(const string &name, AsyncTaskChain *chain);
00134     virtual void thread_main();
00135 
00136     AsyncTaskChain *_chain;
00137     AsyncTask *_servicing;
00138   };
00139 
00140   class AsyncTaskSortWakeTime {
00141   public:
00142     bool operator () (AsyncTask *a, AsyncTask *b) const {
00143       return AsyncTaskChain::get_wake_time(a) > AsyncTaskChain::get_wake_time(b);
00144     }
00145   };
00146   
00147   class AsyncTaskSortPriority {
00148   public:
00149     bool operator () (AsyncTask *a, AsyncTask *b) const {
00150       if (a->get_sort() != b->get_sort()) {
00151         return a->get_sort() > b->get_sort();
00152       }
00153       if (a->get_priority() != b->get_priority()) {
00154         return a->get_priority() < b->get_priority();
00155       }
00156       return a->get_start_time() > b->get_start_time();
00157     }
00158   };
00159 
00160   typedef pvector< PT(AsyncTaskChainThread) > Threads;
00161 
00162   AsyncTaskManager *_manager;
00163 
00164   ConditionVarFull _cvar;  // signaled when one of the task heaps, _state, or _current_sort changes, or a task finishes.
00165 
00166   enum State {
00167     S_initial,     // no threads yet
00168     S_started,     // threads have been started
00169     S_interrupted, // task returned DS_interrupt, requested from sub-thread.
00170     S_shutdown     // waiting for thread shutdown, requested from main thread
00171   };
00172 
00173   bool _tick_clock;
00174   bool _timeslice_priority;
00175   int _num_threads;
00176   ThreadPriority _thread_priority;
00177   Threads _threads;
00178   double _frame_budget;
00179   bool _frame_sync;
00180   int _num_busy_threads;
00181   int _num_tasks;
00182   TaskHeap _active;
00183   TaskHeap _this_active;
00184   TaskHeap _next_active;
00185   TaskHeap _sleeping;
00186   State _state;
00187   int _current_sort;
00188   bool _pickup_mode;
00189   bool _needs_cleanup;
00190 
00191   int _current_frame;
00192   double _time_in_frame;
00193   bool _block_till_next_frame;
00194   
00195   static PStatCollector _task_pcollector;
00196   static PStatCollector _wait_pcollector;
00197 
00198 public:
00199   static TypeHandle get_class_type() {
00200     return _type_handle;
00201   }
00202   static void init_type() {
00203     TypedReferenceCount::init_type();
00204     register_type(_type_handle, "AsyncTaskChain",
00205                   TypedReferenceCount::get_class_type());
00206   }
00207   virtual TypeHandle get_type() const {
00208     return get_class_type();
00209   }
00210   virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
00211 
00212 private:
00213   static TypeHandle _type_handle;
00214 
00215   friend class AsyncTaskChainThread;
00216   friend class AsyncTask;
00217   friend class AsyncTaskManager;
00218   friend class AsyncTaskSortWakeTime;
00219 };
00220 
00221 INLINE ostream &operator << (ostream &out, const AsyncTaskChain &chain) {
00222   chain.output(out);
00223   return out;
00224 };
00225 
00226 #include "asyncTaskChain.I"
00227 
00228 #endif
 All Classes Functions Variables Enumerations