mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-03 10:22:45 -04:00
minor threading fixes
This commit is contained in:
parent
0c2b6e3164
commit
4c2659988f
@ -26,7 +26,6 @@
|
|||||||
INLINE AudioLoadRequest::
|
INLINE AudioLoadRequest::
|
||||||
AudioLoadRequest(AudioManager *audio_manager, const string &filename,
|
AudioLoadRequest(AudioManager *audio_manager, const string &filename,
|
||||||
bool positional) :
|
bool positional) :
|
||||||
AsyncTask(filename),
|
|
||||||
_audio_manager(audio_manager),
|
_audio_manager(audio_manager),
|
||||||
_filename(filename),
|
_filename(filename),
|
||||||
_positional(positional),
|
_positional(positional),
|
||||||
|
@ -36,6 +36,9 @@
|
|||||||
// an asynchronous load.
|
// an asynchronous load.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
class EXPCL_PANDA_AUDIO AudioLoadRequest : public AsyncTask {
|
class EXPCL_PANDA_AUDIO AudioLoadRequest : public AsyncTask {
|
||||||
|
public:
|
||||||
|
ALLOC_DELETED_CHAIN(AudioLoadRequest);
|
||||||
|
|
||||||
PUBLISHED:
|
PUBLISHED:
|
||||||
INLINE AudioLoadRequest(AudioManager *audio_manager, const string &filename,
|
INLINE AudioLoadRequest(AudioManager *audio_manager, const string &filename,
|
||||||
bool positional);
|
bool positional);
|
||||||
|
@ -23,8 +23,7 @@
|
|||||||
// Description:
|
// Description:
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
INLINE AsyncTask::
|
INLINE AsyncTask::
|
||||||
AsyncTask(const string &name) :
|
AsyncTask() :
|
||||||
Namable(name),
|
|
||||||
_state(S_inactive),
|
_state(S_inactive),
|
||||||
_manager(NULL)
|
_manager(NULL)
|
||||||
{
|
{
|
||||||
|
@ -37,5 +37,5 @@ AsyncTask::
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void AsyncTask::
|
void AsyncTask::
|
||||||
output(ostream &out) const {
|
output(ostream &out) const {
|
||||||
out << get_type() << " " << get_name();
|
out << get_type();
|
||||||
}
|
}
|
||||||
|
@ -43,10 +43,11 @@ class AsyncTaskManager;
|
|||||||
// class, and override do_task(), to define the
|
// class, and override do_task(), to define the
|
||||||
// functionality you wish to have the task perform.
|
// 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:
|
public:
|
||||||
INLINE AsyncTask(const string &name);
|
INLINE AsyncTask();
|
||||||
virtual ~AsyncTask();
|
virtual ~AsyncTask();
|
||||||
|
ALLOC_DELETED_CHAIN(AsyncTask);
|
||||||
|
|
||||||
PUBLISHED:
|
PUBLISHED:
|
||||||
enum State {
|
enum State {
|
||||||
|
@ -194,6 +194,7 @@ remove(AsyncTask *task) {
|
|||||||
// serviced. Wait for it to finish.
|
// serviced. Wait for it to finish.
|
||||||
while (task->_manager == this &&
|
while (task->_manager == this &&
|
||||||
task->_state == AsyncTask::S_servicing) {
|
task->_state == AsyncTask::S_servicing) {
|
||||||
|
PStatTimer timer(_wait_pcollector);
|
||||||
_cvar.wait();
|
_cvar.wait();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -235,6 +236,37 @@ has_task(AsyncTask *task) const {
|
|||||||
return true;
|
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
|
// Function: AsyncTaskManager::poll
|
||||||
// Access: Published
|
// Access: Published
|
||||||
@ -250,32 +282,8 @@ poll() {
|
|||||||
if (!_threads.empty()) {
|
if (!_threads.empty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Tasks new_active;
|
do_poll();
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
@ -417,7 +425,9 @@ do_start_threads() {
|
|||||||
if (Thread::is_threading_supported()) {
|
if (Thread::is_threading_supported()) {
|
||||||
_threads.reserve(_num_threads);
|
_threads.reserve(_num_threads);
|
||||||
for (int i = 0; i < _num_threads; ++i) {
|
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)) {
|
if (thread->start(TP_low, true)) {
|
||||||
_threads.push_back(thread);
|
_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
|
// Function: AsyncTaskManager::AsyncTaskManagerThread::Constructor
|
||||||
// Access: Public
|
// Access: Public
|
||||||
// Description:
|
// Description:
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
AsyncTaskManager::AsyncTaskManagerThread::
|
AsyncTaskManager::AsyncTaskManagerThread::
|
||||||
AsyncTaskManagerThread(AsyncTaskManager *manager) :
|
AsyncTaskManagerThread(const string &name, AsyncTaskManager *manager) :
|
||||||
Thread(manager->get_name(), manager->get_name()),
|
Thread(name, manager->get_name()),
|
||||||
_manager(manager),
|
_manager(manager),
|
||||||
_servicing(NULL)
|
_servicing(NULL)
|
||||||
{
|
{
|
||||||
|
@ -50,7 +50,7 @@
|
|||||||
class EXPCL_PANDA_EVENT AsyncTaskManager : public TypedReferenceCount, public Namable {
|
class EXPCL_PANDA_EVENT AsyncTaskManager : public TypedReferenceCount, public Namable {
|
||||||
PUBLISHED:
|
PUBLISHED:
|
||||||
AsyncTaskManager(const string &name, int num_threads);
|
AsyncTaskManager(const string &name, int num_threads);
|
||||||
virtual ~AsyncTaskManager();
|
BLOCKING virtual ~AsyncTaskManager();
|
||||||
|
|
||||||
INLINE int get_num_threads() const;
|
INLINE int get_num_threads() const;
|
||||||
BLOCKING void stop_threads();
|
BLOCKING void stop_threads();
|
||||||
@ -62,6 +62,8 @@ PUBLISHED:
|
|||||||
bool remove(AsyncTask *task);
|
bool remove(AsyncTask *task);
|
||||||
bool has_task(AsyncTask *task) const;
|
bool has_task(AsyncTask *task) const;
|
||||||
|
|
||||||
|
BLOCKING void wait_for_tasks();
|
||||||
|
|
||||||
INLINE int get_num_tasks() const;
|
INLINE int get_num_tasks() const;
|
||||||
|
|
||||||
void poll();
|
void poll();
|
||||||
@ -76,11 +78,12 @@ protected:
|
|||||||
void service_one_task(AsyncTaskManagerThread *thread);
|
void service_one_task(AsyncTaskManagerThread *thread);
|
||||||
void task_done(AsyncTask *task);
|
void task_done(AsyncTask *task);
|
||||||
void do_start_threads();
|
void do_start_threads();
|
||||||
|
void do_poll();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
class AsyncTaskManagerThread : public Thread {
|
class AsyncTaskManagerThread : public Thread {
|
||||||
public:
|
public:
|
||||||
AsyncTaskManagerThread(AsyncTaskManager *manager);
|
AsyncTaskManagerThread(const string &name, AsyncTaskManager *manager);
|
||||||
virtual void thread_main();
|
virtual void thread_main();
|
||||||
|
|
||||||
AsyncTaskManager *_manager;
|
AsyncTaskManager *_manager;
|
||||||
|
@ -251,6 +251,7 @@ end_traverse() {
|
|||||||
#endif // NDEBUG
|
#endif // NDEBUG
|
||||||
}
|
}
|
||||||
_pending_objects.clear();
|
_pending_objects.clear();
|
||||||
|
CullTraverser::end_traverse();
|
||||||
|
|
||||||
gsg->end_scene();
|
gsg->end_scene();
|
||||||
_buffer->end_frame(GraphicsOutput::FM_render, current_thread);
|
_buffer->end_frame(GraphicsOutput::FM_render, current_thread);
|
||||||
|
@ -23,6 +23,15 @@
|
|||||||
#include "renderState.h"
|
#include "renderState.h"
|
||||||
#include "pnotify.h"
|
#include "pnotify.h"
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: CullHandler::Constructor
|
||||||
|
// Access: Public
|
||||||
|
// Description:
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
CullHandler::
|
||||||
|
CullHandler() {
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: CullHandler::Destructor
|
// Function: CullHandler::Destructor
|
||||||
// Access: Public, Virtual
|
// Access: Public, Virtual
|
||||||
@ -50,6 +59,17 @@ record_object(CullableObject *object, const CullTraverser *traverser) {
|
|||||||
delete object;
|
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
|
// Function: CullHandler::draw_with_decals
|
||||||
// Access: Public, Static
|
// Access: Public, Static
|
||||||
|
@ -34,10 +34,12 @@ class CullTraverser;
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
class EXPCL_PANDA_PGRAPH CullHandler {
|
class EXPCL_PANDA_PGRAPH CullHandler {
|
||||||
public:
|
public:
|
||||||
|
CullHandler();
|
||||||
virtual ~CullHandler();
|
virtual ~CullHandler();
|
||||||
|
|
||||||
virtual void record_object(CullableObject *object,
|
virtual void record_object(CullableObject *object,
|
||||||
const CullTraverser *traverser);
|
const CullTraverser *traverser);
|
||||||
|
virtual void end_traverse();
|
||||||
|
|
||||||
INLINE static void draw(CullableObject *object,
|
INLINE static void draw(CullableObject *object,
|
||||||
GraphicsStateGuardianBase *gsg,
|
GraphicsStateGuardianBase *gsg,
|
||||||
|
@ -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
|
// Function: CullResult::Destructor
|
||||||
// Access: Public
|
// Access: Public
|
||||||
|
@ -56,6 +56,19 @@
|
|||||||
static const float dual_opaque_level = 252.0f / 256.0f;
|
static const float dual_opaque_level = 252.0f / 256.0f;
|
||||||
static const double bin_color_flash_rate = 1.0; // 1 state change per second
|
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
|
// Function: CullResult::make_next
|
||||||
// Access: Public
|
// Access: Public
|
||||||
|
@ -24,7 +24,6 @@
|
|||||||
#include "renderState.h"
|
#include "renderState.h"
|
||||||
#include "cullableObject.h"
|
#include "cullableObject.h"
|
||||||
#include "geomMunger.h"
|
#include "geomMunger.h"
|
||||||
|
|
||||||
#include "referenceCount.h"
|
#include "referenceCount.h"
|
||||||
#include "pointerTo.h"
|
#include "pointerTo.h"
|
||||||
#include "pvector.h"
|
#include "pvector.h"
|
||||||
@ -51,8 +50,8 @@ class SceneSetup;
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
class EXPCL_PANDA_PGRAPH CullResult : public ReferenceCount {
|
class EXPCL_PANDA_PGRAPH CullResult : public ReferenceCount {
|
||||||
public:
|
public:
|
||||||
INLINE CullResult(GraphicsStateGuardianBase *gsg,
|
CullResult(GraphicsStateGuardianBase *gsg,
|
||||||
const PStatCollector &draw_region_pcollector);
|
const PStatCollector &draw_region_pcollector);
|
||||||
INLINE ~CullResult();
|
INLINE ~CullResult();
|
||||||
|
|
||||||
PT(CullResult) make_next() const;
|
PT(CullResult) make_next() const;
|
||||||
@ -81,7 +80,7 @@ private:
|
|||||||
|
|
||||||
GraphicsStateGuardianBase *_gsg;
|
GraphicsStateGuardianBase *_gsg;
|
||||||
PStatCollector _draw_region_pcollector;
|
PStatCollector _draw_region_pcollector;
|
||||||
|
|
||||||
typedef pvector< PT(CullBin) > Bins;
|
typedef pvector< PT(CullBin) > Bins;
|
||||||
Bins _bins;
|
Bins _bins;
|
||||||
};
|
};
|
||||||
|
@ -359,6 +359,7 @@ traverse_below(CullTraverserData &data) {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void CullTraverser::
|
void CullTraverser::
|
||||||
end_traverse() {
|
end_traverse() {
|
||||||
|
_cull_handler->end_traverse();
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
|
@ -25,7 +25,6 @@
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
INLINE ModelFlattenRequest::
|
INLINE ModelFlattenRequest::
|
||||||
ModelFlattenRequest(PandaNode *orig) :
|
ModelFlattenRequest(PandaNode *orig) :
|
||||||
AsyncTask(orig->get_name()),
|
|
||||||
_orig(orig),
|
_orig(orig),
|
||||||
_is_ready(false)
|
_is_ready(false)
|
||||||
{
|
{
|
||||||
|
@ -35,6 +35,9 @@
|
|||||||
// retrieved from this object.
|
// retrieved from this object.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
class EXPCL_PANDA_PGRAPH ModelFlattenRequest : public AsyncTask {
|
class EXPCL_PANDA_PGRAPH ModelFlattenRequest : public AsyncTask {
|
||||||
|
public:
|
||||||
|
ALLOC_DELETED_CHAIN(ModelFlattenRequest);
|
||||||
|
|
||||||
PUBLISHED:
|
PUBLISHED:
|
||||||
INLINE ModelFlattenRequest(PandaNode *orig);
|
INLINE ModelFlattenRequest(PandaNode *orig);
|
||||||
|
|
||||||
|
@ -25,7 +25,6 @@
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
INLINE ModelLoadRequest::
|
INLINE ModelLoadRequest::
|
||||||
ModelLoadRequest(const Filename &filename, const LoaderOptions &options) :
|
ModelLoadRequest(const Filename &filename, const LoaderOptions &options) :
|
||||||
AsyncTask(filename),
|
|
||||||
_filename(filename),
|
_filename(filename),
|
||||||
_options(options),
|
_options(options),
|
||||||
_is_ready(false)
|
_is_ready(false)
|
||||||
|
@ -35,6 +35,9 @@
|
|||||||
// an asynchronous load.
|
// an asynchronous load.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
class EXPCL_PANDA_PGRAPH ModelLoadRequest : public AsyncTask {
|
class EXPCL_PANDA_PGRAPH ModelLoadRequest : public AsyncTask {
|
||||||
|
public:
|
||||||
|
ALLOC_DELETED_CHAIN(ModelLoadRequest);
|
||||||
|
|
||||||
PUBLISHED:
|
PUBLISHED:
|
||||||
INLINE ModelLoadRequest(const Filename &filename,
|
INLINE ModelLoadRequest(const Filename &filename,
|
||||||
const LoaderOptions &options);
|
const LoaderOptions &options);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user