integrate PStatThread and Thread; better thread handling in GraphicsEngine::render_frame()
This commit is contained in:
parent
0faf866c57
commit
b7ceab1bff
|
|
@ -43,6 +43,7 @@
|
|||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
PStatCollector GraphicsEngine::_wait_pcollector("Wait");
|
||||
PStatCollector GraphicsEngine::_app_pcollector("App");
|
||||
PStatCollector GraphicsEngine::_yield_pcollector("App:Yield");
|
||||
PStatCollector GraphicsEngine::_cull_pcollector("Cull");
|
||||
|
|
@ -490,12 +491,24 @@ render_frame() {
|
|||
}
|
||||
}
|
||||
new_windows.swap(_windows);
|
||||
|
||||
// Now it's time to do any drawing from the main frame--after all of
|
||||
// the App code has executed, but before we begin the next frame.
|
||||
_app.do_frame(this);
|
||||
|
||||
// Grab each thread's mutex again after all windows have flipped.
|
||||
// Grab each thread's mutex again after all windows have flipped,
|
||||
// and wait for the thread to finish.
|
||||
Threads::const_iterator ti;
|
||||
for (ti = _threads.begin(); ti != _threads.end(); ++ti) {
|
||||
RenderThread *thread = (*ti).second;
|
||||
thread->_cv_mutex.lock();
|
||||
|
||||
if (thread->_thread_state != TS_wait) {
|
||||
PStatTimer timer(_wait_pcollector);
|
||||
while (thread->_thread_state != TS_wait) {
|
||||
thread->_cv_done.wait();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Now cycle the pipeline and officially begin the next frame.
|
||||
|
|
@ -524,12 +537,11 @@ render_frame() {
|
|||
}
|
||||
|
||||
// Now signal all of our threads to begin their next frame.
|
||||
_app.do_frame(this);
|
||||
for (ti = _threads.begin(); ti != _threads.end(); ++ti) {
|
||||
RenderThread *thread = (*ti).second;
|
||||
if (thread->_thread_state == TS_wait) {
|
||||
thread->_thread_state = TS_do_frame;
|
||||
thread->_cv.signal();
|
||||
thread->_cv_start.signal();
|
||||
}
|
||||
thread->_cv_mutex.release();
|
||||
}
|
||||
|
|
@ -579,10 +591,16 @@ open_windows() {
|
|||
for (ti = _threads.begin(); ti != _threads.end(); ++ti) {
|
||||
RenderThread *thread = (*ti).second;
|
||||
thread->_cv_mutex.lock();
|
||||
if (thread->_thread_state == TS_wait) {
|
||||
thread->_thread_state = TS_do_windows;
|
||||
thread->_cv.signal();
|
||||
|
||||
if (thread->_thread_state != TS_wait) {
|
||||
PStatTimer timer(_wait_pcollector);
|
||||
while (thread->_thread_state != TS_wait) {
|
||||
thread->_cv_done.wait();
|
||||
}
|
||||
}
|
||||
|
||||
thread->_thread_state = TS_do_windows;
|
||||
thread->_cv_start.signal();
|
||||
thread->_cv_mutex.release();
|
||||
}
|
||||
|
||||
|
|
@ -591,10 +609,16 @@ open_windows() {
|
|||
for (ti = _threads.begin(); ti != _threads.end(); ++ti) {
|
||||
RenderThread *thread = (*ti).second;
|
||||
thread->_cv_mutex.lock();
|
||||
if (thread->_thread_state == TS_wait) {
|
||||
thread->_thread_state = TS_do_windows;
|
||||
thread->_cv.signal();
|
||||
|
||||
if (thread->_thread_state != TS_wait) {
|
||||
PStatTimer timer(_wait_pcollector);
|
||||
while (thread->_thread_state != TS_wait) {
|
||||
thread->_cv_done.wait();
|
||||
}
|
||||
}
|
||||
|
||||
thread->_thread_state = TS_do_windows;
|
||||
thread->_cv_start.signal();
|
||||
thread->_cv_mutex.release();
|
||||
}
|
||||
}
|
||||
|
|
@ -980,21 +1004,28 @@ do_flip_frame() {
|
|||
nassertv(_flip_state == FS_draw || _flip_state == FS_sync);
|
||||
|
||||
// First, wait for all the threads to finish their current frame, if
|
||||
// necessary. Grabbing the mutex should achieve that.
|
||||
// necessary. Grabbing the mutex (and waiting for TS_wait) should
|
||||
// achieve that.
|
||||
Threads::const_iterator ti;
|
||||
for (ti = _threads.begin(); ti != _threads.end(); ++ti) {
|
||||
RenderThread *thread = (*ti).second;
|
||||
thread->_cv_mutex.lock();
|
||||
|
||||
if (thread->_thread_state != TS_wait) {
|
||||
PStatTimer timer(_wait_pcollector);
|
||||
while (thread->_thread_state != TS_wait) {
|
||||
thread->_cv_done.wait();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Now signal all of our threads to flip the windows.
|
||||
_app.do_flip(this);
|
||||
for (ti = _threads.begin(); ti != _threads.end(); ++ti) {
|
||||
RenderThread *thread = (*ti).second;
|
||||
if (thread->_thread_state == TS_wait) {
|
||||
thread->_thread_state = TS_do_flip;
|
||||
thread->_cv.signal();
|
||||
}
|
||||
nassertv(thread->_thread_state == TS_wait);
|
||||
thread->_thread_state = TS_do_flip;
|
||||
thread->_cv_start.signal();
|
||||
thread->_cv_mutex.release();
|
||||
}
|
||||
|
||||
|
|
@ -1305,10 +1336,15 @@ terminate_threads() {
|
|||
// Now tell them to release their windows' graphics contexts.
|
||||
for (ti = _threads.begin(); ti != _threads.end(); ++ti) {
|
||||
RenderThread *thread = (*ti).second;
|
||||
if (thread->_thread_state == TS_wait) {
|
||||
thread->_thread_state = TS_do_release;
|
||||
thread->_cv.signal();
|
||||
|
||||
if (thread->_thread_state != TS_wait) {
|
||||
PStatTimer timer(_wait_pcollector);
|
||||
while (thread->_thread_state != TS_wait) {
|
||||
thread->_cv_done.wait();
|
||||
}
|
||||
}
|
||||
thread->_thread_state = TS_do_release;
|
||||
thread->_cv_start.signal();
|
||||
thread->_cv_mutex.release();
|
||||
}
|
||||
|
||||
|
|
@ -1322,7 +1358,7 @@ terminate_threads() {
|
|||
for (ti = _threads.begin(); ti != _threads.end(); ++ti) {
|
||||
RenderThread *thread = (*ti).second;
|
||||
thread->_thread_state = TS_terminate;
|
||||
thread->_cv.signal();
|
||||
thread->_cv_start.signal();
|
||||
thread->_cv_mutex.release();
|
||||
}
|
||||
|
||||
|
|
@ -1738,9 +1774,10 @@ do_callbacks(GraphicsEngine::CallbackTime callback_time) {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
GraphicsEngine::RenderThread::
|
||||
RenderThread(const string &name, GraphicsEngine *engine) :
|
||||
Thread(name),
|
||||
Thread(name, "Main"),
|
||||
_engine(engine),
|
||||
_cv(_cv_mutex)
|
||||
_cv_start(_cv_mutex),
|
||||
_cv_done(_cv_mutex)
|
||||
{
|
||||
_thread_state = TS_wait;
|
||||
}
|
||||
|
|
@ -1756,6 +1793,8 @@ void GraphicsEngine::RenderThread::
|
|||
thread_main() {
|
||||
MutexHolder holder(_cv_mutex);
|
||||
while (true) {
|
||||
nassertv(_cv_mutex.debug_is_locked());
|
||||
|
||||
switch (_thread_state) {
|
||||
case TS_wait:
|
||||
break;
|
||||
|
|
@ -1763,31 +1802,41 @@ thread_main() {
|
|||
case TS_do_frame:
|
||||
do_pending(_engine);
|
||||
do_frame(_engine);
|
||||
_thread_state = TS_wait;
|
||||
break;
|
||||
|
||||
case TS_do_flip:
|
||||
do_flip(_engine);
|
||||
_thread_state = TS_wait;
|
||||
break;
|
||||
|
||||
case TS_do_release:
|
||||
do_pending(_engine);
|
||||
do_release(_engine);
|
||||
_thread_state = TS_wait;
|
||||
break;
|
||||
|
||||
case TS_do_windows:
|
||||
do_windows(_engine);
|
||||
do_pending(_engine);
|
||||
_thread_state = TS_wait;
|
||||
break;
|
||||
|
||||
case TS_terminate:
|
||||
do_pending(_engine);
|
||||
do_close(_engine);
|
||||
_thread_state = TS_done;
|
||||
_cv_done.signal();
|
||||
return;
|
||||
|
||||
case TS_done:
|
||||
// Shouldn't be possible to get here.
|
||||
nassertv(false);
|
||||
return;
|
||||
}
|
||||
_cv.wait();
|
||||
|
||||
_thread_state = TS_wait;
|
||||
_cv_done.signal();
|
||||
|
||||
{
|
||||
PStatTimer timer(_wait_pcollector);
|
||||
_cv_start.wait();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -107,7 +107,8 @@ public:
|
|||
TS_do_flip,
|
||||
TS_do_release,
|
||||
TS_do_windows,
|
||||
TS_terminate
|
||||
TS_terminate,
|
||||
TS_done
|
||||
};
|
||||
|
||||
enum CallbackTime {
|
||||
|
|
@ -216,7 +217,8 @@ private:
|
|||
|
||||
GraphicsEngine *_engine;
|
||||
Mutex _cv_mutex;
|
||||
ConditionVar _cv;
|
||||
ConditionVar _cv_start;
|
||||
ConditionVar _cv_done;
|
||||
ThreadState _thread_state;
|
||||
};
|
||||
|
||||
|
|
@ -243,6 +245,7 @@ private:
|
|||
FlipState _flip_state;
|
||||
Mutex _lock;
|
||||
|
||||
static PStatCollector _wait_pcollector;
|
||||
static PStatCollector _app_pcollector;
|
||||
static PStatCollector _yield_pcollector;
|
||||
static PStatCollector _cull_pcollector;
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@
|
|||
dcast.T dcast.h \
|
||||
encryptStreamBuf.h encryptStreamBuf.I encryptStream.h encryptStream.I \
|
||||
error_utils.h \
|
||||
externalThread.h \
|
||||
hashGeneratorBase.I hashGeneratorBase.h \
|
||||
hashVal.I hashVal.h \
|
||||
indirectLess.I indirectLess.h \
|
||||
|
|
@ -88,6 +89,7 @@
|
|||
datagramSink.cxx dcast.cxx \
|
||||
encryptStreamBuf.cxx encryptStream.cxx \
|
||||
error_utils.cxx \
|
||||
externalThread.cxx \
|
||||
hashGeneratorBase.cxx hashVal.cxx \
|
||||
mainThread.cxx \
|
||||
memoryInfo.cxx memoryUsage.cxx memoryUsagePointerCounts.cxx \
|
||||
|
|
@ -145,6 +147,7 @@
|
|||
datagramSink.I datagramSink.h dcast.T dcast.h \
|
||||
encryptStreamBuf.h encryptStreamBuf.I encryptStream.h encryptStream.I \
|
||||
error_utils.h \
|
||||
externalThread.h \
|
||||
hashGeneratorBase.I \
|
||||
hashGeneratorBase.h hashVal.I hashVal.h \
|
||||
indirectLess.I indirectLess.h \
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
#include "error_utils.cxx"
|
||||
#include "encryptStreamBuf.cxx"
|
||||
#include "encryptStream.cxx"
|
||||
#include "externalThread.cxx"
|
||||
#include "hashGeneratorBase.cxx"
|
||||
#include "hashVal.cxx"
|
||||
#include "mainThread.cxx"
|
||||
|
|
|
|||
|
|
@ -0,0 +1,40 @@
|
|||
// Filename: externalThread.cxx
|
||||
// Created by: drose (30Jan06)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d-general@lists.sourceforge.net .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "externalThread.h"
|
||||
|
||||
TypeHandle ExternalThread::_type_handle;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ExternalThread::Constructor
|
||||
// Access: Private
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
ExternalThread::
|
||||
ExternalThread() : Thread("External", "External") {
|
||||
_started = true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ExternalThread::thread_main
|
||||
// Access: Private, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void ExternalThread::
|
||||
thread_main() {
|
||||
}
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
// Filename: externalThread.h
|
||||
// Created by: drose (30Jan06)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d-general@lists.sourceforge.net .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef EXTERNALTHREAD_H
|
||||
#define EXTERNALTHREAD_H
|
||||
|
||||
#include "pandabase.h"
|
||||
#include "thread.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : ExternalThread
|
||||
// Description : The special "external thread" class. There is one
|
||||
// instance of these in the world, and it is returned by
|
||||
// Thread::get_external_thread().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDAEXPRESS ExternalThread : public Thread {
|
||||
private:
|
||||
ExternalThread();
|
||||
virtual void thread_main();
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
return _type_handle;
|
||||
}
|
||||
static void init_type() {
|
||||
Thread::init_type();
|
||||
register_type(_type_handle, "ExternalThread",
|
||||
Thread::get_class_type());
|
||||
}
|
||||
virtual TypeHandle get_type() const {
|
||||
return get_class_type();
|
||||
}
|
||||
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
|
||||
|
||||
private:
|
||||
static TypeHandle _type_handle;
|
||||
|
||||
friend class Thread;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -26,7 +26,8 @@ TypeHandle MainThread::_type_handle;
|
|||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
MainThread::
|
||||
MainThread() : Thread("main") {
|
||||
MainThread() : Thread("Main", "Main") {
|
||||
_started = true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -27,10 +27,22 @@
|
|||
// terminate and destruct itself.
|
||||
//
|
||||
// Call start() to begin thread execution.
|
||||
//
|
||||
// The name should be unique for each thread (though
|
||||
// this is not enforced, and not strictly required).
|
||||
// The sync_name can be shared between multiple
|
||||
// different threads; threads that run synchronously
|
||||
// with each other should be given the same sync_name,
|
||||
// for the benefit of PStats.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE Thread::
|
||||
Thread(const string &name) : _name(name), _impl(this) {
|
||||
Thread(const string &name, const string &sync_name) :
|
||||
_name(name),
|
||||
_sync_name(sync_name),
|
||||
_impl(this)
|
||||
{
|
||||
_started = false;
|
||||
_pstats_index = -1;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -56,13 +68,55 @@ operator = (const Thread ©) {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Thread::get_name
|
||||
// Access: Public
|
||||
// Description: Returns the name of the thread.
|
||||
// Description: Returns the name of the thread. Each thread should
|
||||
// probably have a unique name, but this is not enforced
|
||||
// (and not strictly required).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE const string &Thread::
|
||||
get_name() const {
|
||||
return _name;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Thread::get_sync_name
|
||||
// Access: Public
|
||||
// Description: Returns the sync name of the thread. This name
|
||||
// collects threads into "sync groups", which are
|
||||
// expected to run synchronously. This is mainly used
|
||||
// for the benefit of PStats; threads with the same sync
|
||||
// name can be ticked all at once via the thread_tick()
|
||||
// call.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE const string &Thread::
|
||||
get_sync_name() const {
|
||||
return _sync_name;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Thread::get_pstats_index
|
||||
// Access: Public
|
||||
// Description: Returns the PStats index associated with this thread,
|
||||
// or -1 if no index has yet been associated with this
|
||||
// thread. This is used internally by the PStatClient;
|
||||
// you should not need to call this directly.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE int Thread::
|
||||
get_pstats_index() const {
|
||||
return _pstats_index;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Thread::set_pstats_index
|
||||
// Access: Public
|
||||
// Description: Stores a PStats index to be associated with this
|
||||
// thread. This is used internally by the PStatClient;
|
||||
// you should not need to call this directly.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void Thread::
|
||||
set_pstats_index(int pstats_index) {
|
||||
_pstats_index = pstats_index;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Thread::start
|
||||
// Access: Public
|
||||
|
|
@ -147,18 +201,47 @@ get_main_thread() {
|
|||
return _main_thread;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Thread::get_external_thread
|
||||
// Access: Public, Static
|
||||
// Description: Returns a pointer to the "external" Thread
|
||||
// object--this is a special Thread object that
|
||||
// corresponds to any thread spawned outside of Panda's
|
||||
// threading interface. Note that multiple different
|
||||
// threads may share this same pointer.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE Thread *Thread::
|
||||
get_external_thread() {
|
||||
if (_external_thread == (Thread *)NULL) {
|
||||
init_external_thread();
|
||||
}
|
||||
return _external_thread;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Thread::get_current_thread
|
||||
// Access: Public, Static
|
||||
// Description: Returns a pointer to the currently-executing Thread
|
||||
// object. If this is called from the main thread, this
|
||||
// will return the same value as get_main_thread(). If
|
||||
// the current thread was spawned outside of Panda's
|
||||
// threading system, this might return NULL.
|
||||
// will return the same value as get_main_thread().
|
||||
//
|
||||
// This will always return some valid Thread pointer.
|
||||
// It will never return NULL, even if the current thread
|
||||
// was spawned outside of Panda's threading system,
|
||||
// although all non-Panda threads will return the exact
|
||||
// same Thread pointer.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE Thread *Thread::
|
||||
get_current_thread() {
|
||||
return ThreadImpl::get_current_thread();
|
||||
#ifndef HAVE_THREADS
|
||||
return get_main_thread();
|
||||
#else // HAVE_THREADS
|
||||
Thread *thread = ThreadImpl::get_current_thread();
|
||||
if (thread == (Thread *)NULL) {
|
||||
return Thread::get_external_thread();
|
||||
}
|
||||
return thread;
|
||||
#endif // HAVE_THREADS
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -18,8 +18,10 @@
|
|||
|
||||
#include "thread.h"
|
||||
#include "mainThread.h"
|
||||
#include "externalThread.h"
|
||||
|
||||
Thread *Thread::_main_thread;
|
||||
Thread *Thread::_external_thread;
|
||||
TypeHandle Thread::_type_handle;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -51,6 +53,18 @@ void Thread::
|
|||
init_main_thread() {
|
||||
if (_main_thread == (Thread *)NULL) {
|
||||
_main_thread = new MainThread;
|
||||
((Thread *)_main_thread)->_started = true;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Thread::init_external_thread
|
||||
// Access: Private, Static
|
||||
// Description: Creates the Thread object that represents all of the
|
||||
// external threads.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void Thread::
|
||||
init_external_thread() {
|
||||
if (_external_thread == (Thread *)NULL) {
|
||||
_external_thread = new ExternalThread;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@
|
|||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDAEXPRESS Thread : public TypedReferenceCount {
|
||||
public:
|
||||
INLINE Thread(const string &name);
|
||||
INLINE Thread(const string &name, const string &sync_name);
|
||||
virtual ~Thread();
|
||||
|
||||
private:
|
||||
|
|
@ -51,6 +51,10 @@ protected:
|
|||
|
||||
public:
|
||||
INLINE const string &get_name() const;
|
||||
INLINE const string &get_sync_name() const;
|
||||
|
||||
INLINE int get_pstats_index() const;
|
||||
INLINE void set_pstats_index(int pstats_index);
|
||||
|
||||
INLINE bool start(ThreadPriority priority, bool global, bool joinable);
|
||||
INLINE void interrupt();
|
||||
|
|
@ -59,6 +63,7 @@ public:
|
|||
INLINE static void prepare_for_exit();
|
||||
|
||||
INLINE static Thread *get_main_thread();
|
||||
INLINE static Thread *get_external_thread();
|
||||
INLINE static Thread *get_current_thread();
|
||||
INLINE static bool is_threading_supported();
|
||||
INLINE static void sleep(double seconds);
|
||||
|
|
@ -67,12 +72,18 @@ public:
|
|||
|
||||
private:
|
||||
static void init_main_thread();
|
||||
static void init_external_thread();
|
||||
|
||||
protected:
|
||||
bool _started;
|
||||
string _name;
|
||||
string _sync_name;
|
||||
ThreadImpl _impl;
|
||||
int _pstats_index;
|
||||
|
||||
private:
|
||||
static Thread *_main_thread;
|
||||
static Thread *_external_thread;
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
|
|
|
|||
|
|
@ -106,6 +106,18 @@ p() const {
|
|||
return (To *)WeakPointerToBase<T>::_void_ptr;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: WeakPointerTo::get_orig
|
||||
// Access: Public
|
||||
// Description: Returns the original pointer value, even if the
|
||||
// object has since been deleted.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class T>
|
||||
INLINE TYPENAME WeakPointerTo<T>::To *WeakPointerTo<T>::
|
||||
get_orig() const {
|
||||
return (To *)WeakPointerToBase<T>::_void_ptr;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: WeakPointerTo::Assignment operator
|
||||
// Access: Public
|
||||
|
|
@ -258,6 +270,18 @@ p() const {
|
|||
return (To *)WeakPointerToBase<T>::_void_ptr;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: WeakConstPointerTo::get_orig
|
||||
// Access: Public
|
||||
// Description: Returns the original pointer value, even if the
|
||||
// object has since been deleted.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class T>
|
||||
INLINE const TYPENAME WeakConstPointerTo<T>::To *WeakConstPointerTo<T>::
|
||||
get_orig() const {
|
||||
return (To *)WeakPointerToBase<T>::_void_ptr;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: WeakConstPointerTo::Assignment operator
|
||||
// Access: Public
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ public:
|
|||
|
||||
PUBLISHED:
|
||||
INLINE To *p() const;
|
||||
INLINE To *get_orig() const;
|
||||
|
||||
INLINE WeakPointerTo<T> &operator = (To *ptr);
|
||||
INLINE WeakPointerTo<T> &operator = (const PointerTo<T> ©);
|
||||
|
|
@ -84,6 +85,7 @@ public:
|
|||
|
||||
PUBLISHED:
|
||||
INLINE const To *p() const;
|
||||
INLINE const To *get_orig() const;
|
||||
|
||||
INLINE WeakConstPointerTo<T> &operator = (const To *ptr);
|
||||
INLINE WeakConstPointerTo<T> &operator = (const PointerTo<T> ©);
|
||||
|
|
|
|||
|
|
@ -24,7 +24,8 @@
|
|||
pStatClientVersion.cxx \
|
||||
pStatClientControlMessage.cxx pStatCollectorDef.cxx \
|
||||
pStatFrameData.cxx pStatProperties.cxx \
|
||||
pStatServerControlMessage.cxx
|
||||
pStatServerControlMessage.cxx \
|
||||
pStatThread.cxx
|
||||
|
||||
#define INSTALL_HEADERS \
|
||||
config_pstats.h pStatClient.I pStatClient.h \
|
||||
|
|
|
|||
|
|
@ -120,6 +120,34 @@ get_thread_name(int index) const {
|
|||
return _threads[index]._name;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatClient::get_thread_sync_name
|
||||
// Access: Published
|
||||
// Description: Returns the sync_name of the indicated thread.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE string PStatClient::
|
||||
get_thread_sync_name(int index) const {
|
||||
ReMutexHolder holder(_lock);
|
||||
nassertr(index >= 0 && index < (int)_threads.size(), string());
|
||||
return _threads[index]._sync_name;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatClient::get_thread_object
|
||||
// Access: Published
|
||||
// Description: Returns the Panda Thread object associated with the
|
||||
// indicated PStatThread.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE Thread *PStatClient::
|
||||
get_thread_object(int index) const {
|
||||
ReMutexHolder holder(_lock);
|
||||
nassertr(index >= 0 && index < (int)_threads.size(), NULL);
|
||||
if (_threads[index]._thread.was_deleted()) {
|
||||
return NULL;
|
||||
}
|
||||
return _threads[index]._thread;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatClient::get_clock
|
||||
// Access: Published
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@
|
|||
#include "pStatThread.h"
|
||||
#include "config_pstats.h"
|
||||
#include "pStatProperties.h"
|
||||
#include "thread.h"
|
||||
|
||||
PStatCollector PStatClient::_total_size_pcollector("Memory usage");
|
||||
PStatCollector PStatClient::_cpp_size_pcollector("Memory usage:C++");
|
||||
|
|
@ -68,8 +69,8 @@ PStatClient() :
|
|||
//collector._def->_suggested_color.set(0.5, 0.5, 0.5);
|
||||
_collectors.push_back(collector);
|
||||
|
||||
// We also always have a thread at index 0 named "Main".
|
||||
make_thread("Main");
|
||||
// The main thread is always at index 0.
|
||||
make_thread(Thread::get_main_thread());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -148,20 +149,40 @@ get_thread(int index) const {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatClient::get_main_thread
|
||||
// Access: Published
|
||||
// Description: Returns a handle to the client's "Main", or default,
|
||||
// thread. This is where collectors will be started and
|
||||
// stopped if they don't specify otherwise.
|
||||
// Description: Returns a handle to the client's Main thread. This
|
||||
// is the thread that started the application.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
PStatThread PStatClient::
|
||||
get_main_thread() const {
|
||||
return PStatThread((PStatClient *)this, 0);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatClient::get_current_thread
|
||||
// Access: Published
|
||||
// Description: Returns a handle to the currently-executing thread.
|
||||
// This is the thread that PStatCollectors will be
|
||||
// counted in if they do not specify otherwise.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
PStatThread PStatClient::
|
||||
get_current_thread() const {
|
||||
Thread *thread = Thread::get_current_thread();
|
||||
int thread_index = thread->get_pstats_index();
|
||||
if (thread_index != -1) {
|
||||
return PStatThread((PStatClient *)this, thread_index);
|
||||
}
|
||||
|
||||
// This is the first time we have encountered this current Thread.
|
||||
// Make a new PStatThread object for it.
|
||||
return ((PStatClient *)this)->make_thread(thread);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatClient::main_tick
|
||||
// Access: Published, Static
|
||||
// Description: A convenience function to call new_frame() on the
|
||||
// global PStatClient's main thread.
|
||||
// global PStatClient's main thread, and any other
|
||||
// threads with a sync_name of "Main".
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PStatClient::
|
||||
main_tick() {
|
||||
|
|
@ -185,19 +206,65 @@ main_tick() {
|
|||
get_global_pstats()->client_main_tick();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatClient::thread_tick
|
||||
// Access: Published, Static
|
||||
// Description: A convenience function to call new_frame() on any
|
||||
// threads with the indicated sync_name
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PStatClient::
|
||||
thread_tick(const string &sync_name) {
|
||||
get_global_pstats()->client_thread_tick(sync_name);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatClient::client_main_tick
|
||||
// Access: Published
|
||||
// Description: A convenience function to call new_frame() on the
|
||||
// the given client's main thread.
|
||||
// given PStatClient's main thread, and any other
|
||||
// threads with a sync_name of "Main".
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PStatClient::
|
||||
client_main_tick() {
|
||||
ReMutexHolder holder(_lock);
|
||||
if (has_impl()) {
|
||||
_impl->client_main_tick();
|
||||
|
||||
MultiThingsByName::const_iterator ni =
|
||||
_threads_by_sync_name.find("Main");
|
||||
if (ni != _threads_by_sync_name.end()) {
|
||||
const vector_int &indices = (*ni).second;
|
||||
for (vector_int::const_iterator vi = indices.begin();
|
||||
vi != indices.end();
|
||||
++vi) {
|
||||
_impl->new_frame(*vi);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatClient::client_thread_tick
|
||||
// Access: Published
|
||||
// Description: A convenience function to call new_frame() on all of
|
||||
// the threads with the indicated sync name.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PStatClient::
|
||||
client_thread_tick(const string &sync_name) {
|
||||
ReMutexHolder holder(_lock);
|
||||
|
||||
if (has_impl()) {
|
||||
MultiThingsByName::const_iterator ni =
|
||||
_threads_by_sync_name.find(sync_name);
|
||||
if (ni != _threads_by_sync_name.end()) {
|
||||
const vector_int &indices = (*ni).second;
|
||||
for (vector_int::const_iterator vi = indices.begin();
|
||||
vi != indices.end();
|
||||
++vi) {
|
||||
_impl->new_frame(*vi);
|
||||
}
|
||||
}
|
||||
}
|
||||
get_main_thread().new_frame();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -347,35 +414,56 @@ make_collector_with_name(int parent_index, const string &name) {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatClient::make_thread
|
||||
// Access: Private
|
||||
// Description: Returns a PStatThread with the indicated name
|
||||
// suitable for grouping collectors. This is normally
|
||||
// called by a PStatThread constructor.
|
||||
// Description: Returns a PStatThread for the indicated Panda Thread
|
||||
// object. This is normally called by a PStatThread
|
||||
// constructor.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
PStatThread PStatClient::
|
||||
make_thread(const string &name) {
|
||||
make_thread(Thread *thread) {
|
||||
ReMutexHolder holder(_lock);
|
||||
|
||||
ThingsByName::const_iterator ni =
|
||||
_threads_by_name.find(name);
|
||||
|
||||
if (ni != _threads_by_name.end()) {
|
||||
// We already had a thread by this name; return it.
|
||||
int index = (*ni).second;
|
||||
nassertr(index >= 0 && index < (int)_threads.size(), PStatThread());
|
||||
return PStatThread(this, (*ni).second);
|
||||
int thread_index = thread->get_pstats_index();
|
||||
if (thread_index != -1) {
|
||||
return PStatThread((PStatClient *)this, thread_index);
|
||||
}
|
||||
|
||||
// Create a new thread for this name.
|
||||
MultiThingsByName::const_iterator ni =
|
||||
_threads_by_name.find(thread->get_name());
|
||||
|
||||
if (ni != _threads_by_name.end()) {
|
||||
// We have seen a thread with this name before. Can we re-use any
|
||||
// of them?
|
||||
const vector_int &indices = (*ni).second;
|
||||
for (vector_int::const_iterator vi = indices.begin();
|
||||
vi != indices.end();
|
||||
++vi) {
|
||||
int index = (*vi);
|
||||
nassertr(index >= 0 && index < (int)_threads.size(), PStatThread());
|
||||
if (_threads[index]._thread.was_deleted() &&
|
||||
_threads[index]._sync_name == thread->get_sync_name()) {
|
||||
// Yes, re-use this one.
|
||||
_threads[index]._thread = thread;
|
||||
thread->set_pstats_index(index);
|
||||
return PStatThread(this, index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Create a new PStatsThread for this thread pointer.
|
||||
int new_index = _threads.size();
|
||||
_threads_by_name.insert(ThingsByName::value_type(name, new_index));
|
||||
thread->set_pstats_index(new_index);
|
||||
_threads_by_name[thread->get_name()].push_back(new_index);
|
||||
_threads_by_sync_name[thread->get_sync_name()].push_back(new_index);
|
||||
|
||||
InternalThread pthread;
|
||||
pthread._thread = thread;
|
||||
pthread._name = thread->get_name();
|
||||
pthread._sync_name = thread->get_sync_name();
|
||||
pthread._is_active = false;
|
||||
pthread._next_packet = 0.0;
|
||||
pthread._frame_number = 0;
|
||||
|
||||
Thread thread;
|
||||
thread._name = name;
|
||||
thread._is_active = false;
|
||||
thread._next_packet = 0.0;
|
||||
thread._frame_number = 0;
|
||||
|
||||
_threads.push_back(thread);
|
||||
_threads.push_back(pthread);
|
||||
|
||||
// We need an additional PerThreadData for this thread in all of the
|
||||
// collectors.
|
||||
|
|
@ -508,10 +596,12 @@ stop(int collector_index, int thread_index) {
|
|||
_collectors[collector_index].is_active() &&
|
||||
_threads[thread_index]._is_active) {
|
||||
if (_collectors[collector_index]._per_thread[thread_index]._nested_count == 0) {
|
||||
pstats_cat.warning()
|
||||
<< "Collector " << get_collector_fullname(collector_index)
|
||||
<< " was already stopped in thread " << get_thread_name(thread_index)
|
||||
<< "!\n";
|
||||
if (pstats_cat.is_debug()) {
|
||||
pstats_cat.debug()
|
||||
<< "Collector " << get_collector_fullname(collector_index)
|
||||
<< " was already stopped in thread " << get_thread_name(thread_index)
|
||||
<< "!\n";
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -546,10 +636,12 @@ stop(int collector_index, int thread_index, float as_of) {
|
|||
_collectors[collector_index].is_active() &&
|
||||
_threads[thread_index]._is_active) {
|
||||
if (_collectors[collector_index]._per_thread[thread_index]._nested_count == 0) {
|
||||
pstats_cat.warning()
|
||||
<< "Collector " << get_collector_fullname(collector_index)
|
||||
<< " was already stopped in thread " << get_thread_name(thread_index)
|
||||
<< "!\n";
|
||||
if (pstats_cat.is_debug()) {
|
||||
pstats_cat.debug()
|
||||
<< "Collector " << get_collector_fullname(collector_index)
|
||||
<< " was already stopped in thread " << get_thread_name(thread_index)
|
||||
<< "!\n";
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -28,6 +28,9 @@
|
|||
#include "reMutexHolder.h"
|
||||
#include "luse.h"
|
||||
#include "pmap.h"
|
||||
#include "thread.h"
|
||||
#include "weakPointerTo.h"
|
||||
#include "vector_int.h"
|
||||
|
||||
class PStatCollector;
|
||||
class PStatCollectorDef;
|
||||
|
|
@ -71,8 +74,11 @@ PUBLISHED:
|
|||
INLINE int get_num_threads() const;
|
||||
PStatThread get_thread(int index) const;
|
||||
INLINE string get_thread_name(int index) const;
|
||||
INLINE string get_thread_sync_name(int index) const;
|
||||
INLINE Thread *get_thread_object(int index) const;
|
||||
|
||||
PStatThread get_main_thread() const;
|
||||
PStatThread get_current_thread() const;
|
||||
|
||||
INLINE const ClockObject &get_clock() const;
|
||||
|
||||
|
|
@ -83,8 +89,10 @@ PUBLISHED:
|
|||
INLINE static void resume_after_pause();
|
||||
|
||||
static void main_tick();
|
||||
static void thread_tick(const string &sync_name);
|
||||
|
||||
void client_main_tick();
|
||||
void client_thread_tick(const string &sync_name);
|
||||
INLINE bool client_connect(string hostname, int port);
|
||||
void client_disconnect();
|
||||
INLINE bool client_is_connected() const;
|
||||
|
|
@ -100,7 +108,7 @@ private:
|
|||
|
||||
PStatCollector make_collector_with_relname(int parent_index, string relname);
|
||||
PStatCollector make_collector_with_name(int parent_index, const string &name);
|
||||
PStatThread make_thread(const string &name);
|
||||
PStatThread make_thread(Thread *thread);
|
||||
|
||||
bool is_active(int collector_index, int thread_index) const;
|
||||
bool is_started(int collector_index, int thread_index) const;
|
||||
|
|
@ -119,9 +127,9 @@ private:
|
|||
// This mutex protects everything in this class.
|
||||
ReMutex _lock;
|
||||
|
||||
// Not a phash_map, so the threads remain sorted by name.
|
||||
typedef pmap<string, int> ThingsByName;
|
||||
ThingsByName _threads_by_name;
|
||||
typedef pmap<string, vector_int> MultiThingsByName;
|
||||
MultiThingsByName _threads_by_name, _threads_by_sync_name;
|
||||
|
||||
// This is for the data that is per-collector, per-thread. A vector
|
||||
// of these is stored in each Collector object, below, indexed by
|
||||
|
|
@ -169,15 +177,17 @@ private:
|
|||
// This defines a single thread, i.e. a separate chain of execution,
|
||||
// independent of all other threads. Timing and level data are
|
||||
// maintained separately for each thread.
|
||||
class Thread {
|
||||
class InternalThread {
|
||||
public:
|
||||
WPT(Thread) _thread;
|
||||
string _name;
|
||||
string _sync_name;
|
||||
PStatFrameData _frame_data;
|
||||
bool _is_active;
|
||||
int _frame_number;
|
||||
float _next_packet;
|
||||
};
|
||||
typedef pvector<Thread> Threads;
|
||||
typedef pvector<InternalThread> Threads;
|
||||
Threads _threads;
|
||||
|
||||
PStatClientImpl *_impl;
|
||||
|
|
|
|||
|
|
@ -168,7 +168,7 @@ void PStatClientImpl::
|
|||
new_frame(int thread_index) {
|
||||
nassertv(thread_index >= 0 && thread_index < (int)_client->_threads.size());
|
||||
|
||||
PStatClient::Thread &thread = _client->_threads[thread_index];
|
||||
PStatClient::InternalThread &pthread = _client->_threads[thread_index];
|
||||
|
||||
// If we're the main thread, we should exchange control packets with
|
||||
// the server.
|
||||
|
|
@ -179,34 +179,34 @@ new_frame(int thread_index) {
|
|||
// If we've got the UDP port by the time the frame starts, it's
|
||||
// time to become active and start actually tracking data.
|
||||
if (_got_udp_port) {
|
||||
thread._is_active = true;
|
||||
pthread._is_active = true;
|
||||
}
|
||||
|
||||
if (!thread._is_active) {
|
||||
if (!pthread._is_active) {
|
||||
return;
|
||||
}
|
||||
|
||||
float frame_start = _clock.get_real_time();
|
||||
|
||||
if (!thread._frame_data.is_empty()) {
|
||||
if (!pthread._frame_data.is_empty()) {
|
||||
// Collector 0 is the whole frame.
|
||||
_client->stop(0, thread_index, frame_start);
|
||||
|
||||
// Fill up the level data for all the collectors who have level
|
||||
// data for this thread.
|
||||
// data for this pthread.
|
||||
int num_collectors = _client->_collectors.size();
|
||||
for (int i = 0; i < num_collectors; i++) {
|
||||
const PStatClient::PerThreadData &ptd =
|
||||
_client->_collectors[i]._per_thread[thread_index];
|
||||
if (ptd._has_level) {
|
||||
thread._frame_data.add_level(i, ptd._level);
|
||||
pthread._frame_data.add_level(i, ptd._level);
|
||||
}
|
||||
}
|
||||
transmit_frame_data(thread_index);
|
||||
}
|
||||
|
||||
thread._frame_data.clear();
|
||||
thread._frame_number++;
|
||||
pthread._frame_data.clear();
|
||||
pthread._frame_number++;
|
||||
_client->start(0, thread_index, frame_start);
|
||||
|
||||
// Also record the time for the PStats operation itself.
|
||||
|
|
|
|||
|
|
@ -134,7 +134,11 @@ operator = (const PStatCollector ©) {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool PStatCollector::
|
||||
is_active() {
|
||||
#ifndef HAVE_THREADS
|
||||
return _client->is_active(_index, 0);
|
||||
#else // HAVE_THREADS
|
||||
return is_active(_client->get_current_thread());
|
||||
#endif // HAVE_THREADS
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -145,7 +149,11 @@ is_active() {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool PStatCollector::
|
||||
is_started() {
|
||||
#ifndef HAVE_THREADS
|
||||
return _client->is_started(_index, 0);
|
||||
#else // HAVE_THREADS
|
||||
return is_started(_client->get_current_thread());
|
||||
#endif // HAVE_THREADS
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -156,7 +164,11 @@ is_started() {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void PStatCollector::
|
||||
start() {
|
||||
#ifndef HAVE_THREADS
|
||||
_client->start(_index, 0);
|
||||
#else // HAVE_THREADS
|
||||
start(_client->get_current_thread());
|
||||
#endif // HAVE_THREADS
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -167,7 +179,11 @@ start() {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void PStatCollector::
|
||||
stop() {
|
||||
#ifndef HAVE_THREADS
|
||||
_client->stop(_index, 0);
|
||||
#else // HAVE_THREADS
|
||||
stop(_client->get_current_thread());
|
||||
#endif // HAVE_THREADS
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -180,7 +196,11 @@ stop() {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void PStatCollector::
|
||||
clear_level() {
|
||||
#ifndef HAVE_THREADS
|
||||
_client->clear_level(_index, 0);
|
||||
#else // HAVE_THREADS
|
||||
clear_level(_client->get_current_thread());
|
||||
#endif // HAVE_THREADS
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -192,7 +212,11 @@ clear_level() {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void PStatCollector::
|
||||
set_level(float level) {
|
||||
#ifndef HAVE_THREADS
|
||||
_client->set_level(_index, 0, level);
|
||||
#else // HAVE_THREADS
|
||||
set_level(_client->get_current_thread(), level);
|
||||
#endif // HAVE_THREADS
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -206,7 +230,11 @@ set_level(float level) {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void PStatCollector::
|
||||
add_level(float increment) {
|
||||
#ifndef HAVE_THREADS
|
||||
_client->add_level(_index, 0, increment);
|
||||
#else // HAVE_THREADS
|
||||
add_level(_client->get_current_thread(), increment);
|
||||
#endif // HAVE_THREADS
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -220,7 +248,11 @@ add_level(float increment) {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void PStatCollector::
|
||||
sub_level(float decrement) {
|
||||
_client->add_level(_index, 0, -decrement);
|
||||
#ifndef HAVE_THREADS
|
||||
_client->sub_level(_index, 0, decrement);
|
||||
#else // HAVE_THREADS
|
||||
sub_level(_client->get_current_thread(), decrement);
|
||||
#endif // HAVE_THREADS
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -230,12 +262,16 @@ sub_level(float decrement) {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
INLINE float PStatCollector::
|
||||
get_level() {
|
||||
#ifndef HAVE_THREADS
|
||||
return _client->get_level(_index, 0);
|
||||
#else // HAVE_THREADS
|
||||
return get_level(_client->get_current_thread());
|
||||
#endif // HAVE_THREADS
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatCollector::is_active
|
||||
// Access: Public
|
||||
// Access: Published
|
||||
// Description: Returns true if this particular collector is active
|
||||
// on the indicated thread, and we are currently
|
||||
// transmitting PStats data.
|
||||
|
|
@ -247,7 +283,7 @@ is_active(const PStatThread &thread) {
|
|||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatCollector::is_started
|
||||
// Access: Public
|
||||
// Access: Published
|
||||
// Description: Returns true if this particular collector has been
|
||||
// started on the indicated thread, or false otherwise.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -258,7 +294,7 @@ is_started(const PStatThread &thread) {
|
|||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatCollector::start
|
||||
// Access: Public
|
||||
// Access: Published
|
||||
// Description: Starts this timer ticking within a particular thread.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void PStatCollector::
|
||||
|
|
@ -268,7 +304,7 @@ start(const PStatThread &thread) {
|
|||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatCollector::start
|
||||
// Access: Public
|
||||
// Access: Published
|
||||
// Description: Marks that the timer should have been started as of
|
||||
// the indicated time. This must be a time based on the
|
||||
// PStatClient's clock (see PStatClient::get_clock()),
|
||||
|
|
@ -282,7 +318,7 @@ start(const PStatThread &thread, float as_of) {
|
|||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatCollector::stop
|
||||
// Access: Public
|
||||
// Access: Published
|
||||
// Description: Stops this timer within a particular thread.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void PStatCollector::
|
||||
|
|
@ -292,7 +328,7 @@ stop(const PStatThread &thread) {
|
|||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatCollector::stop
|
||||
// Access: Public
|
||||
// Access: Published
|
||||
// Description: Marks that the timer should have been stopped as of
|
||||
// the indicated time. This must be a time based on the
|
||||
// PStatClient's clock (see PStatClient::get_clock()),
|
||||
|
|
@ -306,7 +342,7 @@ stop(const PStatThread &thread, float as_of) {
|
|||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatCollector::clear_level
|
||||
// Access: Public
|
||||
// Access: Published
|
||||
// Description: Removes the level setting associated with this
|
||||
// collector for the indicated thread. The collector
|
||||
// will no longer show up on any level graphs in this
|
||||
|
|
@ -319,7 +355,7 @@ clear_level(const PStatThread &thread) {
|
|||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatCollector::set_level
|
||||
// Access: Public
|
||||
// Access: Published
|
||||
// Description: Sets the level setting associated with this
|
||||
// collector for the indicated thread to the indicated
|
||||
// value.
|
||||
|
|
@ -331,7 +367,7 @@ set_level(const PStatThread &thread, float level) {
|
|||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatCollector::add_level
|
||||
// Access: Public
|
||||
// Access: Published
|
||||
// Description: Adds the indicated increment (which may be negative)
|
||||
// to the level setting associated with this collector
|
||||
// for the indicated thread. If the collector did not
|
||||
|
|
@ -345,7 +381,7 @@ add_level(const PStatThread &thread, float increment) {
|
|||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatCollector::sub_level
|
||||
// Access: Public
|
||||
// Access: Published
|
||||
// Description: Subtracts the indicated decrement (which may be
|
||||
// negative) to the level setting associated with this
|
||||
// collector for the indicated thread. If the collector
|
||||
|
|
@ -359,7 +395,7 @@ sub_level(const PStatThread &thread, float decrement) {
|
|||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatCollector::get_level
|
||||
// Access: Public
|
||||
// Access: Published
|
||||
// Description: Returns the current level value of the given collector.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE float PStatCollector::
|
||||
|
|
@ -369,7 +405,7 @@ get_level(const PStatThread &thread) {
|
|||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatCollector::get_index
|
||||
// Access: Public
|
||||
// Access: Published
|
||||
// Description: Returns the index number of this particular collector
|
||||
// within the PStatClient.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -77,9 +77,6 @@ PUBLISHED:
|
|||
INLINE void sub_level(float decrement);
|
||||
INLINE float get_level();
|
||||
|
||||
INLINE int get_index() const;
|
||||
|
||||
public:
|
||||
INLINE bool is_active(const PStatThread &thread);
|
||||
INLINE bool is_started(const PStatThread &thread);
|
||||
INLINE void start(const PStatThread &thread);
|
||||
|
|
@ -93,6 +90,8 @@ public:
|
|||
INLINE void sub_level(const PStatThread &thread, float decrement);
|
||||
INLINE float get_level(const PStatThread &thread);
|
||||
|
||||
INLINE int get_index() const;
|
||||
|
||||
private:
|
||||
PStatClient *_client;
|
||||
int _index;
|
||||
|
|
@ -117,7 +116,6 @@ PUBLISHED:
|
|||
INLINE void sub_level(float) { }
|
||||
INLINE float get_level() { return 0.0; }
|
||||
|
||||
public:
|
||||
INLINE bool is_active(const PStatThread &) { return false; }
|
||||
INLINE void start(const PStatThread &) { }
|
||||
INLINE void start(const PStatThread &, float) { }
|
||||
|
|
@ -130,6 +128,8 @@ public:
|
|||
INLINE void sub_level(const PStatThread &, float) { }
|
||||
INLINE float get_level(const PStatThread &) { return 0.0; }
|
||||
|
||||
INLINE int get_index() const { return 0; }
|
||||
|
||||
#endif // DO_PSTATS
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -109,6 +109,7 @@ struct LevelCollectorProperties {
|
|||
};
|
||||
|
||||
static TimeCollectorProperties time_properties[] = {
|
||||
{ 1, "Wait", { 0.6, 0.6, 0.6 } },
|
||||
{ 1, "App", { 0.0, 0.8, 0.4 }, 1.0 / 30.0 },
|
||||
{ 1, "App:Collisions", { 1.0, 0.5, 0.0 } },
|
||||
{ 1, "App:Collisions:Reset", { 0.0, 0.0, 0.5 } },
|
||||
|
|
|
|||
|
|
@ -48,17 +48,15 @@ PStatThread(PStatClient *client, int index) :
|
|||
// Description: Creates a new named thread. This will be used to
|
||||
// unify tasks that share a common thread, and
|
||||
// differentiate tasks that occur in different threads.
|
||||
// If any two different PStatThread objects share the
|
||||
// same name, then they are really the same thread.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE PStatThread::
|
||||
PStatThread(const string &name, PStatClient *client) {
|
||||
PStatThread(Thread *thread, PStatClient *client) {
|
||||
#ifdef DO_PSTATS
|
||||
if (client == (PStatClient *)NULL) {
|
||||
client = PStatClient::get_global_pstats();
|
||||
}
|
||||
PStatThread thread(client->make_thread(name));
|
||||
(*this) = thread;
|
||||
PStatThread pthread(client->make_thread(thread));
|
||||
(*this) = pthread;
|
||||
#else
|
||||
_client = (PStatClient *)NULL;
|
||||
_index = 0;
|
||||
|
|
@ -95,6 +93,10 @@ operator = (const PStatThread ©) {
|
|||
// whatever a frame may be deemed to be, to accumulate
|
||||
// all the stats that have collected so far for the
|
||||
// thread and ship them off to the server.
|
||||
//
|
||||
// Calling PStatClient::thread_tick() will automatically
|
||||
// call this for any threads with the indicated sync
|
||||
// name.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void PStatThread::
|
||||
new_frame() {
|
||||
|
|
@ -102,3 +104,14 @@ new_frame() {
|
|||
_client->get_impl()->new_frame(_index);
|
||||
#endif
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatThread::get_index
|
||||
// Access: Published
|
||||
// Description: Returns the index number of this particular thread
|
||||
// within the PStatClient.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE int PStatThread::
|
||||
get_index() const {
|
||||
return _index;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,31 @@
|
|||
// Filename: pStatThread.cxx
|
||||
// Created by: drose (30Jan06)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d-general@lists.sourceforge.net .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "pStatThread.h"
|
||||
#include "pStatClient.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatThread::get_thread
|
||||
// Access: Published
|
||||
// Description: Returns the Panda Thread object associated with this
|
||||
// particular PStatThread.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE Thread *PStatThread::
|
||||
get_thread() const {
|
||||
return _client->get_thread_object(_index);
|
||||
}
|
||||
|
|
@ -23,29 +23,30 @@
|
|||
|
||||
#include "pStatClient.h"
|
||||
|
||||
class Thread;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : PStatThread
|
||||
// Description : A lightweight class that represents a single thread
|
||||
// of execution to PStats. It doesn't have any real
|
||||
// connection to any actual threads, but it's used to
|
||||
// differentiate tasks which run in different threads,
|
||||
// so we can measure them properly. It is presently the
|
||||
// user's responsibility to correctly differentiate the
|
||||
// various threads.
|
||||
// of execution to PStats. It corresponds one-to-one
|
||||
// with Panda's Thread instance.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDA PStatThread {
|
||||
private:
|
||||
INLINE PStatThread();
|
||||
INLINE PStatThread(PStatClient *client, int index);
|
||||
|
||||
public:
|
||||
INLINE PStatThread(const string &name, PStatClient *client = NULL);
|
||||
PUBLISHED:
|
||||
INLINE PStatThread(Thread *thread, PStatClient *client = NULL);
|
||||
|
||||
INLINE PStatThread(const PStatThread ©);
|
||||
INLINE void operator = (const PStatThread ©);
|
||||
|
||||
INLINE void new_frame();
|
||||
|
||||
Thread *get_thread() const;
|
||||
INLINE int get_index() const;
|
||||
|
||||
private:
|
||||
PStatClient *_client;
|
||||
int _index;
|
||||
|
|
|
|||
|
|
@ -3,3 +3,4 @@
|
|||
#include "pStatFrameData.cxx"
|
||||
#include "pStatProperties.cxx"
|
||||
#include "pStatServerControlMessage.cxx"
|
||||
#include "pStatThread.cxx"
|
||||
|
|
|
|||
Loading…
Reference in New Issue