mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-02 09:52:27 -04:00
minor threading fixes
This commit is contained in:
parent
0c2b6e3164
commit
4c2659988f
@ -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),
|
||||
|
@ -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);
|
||||
|
@ -23,8 +23,7 @@
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE AsyncTask::
|
||||
AsyncTask(const string &name) :
|
||||
Namable(name),
|
||||
AsyncTask() :
|
||||
_state(S_inactive),
|
||||
_manager(NULL)
|
||||
{
|
||||
|
@ -37,5 +37,5 @@ AsyncTask::
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void AsyncTask::
|
||||
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
|
||||
// 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 {
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -359,6 +359,7 @@ traverse_below(CullTraverserData &data) {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void CullTraverser::
|
||||
end_traverse() {
|
||||
_cull_handler->end_traverse();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
@ -25,7 +25,6 @@
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE ModelFlattenRequest::
|
||||
ModelFlattenRequest(PandaNode *orig) :
|
||||
AsyncTask(orig->get_name()),
|
||||
_orig(orig),
|
||||
_is_ready(false)
|
||||
{
|
||||
|
@ -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);
|
||||
|
||||
|
@ -25,7 +25,6 @@
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE ModelLoadRequest::
|
||||
ModelLoadRequest(const Filename &filename, const LoaderOptions &options) :
|
||||
AsyncTask(filename),
|
||||
_filename(filename),
|
||||
_options(options),
|
||||
_is_ready(false)
|
||||
|
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user