diff --git a/panda/src/audio/audioLoadRequest.I b/panda/src/audio/audioLoadRequest.I index ab7d458855..43d38c5191 100644 --- a/panda/src/audio/audioLoadRequest.I +++ b/panda/src/audio/audioLoadRequest.I @@ -26,7 +26,6 @@ INLINE AudioLoadRequest:: AudioLoadRequest(AudioManager *audio_manager, const string &filename, bool positional) : - AsyncTask(filename), _audio_manager(audio_manager), _filename(filename), _positional(positional), diff --git a/panda/src/audio/audioLoadRequest.h b/panda/src/audio/audioLoadRequest.h index 4e08a9522f..b4c75d4be4 100644 --- a/panda/src/audio/audioLoadRequest.h +++ b/panda/src/audio/audioLoadRequest.h @@ -36,6 +36,9 @@ // an asynchronous load. //////////////////////////////////////////////////////////////////// class EXPCL_PANDA_AUDIO AudioLoadRequest : public AsyncTask { +public: + ALLOC_DELETED_CHAIN(AudioLoadRequest); + PUBLISHED: INLINE AudioLoadRequest(AudioManager *audio_manager, const string &filename, bool positional); diff --git a/panda/src/event/asyncTask.I b/panda/src/event/asyncTask.I index 5e3753d3ba..93b07b8668 100644 --- a/panda/src/event/asyncTask.I +++ b/panda/src/event/asyncTask.I @@ -23,8 +23,7 @@ // Description: //////////////////////////////////////////////////////////////////// INLINE AsyncTask:: -AsyncTask(const string &name) : - Namable(name), +AsyncTask() : _state(S_inactive), _manager(NULL) { diff --git a/panda/src/event/asyncTask.cxx b/panda/src/event/asyncTask.cxx index 85b4a9820f..3a80fcab18 100644 --- a/panda/src/event/asyncTask.cxx +++ b/panda/src/event/asyncTask.cxx @@ -37,5 +37,5 @@ AsyncTask:: //////////////////////////////////////////////////////////////////// void AsyncTask:: output(ostream &out) const { - out << get_type() << " " << get_name(); + out << get_type(); } diff --git a/panda/src/event/asyncTask.h b/panda/src/event/asyncTask.h index 91f3854c38..808fa79ca7 100644 --- a/panda/src/event/asyncTask.h +++ b/panda/src/event/asyncTask.h @@ -43,10 +43,11 @@ class AsyncTaskManager; // class, and override do_task(), to define the // functionality you wish to have the task perform. //////////////////////////////////////////////////////////////////// -class EXPCL_PANDA_EVENT AsyncTask : public TypedReferenceCount, public Namable { +class EXPCL_PANDA_EVENT AsyncTask : public TypedReferenceCount { public: - INLINE AsyncTask(const string &name); + INLINE AsyncTask(); virtual ~AsyncTask(); + ALLOC_DELETED_CHAIN(AsyncTask); PUBLISHED: enum State { diff --git a/panda/src/event/asyncTaskManager.cxx b/panda/src/event/asyncTaskManager.cxx index aaeeae2859..a5fc1bc3d8 100644 --- a/panda/src/event/asyncTaskManager.cxx +++ b/panda/src/event/asyncTaskManager.cxx @@ -194,6 +194,7 @@ remove(AsyncTask *task) { // serviced. Wait for it to finish. while (task->_manager == this && task->_state == AsyncTask::S_servicing) { + PStatTimer timer(_wait_pcollector); _cvar.wait(); } @@ -235,6 +236,37 @@ has_task(AsyncTask *task) const { return true; } +//////////////////////////////////////////////////////////////////// +// Function: AsyncTaskManager::wait_for_tasks +// Access: Published +// Description: Blocks until the task list is empty. +//////////////////////////////////////////////////////////////////// +void AsyncTaskManager:: +wait_for_tasks() { + MutexHolder holder(_lock); + + if (_threads.empty()) { + // Non-threaded case. + while (!_active.empty()) { + if (_state == AsyncTaskManager::S_shutdown) { + return; + } + do_poll(); + } + + } else { + // Threaded case. + while (_num_tasks > 0) { + if (_state == AsyncTaskManager::S_shutdown) { + return; + } + + PStatTimer timer(_wait_pcollector); + _cvar.wait(); + } + } +} + //////////////////////////////////////////////////////////////////// // Function: AsyncTaskManager::poll // Access: Published @@ -250,32 +282,8 @@ poll() { if (!_threads.empty()) { return; } - - Tasks new_active; - int new_num_tasks = 0; - Tasks::iterator ti; - for (ti = _active.begin(); ti != _active.end(); ++ti) { - AsyncTask *task = (*ti); - nassertv(task->_state == AsyncTask::S_active); - task->_state = AsyncTask::S_servicing; - - // Here we keep the manager lock held while we are servicing each - // task. This is the single-threaded implementation, after all, - // so what difference should it make? - if (task->do_task()) { - new_active.push_back(task); - ++new_num_tasks; - task->_state = AsyncTask::S_active; - - } else { - // The task has finished. - task_done(task); - } - } - - _active.swap(new_active); - _num_tasks = new_num_tasks; - _cvar.signal_all(); + + do_poll(); } //////////////////////////////////////////////////////////////////// @@ -417,7 +425,9 @@ do_start_threads() { if (Thread::is_threading_supported()) { _threads.reserve(_num_threads); for (int i = 0; i < _num_threads; ++i) { - PT(AsyncTaskManagerThread) thread = new AsyncTaskManagerThread(this); + ostringstream strm; + strm << get_name() << "_" << i; + PT(AsyncTaskManagerThread) thread = new AsyncTaskManagerThread(strm.str(), this); if (thread->start(TP_low, true)) { _threads.push_back(thread); } @@ -426,14 +436,49 @@ do_start_threads() { } } +//////////////////////////////////////////////////////////////////// +// Function: AsyncTaskManager::do_poll +// Access: Protected +// Description: The private implementation of poll(), this assumes +// the lock is already held. +//////////////////////////////////////////////////////////////////// +void AsyncTaskManager:: +do_poll() { + Tasks new_active; + int new_num_tasks = 0; + Tasks::iterator ti; + for (ti = _active.begin(); ti != _active.end(); ++ti) { + AsyncTask *task = (*ti); + nassertv(task->_state == AsyncTask::S_active); + task->_state = AsyncTask::S_servicing; + + // Here we keep the manager lock held while we are servicing each + // task. This is the single-threaded implementation, after all, + // so what difference should it make? + if (task->do_task()) { + new_active.push_back(task); + ++new_num_tasks; + task->_state = AsyncTask::S_active; + + } else { + // The task has finished. + task_done(task); + } + } + + _active.swap(new_active); + _num_tasks = new_num_tasks; + _cvar.signal_all(); +} + //////////////////////////////////////////////////////////////////// // Function: AsyncTaskManager::AsyncTaskManagerThread::Constructor // Access: Public // Description: //////////////////////////////////////////////////////////////////// AsyncTaskManager::AsyncTaskManagerThread:: -AsyncTaskManagerThread(AsyncTaskManager *manager) : - Thread(manager->get_name(), manager->get_name()), +AsyncTaskManagerThread(const string &name, AsyncTaskManager *manager) : + Thread(name, manager->get_name()), _manager(manager), _servicing(NULL) { diff --git a/panda/src/event/asyncTaskManager.h b/panda/src/event/asyncTaskManager.h index d12a4dab67..bef8f3edc2 100644 --- a/panda/src/event/asyncTaskManager.h +++ b/panda/src/event/asyncTaskManager.h @@ -50,7 +50,7 @@ class EXPCL_PANDA_EVENT AsyncTaskManager : public TypedReferenceCount, public Namable { PUBLISHED: AsyncTaskManager(const string &name, int num_threads); - virtual ~AsyncTaskManager(); + BLOCKING virtual ~AsyncTaskManager(); INLINE int get_num_threads() const; BLOCKING void stop_threads(); @@ -62,6 +62,8 @@ PUBLISHED: bool remove(AsyncTask *task); bool has_task(AsyncTask *task) const; + BLOCKING void wait_for_tasks(); + INLINE int get_num_tasks() const; void poll(); @@ -76,11 +78,12 @@ protected: void service_one_task(AsyncTaskManagerThread *thread); void task_done(AsyncTask *task); void do_start_threads(); + void do_poll(); protected: class AsyncTaskManagerThread : public Thread { public: - AsyncTaskManagerThread(AsyncTaskManager *manager); + AsyncTaskManagerThread(const string &name, AsyncTaskManager *manager); virtual void thread_main(); AsyncTaskManager *_manager; diff --git a/panda/src/grutil/pipeOcclusionCullTraverser.cxx b/panda/src/grutil/pipeOcclusionCullTraverser.cxx index 7d0892dbd9..0907b41d1a 100644 --- a/panda/src/grutil/pipeOcclusionCullTraverser.cxx +++ b/panda/src/grutil/pipeOcclusionCullTraverser.cxx @@ -251,6 +251,7 @@ end_traverse() { #endif // NDEBUG } _pending_objects.clear(); + CullTraverser::end_traverse(); gsg->end_scene(); _buffer->end_frame(GraphicsOutput::FM_render, current_thread); diff --git a/panda/src/pgraph/cullHandler.cxx b/panda/src/pgraph/cullHandler.cxx index 75b6cf9bf6..c96f8ab59a 100644 --- a/panda/src/pgraph/cullHandler.cxx +++ b/panda/src/pgraph/cullHandler.cxx @@ -23,6 +23,15 @@ #include "renderState.h" #include "pnotify.h" +//////////////////////////////////////////////////////////////////// +// Function: CullHandler::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +CullHandler:: +CullHandler() { +} + //////////////////////////////////////////////////////////////////// // Function: CullHandler::Destructor // Access: Public, Virtual @@ -50,6 +59,17 @@ record_object(CullableObject *object, const CullTraverser *traverser) { delete object; } +//////////////////////////////////////////////////////////////////// +// Function: CullHandler::end_traverse +// Access: Public, Virtual +// Description: This callback function is intended to be overridden +// by a derived class. This is called at the end of the +// traversal. +//////////////////////////////////////////////////////////////////// +void CullHandler:: +end_traverse() { +} + //////////////////////////////////////////////////////////////////// // Function: CullHandler::draw_with_decals // Access: Public, Static diff --git a/panda/src/pgraph/cullHandler.h b/panda/src/pgraph/cullHandler.h index 71549c8e61..b8a5b8b88f 100644 --- a/panda/src/pgraph/cullHandler.h +++ b/panda/src/pgraph/cullHandler.h @@ -34,10 +34,12 @@ class CullTraverser; //////////////////////////////////////////////////////////////////// class EXPCL_PANDA_PGRAPH CullHandler { public: + CullHandler(); virtual ~CullHandler(); virtual void record_object(CullableObject *object, const CullTraverser *traverser); + virtual void end_traverse(); INLINE static void draw(CullableObject *object, GraphicsStateGuardianBase *gsg, diff --git a/panda/src/pgraph/cullResult.I b/panda/src/pgraph/cullResult.I index df1bc4bca4..9da29b47b2 100644 --- a/panda/src/pgraph/cullResult.I +++ b/panda/src/pgraph/cullResult.I @@ -17,19 +17,6 @@ //////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////// -// Function: CullResult::Constructor -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -INLINE CullResult:: -CullResult(GraphicsStateGuardianBase *gsg, - const PStatCollector &draw_region_pcollector) : - _gsg(gsg), - _draw_region_pcollector(draw_region_pcollector) -{ -} - //////////////////////////////////////////////////////////////////// // Function: CullResult::Destructor // Access: Public diff --git a/panda/src/pgraph/cullResult.cxx b/panda/src/pgraph/cullResult.cxx index 8dcb1de296..8a9b8418d6 100644 --- a/panda/src/pgraph/cullResult.cxx +++ b/panda/src/pgraph/cullResult.cxx @@ -56,6 +56,19 @@ static const float dual_opaque_level = 252.0f / 256.0f; static const double bin_color_flash_rate = 1.0; // 1 state change per second +//////////////////////////////////////////////////////////////////// +// Function: CullResult::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +CullResult:: +CullResult(GraphicsStateGuardianBase *gsg, + const PStatCollector &draw_region_pcollector) : + _gsg(gsg), + _draw_region_pcollector(draw_region_pcollector) +{ +} + //////////////////////////////////////////////////////////////////// // Function: CullResult::make_next // Access: Public diff --git a/panda/src/pgraph/cullResult.h b/panda/src/pgraph/cullResult.h index 738114872c..3882e5fd2d 100644 --- a/panda/src/pgraph/cullResult.h +++ b/panda/src/pgraph/cullResult.h @@ -24,7 +24,6 @@ #include "renderState.h" #include "cullableObject.h" #include "geomMunger.h" - #include "referenceCount.h" #include "pointerTo.h" #include "pvector.h" @@ -51,8 +50,8 @@ class SceneSetup; //////////////////////////////////////////////////////////////////// class EXPCL_PANDA_PGRAPH CullResult : public ReferenceCount { public: - INLINE CullResult(GraphicsStateGuardianBase *gsg, - const PStatCollector &draw_region_pcollector); + CullResult(GraphicsStateGuardianBase *gsg, + const PStatCollector &draw_region_pcollector); INLINE ~CullResult(); PT(CullResult) make_next() const; @@ -81,7 +80,7 @@ private: GraphicsStateGuardianBase *_gsg; PStatCollector _draw_region_pcollector; - + typedef pvector< PT(CullBin) > Bins; Bins _bins; }; diff --git a/panda/src/pgraph/cullTraverser.cxx b/panda/src/pgraph/cullTraverser.cxx index 613de61328..bbc985047f 100644 --- a/panda/src/pgraph/cullTraverser.cxx +++ b/panda/src/pgraph/cullTraverser.cxx @@ -359,6 +359,7 @@ traverse_below(CullTraverserData &data) { //////////////////////////////////////////////////////////////////// void CullTraverser:: end_traverse() { + _cull_handler->end_traverse(); } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/pgraph/modelFlattenRequest.I b/panda/src/pgraph/modelFlattenRequest.I index cb2129eb7e..7a395f17db 100644 --- a/panda/src/pgraph/modelFlattenRequest.I +++ b/panda/src/pgraph/modelFlattenRequest.I @@ -25,7 +25,6 @@ //////////////////////////////////////////////////////////////////// INLINE ModelFlattenRequest:: ModelFlattenRequest(PandaNode *orig) : - AsyncTask(orig->get_name()), _orig(orig), _is_ready(false) { diff --git a/panda/src/pgraph/modelFlattenRequest.h b/panda/src/pgraph/modelFlattenRequest.h index 82cc7b1fd5..0865fffb21 100644 --- a/panda/src/pgraph/modelFlattenRequest.h +++ b/panda/src/pgraph/modelFlattenRequest.h @@ -35,6 +35,9 @@ // retrieved from this object. //////////////////////////////////////////////////////////////////// class EXPCL_PANDA_PGRAPH ModelFlattenRequest : public AsyncTask { +public: + ALLOC_DELETED_CHAIN(ModelFlattenRequest); + PUBLISHED: INLINE ModelFlattenRequest(PandaNode *orig); diff --git a/panda/src/pgraph/modelLoadRequest.I b/panda/src/pgraph/modelLoadRequest.I index da628cf553..982c763eed 100644 --- a/panda/src/pgraph/modelLoadRequest.I +++ b/panda/src/pgraph/modelLoadRequest.I @@ -25,7 +25,6 @@ //////////////////////////////////////////////////////////////////// INLINE ModelLoadRequest:: ModelLoadRequest(const Filename &filename, const LoaderOptions &options) : - AsyncTask(filename), _filename(filename), _options(options), _is_ready(false) diff --git a/panda/src/pgraph/modelLoadRequest.h b/panda/src/pgraph/modelLoadRequest.h index 77e5f1552a..4442c02583 100644 --- a/panda/src/pgraph/modelLoadRequest.h +++ b/panda/src/pgraph/modelLoadRequest.h @@ -35,6 +35,9 @@ // an asynchronous load. //////////////////////////////////////////////////////////////////// class EXPCL_PANDA_PGRAPH ModelLoadRequest : public AsyncTask { +public: + ALLOC_DELETED_CHAIN(ModelLoadRequest); + PUBLISHED: INLINE ModelLoadRequest(const Filename &filename, const LoaderOptions &options);