// Filename: threadSimpleManager.h // Created by: drose (18Jun07) // //////////////////////////////////////////////////////////////////// // // PANDA 3D SOFTWARE // Copyright (c) Carnegie Mellon University. All rights reserved. // // All use of this software is subject to the terms of the revised BSD // license. You should have received a copy of this license along // with this source code in a file named "LICENSE." // //////////////////////////////////////////////////////////////////// #ifndef THREADSIMPLEMANAGER_H #define THREADSIMPLEMANAGER_H #include "pandabase.h" #include "selectThreadImpl.h" #ifdef THREAD_SIMPLE_IMPL #include "pdeque.h" #include "pmap.h" #include "pvector.h" #include "trueClock.h" #include "configVariableDouble.h" #include #ifdef HAVE_POSIX_THREADS #include // for pthread_t, below #endif #ifdef WIN32 #define WIN32_LEAN_AND_MEAN #include // for DWORD, below #endif class Thread; class ThreadSimpleImpl; class BlockerSimple; struct ThreadContext; //////////////////////////////////////////////////////////////////// // Class : ThreadSimpleManager // Description : This is the global object that selects the // currently-active thread of the various // ThreadSimpleImpl objects running, when the // currently-active thread yields. // // This class only exists when we are using the // ThreadSimple implementation, which is to say, we are // not using "real" threads. // // Generally, you shouldn't be calling these methods // directly. Call the interfaces on Thread instead. //////////////////////////////////////////////////////////////////// class EXPCL_PANDA_PIPELINE ThreadSimpleManager { private: ThreadSimpleManager(); public: void enqueue_ready(ThreadSimpleImpl *thread, bool volunteer); void enqueue_sleep(ThreadSimpleImpl *thread, double seconds); void enqueue_block(ThreadSimpleImpl *thread, BlockerSimple *blocker); bool unblock_one(BlockerSimple *blocker); bool unblock_all(BlockerSimple *blocker); void enqueue_finished(ThreadSimpleImpl *thread); void preempt(ThreadSimpleImpl *thread); void next_context(); void prepare_for_exit(); INLINE ThreadSimpleImpl *get_current_thread(); void set_current_thread(ThreadSimpleImpl *current_thread); INLINE bool is_same_system_thread() const; void remove_thread(ThreadSimpleImpl *thread); static void system_sleep(double seconds); static void system_yield(); double get_current_time() const; INLINE static ThreadSimpleManager *get_global_ptr(); void write_status(ostream &out) const; private: static void init_pointers(); typedef pdeque FifoThreads; typedef pvector Sleeping; static void st_choose_next_context(struct ThreadContext *from_context, void *data); void choose_next_context(struct ThreadContext *from_context); void do_timeslice_accounting(ThreadSimpleImpl *thread, double now); void wake_sleepers(Sleeping &sleepers, double now); void wake_all_sleepers(Sleeping &sleepers); void report_deadlock(); double determine_timeslice(ThreadSimpleImpl *chosen_thread); void kill_non_joinable(FifoThreads &threads); void kill_non_joinable(Sleeping &threads); // STL function object to sort the priority queue of sleeping threads. class CompareStartTime { public: INLINE bool operator ()(ThreadSimpleImpl *a, ThreadSimpleImpl *b) const; }; public: // Defined within the class to avoid static-init ordering problems. ConfigVariableDouble _simple_thread_epoch_timeslice; ConfigVariableDouble _simple_thread_volunteer_delay; ConfigVariableDouble _simple_thread_yield_sleep; ConfigVariableDouble _simple_thread_window; ConfigVariableDouble _simple_thread_low_weight; ConfigVariableDouble _simple_thread_normal_weight; ConfigVariableDouble _simple_thread_high_weight; ConfigVariableDouble _simple_thread_urgent_weight; private: ThreadSimpleImpl *volatile _current_thread; // The list of ready threads: threads that are ready to execute // right now. FifoThreads _ready; // The list of threads that are ready, but will not be executed // until next epoch (for instance, because they exceeded their // timeslice budget this epoch). FifoThreads _next_ready; // The list of threads that are blocked on some ConditionVar or // Mutex. typedef pmap Blocked; Blocked _blocked; // Priority queue (partially-ordered heap) of sleeping threads, // based on wakeup time. Sleeping _sleeping; // Priority queue (partially-ordered heap) of volunteer threads, // based on wakeup time. This are threads that have voluntarily // yielded a timeslice. They are treated the same as sleeping // threads, unless all threads are sleeping. Sleeping _volunteers; // Threads which have finished execution and are awaiting cleanup. FifoThreads _finished; ThreadSimpleImpl *_waiting_for_exit; TrueClock *_clock; double _tick_scale; class TickRecord { public: unsigned int _tick_count; ThreadSimpleImpl *_thread; }; typedef pdeque TickRecords; TickRecords _tick_records; unsigned int _total_ticks; static bool _pointers_initialized; static ThreadSimpleManager *_global_ptr; }; // We include this down here to avoid the circularity problem. /* okcircular */ #include "threadSimpleImpl.h" #include "threadSimpleManager.I" #endif // THREAD_SIMPLE_IMPL #endif