mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-04 10:54:24 -04:00
more threading issues
This commit is contained in:
parent
92b907eb07
commit
8567173ece
@ -32,7 +32,7 @@
|
|||||||
// Thus, for example, "cull/draw" indicates that the
|
// Thus, for example, "cull/draw" indicates that the
|
||||||
// window will be culled in a thread called "cull", and
|
// window will be culled in a thread called "cull", and
|
||||||
// drawn in a separate thread called "draw".
|
// drawn in a separate thread called "draw".
|
||||||
// "draw/draw" or simply "draw/" indicates the window
|
// "draw/draw" or simply "draw" indicates the window
|
||||||
// will be culled and drawn in the same thread, "draw".
|
// will be culled and drawn in the same thread, "draw".
|
||||||
// On the other hand, "/draw" indicates the thread will
|
// On the other hand, "/draw" indicates the thread will
|
||||||
// be culled in the main, or app thread, and drawn in a
|
// be culled in the main, or app thread, and drawn in a
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
#include "mouseButton.h"
|
#include "mouseButton.h"
|
||||||
#include "keyboardButton.h"
|
#include "keyboardButton.h"
|
||||||
#include "mutexHolder.h"
|
#include "mutexHolder.h"
|
||||||
|
#include "reMutexHolder.h"
|
||||||
#include "throw_event.h"
|
#include "throw_event.h"
|
||||||
|
|
||||||
TypeHandle GraphicsWindow::_type_handle;
|
TypeHandle GraphicsWindow::_type_handle;
|
||||||
@ -77,7 +78,7 @@ WindowProperties GraphicsWindow::
|
|||||||
get_properties() const {
|
get_properties() const {
|
||||||
WindowProperties result;
|
WindowProperties result;
|
||||||
{
|
{
|
||||||
MutexHolder holder(_properties_lock);
|
ReMutexHolder holder(_properties_lock);
|
||||||
result = _properties;
|
result = _properties;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
@ -95,7 +96,7 @@ WindowProperties GraphicsWindow::
|
|||||||
get_requested_properties() const {
|
get_requested_properties() const {
|
||||||
WindowProperties result;
|
WindowProperties result;
|
||||||
{
|
{
|
||||||
MutexHolder holder(_properties_lock);
|
ReMutexHolder holder(_properties_lock);
|
||||||
result = _requested_properties;
|
result = _requested_properties;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
@ -109,7 +110,7 @@ get_requested_properties() const {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void GraphicsWindow::
|
void GraphicsWindow::
|
||||||
clear_rejected_properties() {
|
clear_rejected_properties() {
|
||||||
MutexHolder holder(_properties_lock);
|
ReMutexHolder holder(_properties_lock);
|
||||||
_rejected_properties.clear();
|
_rejected_properties.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -126,7 +127,7 @@ WindowProperties GraphicsWindow::
|
|||||||
get_rejected_properties() const {
|
get_rejected_properties() const {
|
||||||
WindowProperties result;
|
WindowProperties result;
|
||||||
{
|
{
|
||||||
MutexHolder holder(_properties_lock);
|
ReMutexHolder holder(_properties_lock);
|
||||||
result = _rejected_properties;
|
result = _rejected_properties;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
@ -145,7 +146,7 @@ get_rejected_properties() const {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void GraphicsWindow::
|
void GraphicsWindow::
|
||||||
request_properties(const WindowProperties &requested_properties) {
|
request_properties(const WindowProperties &requested_properties) {
|
||||||
MutexHolder holder(_properties_lock);
|
ReMutexHolder holder(_properties_lock);
|
||||||
_requested_properties.add_properties(requested_properties);
|
_requested_properties.add_properties(requested_properties);
|
||||||
|
|
||||||
if (!_has_size && _requested_properties.has_size()) {
|
if (!_has_size && _requested_properties.has_size()) {
|
||||||
@ -186,7 +187,7 @@ is_active() const {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void GraphicsWindow::
|
void GraphicsWindow::
|
||||||
set_window_event(const string &window_event) {
|
set_window_event(const string &window_event) {
|
||||||
MutexHolder holder(_properties_lock);
|
ReMutexHolder holder(_properties_lock);
|
||||||
_window_event = window_event;
|
_window_event = window_event;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -200,7 +201,7 @@ set_window_event(const string &window_event) {
|
|||||||
string GraphicsWindow::
|
string GraphicsWindow::
|
||||||
get_window_event() const {
|
get_window_event() const {
|
||||||
string result;
|
string result;
|
||||||
MutexHolder holder(_properties_lock);
|
ReMutexHolder holder(_properties_lock);
|
||||||
result = _window_event;
|
result = _window_event;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -231,7 +232,7 @@ get_window_event() const {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void GraphicsWindow::
|
void GraphicsWindow::
|
||||||
set_close_request_event(const string &close_request_event) {
|
set_close_request_event(const string &close_request_event) {
|
||||||
MutexHolder holder(_properties_lock);
|
ReMutexHolder holder(_properties_lock);
|
||||||
_close_request_event = close_request_event;
|
_close_request_event = close_request_event;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -247,7 +248,7 @@ set_close_request_event(const string &close_request_event) {
|
|||||||
string GraphicsWindow::
|
string GraphicsWindow::
|
||||||
get_close_request_event() const {
|
get_close_request_event() const {
|
||||||
string result;
|
string result;
|
||||||
MutexHolder holder(_properties_lock);
|
ReMutexHolder holder(_properties_lock);
|
||||||
result = _close_request_event;
|
result = _close_request_event;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -495,7 +496,7 @@ process_events() {
|
|||||||
// bitmask after all.
|
// bitmask after all.
|
||||||
WindowProperties properties;
|
WindowProperties properties;
|
||||||
{
|
{
|
||||||
MutexHolder holder(_properties_lock);
|
ReMutexHolder holder(_properties_lock);
|
||||||
properties = _requested_properties;
|
properties = _requested_properties;
|
||||||
_requested_properties.clear();
|
_requested_properties.clear();
|
||||||
|
|
||||||
@ -534,6 +535,7 @@ set_properties_now(WindowProperties &properties) {
|
|||||||
properties.get_open() != _properties.get_open()) {
|
properties.get_open() != _properties.get_open()) {
|
||||||
// Open or close a new window. In this case we can get all of the
|
// Open or close a new window. In this case we can get all of the
|
||||||
// properties at once.
|
// properties at once.
|
||||||
|
|
||||||
_properties.add_properties(properties);
|
_properties.add_properties(properties);
|
||||||
properties.clear();
|
properties.clear();
|
||||||
|
|
||||||
@ -687,7 +689,7 @@ system_changed_properties(const WindowProperties &properties) {
|
|||||||
<< "system_changed_properties(" << properties << ")\n";
|
<< "system_changed_properties(" << properties << ")\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
MutexHolder holder(_properties_lock);
|
ReMutexHolder holder(_properties_lock);
|
||||||
|
|
||||||
if (properties.has_size()) {
|
if (properties.has_size()) {
|
||||||
system_changed_size(properties.get_x_size(), properties.get_y_size());
|
system_changed_size(properties.get_x_size(), properties.get_y_size());
|
||||||
|
@ -29,6 +29,7 @@
|
|||||||
#include "buttonEvent.h"
|
#include "buttonEvent.h"
|
||||||
#include "notify.h"
|
#include "notify.h"
|
||||||
#include "pmutex.h"
|
#include "pmutex.h"
|
||||||
|
#include "remutex.h"
|
||||||
#include "pvector.h"
|
#include "pvector.h"
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
@ -110,7 +111,7 @@ protected:
|
|||||||
WindowProperties _properties;
|
WindowProperties _properties;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Mutex _properties_lock;
|
ReMutex _properties_lock;
|
||||||
// protects _requested_properties, _rejected_properties, and
|
// protects _requested_properties, _rejected_properties, and
|
||||||
// _window_event.
|
// _window_event.
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@ bool Mutex::
|
|||||||
debug_is_locked() const {
|
debug_is_locked() const {
|
||||||
return (_locking_thread == Thread::get_current_thread());
|
return (_locking_thread == Thread::get_current_thread());
|
||||||
}
|
}
|
||||||
#endif
|
#endif // NDEBUG
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: Mutex::do_lock
|
// Function: Mutex::do_lock
|
||||||
|
@ -121,3 +121,17 @@ get_lock_count() const {
|
|||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef NDEBUG
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: ReMutex::debug_is_locked
|
||||||
|
// Access: Public
|
||||||
|
// Description: The same as is_locked(). This method name is
|
||||||
|
// provided just to maintain symmetry with Mutex (which
|
||||||
|
// doesn't provide an is_locked() method).
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE bool ReMutex::
|
||||||
|
debug_is_locked() const {
|
||||||
|
return is_locked();
|
||||||
|
}
|
||||||
|
#endif // NDEBUG
|
||||||
|
@ -48,6 +48,10 @@ public:
|
|||||||
INLINE bool is_locked() const;
|
INLINE bool is_locked() const;
|
||||||
INLINE int get_lock_count() const;
|
INLINE int get_lock_count() const;
|
||||||
|
|
||||||
|
#ifndef NDEBUG
|
||||||
|
INLINE bool debug_is_locked() const;
|
||||||
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void do_lock();
|
void do_lock();
|
||||||
void do_release();
|
void do_release();
|
||||||
|
@ -397,6 +397,13 @@ init_libpgraph() {
|
|||||||
TransformState::register_with_read_factory();
|
TransformState::register_with_read_factory();
|
||||||
TransparencyAttrib::register_with_read_factory();
|
TransparencyAttrib::register_with_read_factory();
|
||||||
|
|
||||||
|
// By initializing the _states map up front, we also guarantee that
|
||||||
|
// the _states_lock mutex gets created before we spawn any threads
|
||||||
|
// (assuming no one is creating threads at static init time).
|
||||||
|
TransformState::init_states();
|
||||||
|
RenderState::init_states();
|
||||||
|
RenderEffects::init_states();
|
||||||
|
|
||||||
LoaderFileTypeRegistry *reg = LoaderFileTypeRegistry::get_global_ptr();
|
LoaderFileTypeRegistry *reg = LoaderFileTypeRegistry::get_global_ptr();
|
||||||
reg->register_type(new LoaderFileTypeBam);
|
reg->register_type(new LoaderFileTypeBam);
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,10 @@
|
|||||||
#include "datagramIterator.h"
|
#include "datagramIterator.h"
|
||||||
#include "indent.h"
|
#include "indent.h"
|
||||||
#include "compareTo.h"
|
#include "compareTo.h"
|
||||||
|
#include "reMutexHolder.h"
|
||||||
|
#include "thread.h"
|
||||||
|
|
||||||
|
ReMutex *RenderEffects::_states_lock = NULL;
|
||||||
RenderEffects::States *RenderEffects::_states = NULL;
|
RenderEffects::States *RenderEffects::_states = NULL;
|
||||||
CPT(RenderEffects) RenderEffects::_empty_state;
|
CPT(RenderEffects) RenderEffects::_empty_state;
|
||||||
TypeHandle RenderEffects::_type_handle;
|
TypeHandle RenderEffects::_type_handle;
|
||||||
@ -43,12 +46,7 @@ TypeHandle RenderEffects::_type_handle;
|
|||||||
RenderEffects::
|
RenderEffects::
|
||||||
RenderEffects() {
|
RenderEffects() {
|
||||||
if (_states == (States *)NULL) {
|
if (_states == (States *)NULL) {
|
||||||
// Make sure the global _states map is allocated. This only has
|
init_states();
|
||||||
// to be done once. We could make this map static, but then we
|
|
||||||
// run into problems if anyone creates a RenderState object at
|
|
||||||
// static init time; it also seems to cause problems when the
|
|
||||||
// Panda shared library is unloaded at application exit time.
|
|
||||||
_states = new States;
|
|
||||||
}
|
}
|
||||||
_saved_entry = _states->end();
|
_saved_entry = _states->end();
|
||||||
_flags = 0;
|
_flags = 0;
|
||||||
@ -83,6 +81,7 @@ operator = (const RenderEffects &) {
|
|||||||
RenderEffects::
|
RenderEffects::
|
||||||
~RenderEffects() {
|
~RenderEffects() {
|
||||||
// Remove the deleted RenderEffects object from the global pool.
|
// Remove the deleted RenderEffects object from the global pool.
|
||||||
|
ReMutexHolder holder(*_states_lock);
|
||||||
if (_saved_entry != _states->end()) {
|
if (_saved_entry != _states->end()) {
|
||||||
_states->erase(_saved_entry);
|
_states->erase(_saved_entry);
|
||||||
_saved_entry = _states->end();
|
_saved_entry = _states->end();
|
||||||
@ -423,6 +422,72 @@ write(ostream &out, int indent_level) const {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: RenderEffects::get_num_states
|
||||||
|
// Access: Published, Static
|
||||||
|
// Description: Returns the total number of unique RenderEffects
|
||||||
|
// objects allocated in the world. This will go up and
|
||||||
|
// down during normal operations.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
int RenderEffects::
|
||||||
|
get_num_states() {
|
||||||
|
if (_states == (States *)NULL) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
ReMutexHolder holder(*_states_lock);
|
||||||
|
return _states->size();
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: RenderEffects::list_states
|
||||||
|
// Access: Published, Static
|
||||||
|
// Description: Lists all of the RenderEffectss in the cache to the
|
||||||
|
// output stream, one per line. This can be quite a lot
|
||||||
|
// of output if the cache is large, so be prepared.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
void RenderEffects::
|
||||||
|
list_states(ostream &out) {
|
||||||
|
out << _states->size() << " states:\n";
|
||||||
|
States::const_iterator si;
|
||||||
|
for (si = _states->begin(); si != _states->end(); ++si) {
|
||||||
|
const RenderEffects *state = (*si);
|
||||||
|
state->write(out, 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: RenderEffects::validate_states
|
||||||
|
// Access: Published, Static
|
||||||
|
// Description: Ensures that the cache is still stored in sorted
|
||||||
|
// order. Returns true if so, false if there is a
|
||||||
|
// problem (which implies someone has modified one of
|
||||||
|
// the supposedly-const RenderEffects objects).
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
bool RenderEffects::
|
||||||
|
validate_states() {
|
||||||
|
if (_states->empty()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
ReMutexHolder holder(*_states_lock);
|
||||||
|
|
||||||
|
States::const_iterator si = _states->begin();
|
||||||
|
States::const_iterator snext = si;
|
||||||
|
++snext;
|
||||||
|
while (snext != _states->end()) {
|
||||||
|
if (!(*(*si) < *(*snext))) {
|
||||||
|
pgraph_cat.error()
|
||||||
|
<< "RenderEffectss out of order!\n";
|
||||||
|
(*si)->write(pgraph_cat.error(false), 2);
|
||||||
|
(*snext)->write(pgraph_cat.error(false), 2);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
si = snext;
|
||||||
|
++snext;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: RenderEffects::cull_callback
|
// Function: RenderEffects::cull_callback
|
||||||
// Access: Public
|
// Access: Public
|
||||||
@ -460,70 +525,30 @@ adjust_transform(CPT(TransformState) &net_transform,
|
|||||||
(*ei)._effect->adjust_transform(net_transform, node_transform);
|
(*ei)._effect->adjust_transform(net_transform, node_transform);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: RenderEffects::get_num_states
|
// Function: RenderEffects::init_states
|
||||||
// Access: Published, Static
|
// Access: Public, Static
|
||||||
// Description: Returns the total number of unique RenderEffects
|
// Description: Make sure the global _states map is allocated. This
|
||||||
// objects allocated in the world. This will go up and
|
// only has to be done once. We could make this map
|
||||||
// down during normal operations.
|
// static, but then we run into problems if anyone
|
||||||
////////////////////////////////////////////////////////////////////
|
// creates a RenderEffects object at static init time;
|
||||||
int RenderEffects::
|
// it also seems to cause problems when the Panda shared
|
||||||
get_num_states() {
|
// library is unloaded at application exit time.
|
||||||
if (_states == (States *)NULL) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return _states->size();
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
// Function: RenderEffects::list_states
|
|
||||||
// Access: Published, Static
|
|
||||||
// Description: Lists all of the RenderEffectss in the cache to the
|
|
||||||
// output stream, one per line. This can be quite a lot
|
|
||||||
// of output if the cache is large, so be prepared.
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void RenderEffects::
|
void RenderEffects::
|
||||||
list_states(ostream &out) {
|
init_states() {
|
||||||
out << _states->size() << " states:\n";
|
_states = new States;
|
||||||
States::const_iterator si;
|
|
||||||
for (si = _states->begin(); si != _states->end(); ++si) {
|
// TODO: we should have a global Panda mutex to allow us to safely
|
||||||
const RenderEffects *state = (*si);
|
// create _states_lock without a startup race condition. For the
|
||||||
state->write(out, 2);
|
// meantime, this is OK because we guarantee that this method is
|
||||||
}
|
// called at static init time, presumably when there is still only
|
||||||
}
|
// one thread in the world.
|
||||||
|
_states_lock = new ReMutex;
|
||||||
////////////////////////////////////////////////////////////////////
|
nassertv(Thread::get_current_thread() == Thread::get_main_thread());
|
||||||
// Function: RenderEffects::validate_states
|
|
||||||
// Access: Published, Static
|
|
||||||
// Description: Ensures that the cache is still stored in sorted
|
|
||||||
// order. Returns true if so, false if there is a
|
|
||||||
// problem (which implies someone has modified one of
|
|
||||||
// the supposedly-const RenderEffects objects).
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
bool RenderEffects::
|
|
||||||
validate_states() {
|
|
||||||
if (_states->empty()) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
States::const_iterator si = _states->begin();
|
|
||||||
States::const_iterator snext = si;
|
|
||||||
++snext;
|
|
||||||
while (snext != _states->end()) {
|
|
||||||
if (!(*(*si) < *(*snext))) {
|
|
||||||
pgraph_cat.error()
|
|
||||||
<< "RenderEffectss out of order!\n";
|
|
||||||
(*si)->write(pgraph_cat.error(false), 2);
|
|
||||||
(*snext)->write(pgraph_cat.error(false), 2);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
si = snext;
|
|
||||||
++snext;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: RenderEffects::return_new
|
// Function: RenderEffects::return_new
|
||||||
@ -541,16 +566,18 @@ CPT(RenderEffects) RenderEffects::
|
|||||||
return_new(RenderEffects *state) {
|
return_new(RenderEffects *state) {
|
||||||
nassertr(state != (RenderEffects *)NULL, state);
|
nassertr(state != (RenderEffects *)NULL, state);
|
||||||
|
|
||||||
// This should be a newly allocated pointer, not one that was used
|
|
||||||
// for anything else.
|
|
||||||
nassertr(state->_saved_entry == _states->end(), state);
|
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
if (paranoid_const) {
|
if (paranoid_const) {
|
||||||
nassertr(validate_states(), state);
|
nassertr(validate_states(), state);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
ReMutexHolder holder(*_states_lock);
|
||||||
|
|
||||||
|
// This should be a newly allocated pointer, not one that was used
|
||||||
|
// for anything else.
|
||||||
|
nassertr(state->_saved_entry == _states->end(), state);
|
||||||
|
|
||||||
// Save the state in a local PointerTo so that it will be freed at
|
// Save the state in a local PointerTo so that it will be freed at
|
||||||
// the end of this function if no one else uses it.
|
// the end of this function if no one else uses it.
|
||||||
CPT(RenderEffects) pt_state = state;
|
CPT(RenderEffects) pt_state = state;
|
||||||
@ -689,6 +716,7 @@ complete_pointers(TypedWritable **p_list, BamReader *manager) {
|
|||||||
nassertr(effect._effect != (RenderEffect *)NULL, pi);
|
nassertr(effect._effect != (RenderEffect *)NULL, pi);
|
||||||
effect._type = effect._effect->get_type();
|
effect._type = effect._effect->get_type();
|
||||||
}
|
}
|
||||||
|
ReMutexHolder holder(*_states_lock);
|
||||||
|
|
||||||
// Now make sure the array is properly sorted. (It won't
|
// Now make sure the array is properly sorted. (It won't
|
||||||
// necessarily preserve its correct sort after being read from bam,
|
// necessarily preserve its correct sort after being read from bam,
|
||||||
|
@ -28,6 +28,7 @@
|
|||||||
#include "typedWritableReferenceCount.h"
|
#include "typedWritableReferenceCount.h"
|
||||||
#include "pointerTo.h"
|
#include "pointerTo.h"
|
||||||
#include "ordered_vector.h"
|
#include "ordered_vector.h"
|
||||||
|
#include "reMutex.h"
|
||||||
|
|
||||||
class CullTraverser;
|
class CullTraverser;
|
||||||
class CullTraverserData;
|
class CullTraverserData;
|
||||||
@ -108,6 +109,8 @@ public:
|
|||||||
virtual void adjust_transform(CPT(TransformState) &net_transform,
|
virtual void adjust_transform(CPT(TransformState) &net_transform,
|
||||||
CPT(TransformState) &node_transform) const;
|
CPT(TransformState) &node_transform) const;
|
||||||
|
|
||||||
|
static void init_states();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static CPT(RenderEffects) return_new(RenderEffects *state);
|
static CPT(RenderEffects) return_new(RenderEffects *state);
|
||||||
void determine_decal();
|
void determine_decal();
|
||||||
@ -116,6 +119,10 @@ private:
|
|||||||
void determine_adjust_transform();
|
void determine_adjust_transform();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
// This mutex protects _states. It also protects any modification
|
||||||
|
// to the cache, which is encoded in _composition_cache and
|
||||||
|
// _invert_composition_cache.
|
||||||
|
static ReMutex *_states_lock;
|
||||||
typedef pset<const RenderEffects *, indirect_less<const RenderEffects *> > States;
|
typedef pset<const RenderEffects *, indirect_less<const RenderEffects *> > States;
|
||||||
static States *_states;
|
static States *_states;
|
||||||
static CPT(RenderEffects) _empty_state;
|
static CPT(RenderEffects) _empty_state;
|
||||||
|
@ -35,7 +35,10 @@
|
|||||||
#include "datagramIterator.h"
|
#include "datagramIterator.h"
|
||||||
#include "indent.h"
|
#include "indent.h"
|
||||||
#include "compareTo.h"
|
#include "compareTo.h"
|
||||||
|
#include "reMutexHolder.h"
|
||||||
|
#include "thread.h"
|
||||||
|
|
||||||
|
ReMutex *RenderState::_states_lock = NULL;
|
||||||
RenderState::States *RenderState::_states = NULL;
|
RenderState::States *RenderState::_states = NULL;
|
||||||
CPT(RenderState) RenderState::_empty_state;
|
CPT(RenderState) RenderState::_empty_state;
|
||||||
UpdateSeq RenderState::_last_cycle_detect;
|
UpdateSeq RenderState::_last_cycle_detect;
|
||||||
@ -59,12 +62,7 @@ TypeHandle RenderState::_type_handle;
|
|||||||
RenderState::
|
RenderState::
|
||||||
RenderState() {
|
RenderState() {
|
||||||
if (_states == (States *)NULL) {
|
if (_states == (States *)NULL) {
|
||||||
// Make sure the global _states map is allocated. This only has
|
init_states();
|
||||||
// to be done once. We could make this map static, but then we
|
|
||||||
// run into problems if anyone creates a RenderState object at
|
|
||||||
// static init time; it also seems to cause problems when the
|
|
||||||
// Panda shared library is unloaded at application exit time.
|
|
||||||
_states = new States;
|
|
||||||
}
|
}
|
||||||
_saved_entry = _states->end();
|
_saved_entry = _states->end();
|
||||||
_flags = 0;
|
_flags = 0;
|
||||||
@ -103,12 +101,13 @@ RenderState::
|
|||||||
nassertv(!is_destructing());
|
nassertv(!is_destructing());
|
||||||
set_destructing();
|
set_destructing();
|
||||||
|
|
||||||
|
ReMutexHolder holder(*_states_lock);
|
||||||
if (_saved_entry != _states->end()) {
|
if (_saved_entry != _states->end()) {
|
||||||
nassertv(_states->find(this) == _saved_entry);
|
nassertv(_states->find(this) == _saved_entry);
|
||||||
_states->erase(_saved_entry);
|
_states->erase(_saved_entry);
|
||||||
_saved_entry = _states->end();
|
_saved_entry = _states->end();
|
||||||
}
|
}
|
||||||
|
|
||||||
remove_cache_pointers();
|
remove_cache_pointers();
|
||||||
|
|
||||||
// If this was true at the beginning of the destructor, but is no
|
// If this was true at the beginning of the destructor, but is no
|
||||||
@ -319,6 +318,8 @@ compose(const RenderState *other) const {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ReMutexHolder holder(*_states_lock);
|
||||||
|
|
||||||
// Is this composition already cached?
|
// Is this composition already cached?
|
||||||
CompositionCache::const_iterator ci = _composition_cache.find(other);
|
CompositionCache::const_iterator ci = _composition_cache.find(other);
|
||||||
if (ci != _composition_cache.end()) {
|
if (ci != _composition_cache.end()) {
|
||||||
@ -397,6 +398,8 @@ invert_compose(const RenderState *other) const {
|
|||||||
return make_empty();
|
return make_empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ReMutexHolder holder(*_states_lock);
|
||||||
|
|
||||||
// Is this composition already cached?
|
// Is this composition already cached?
|
||||||
CompositionCache::const_iterator ci = _invert_composition_cache.find(other);
|
CompositionCache::const_iterator ci = _invert_composition_cache.find(other);
|
||||||
if (ci != _invert_composition_cache.end()) {
|
if (ci != _invert_composition_cache.end()) {
|
||||||
@ -590,6 +593,8 @@ get_override(TypeHandle type) const {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
int RenderState::
|
int RenderState::
|
||||||
unref() const {
|
unref() const {
|
||||||
|
ReMutexHolder holder(*_states_lock);
|
||||||
|
|
||||||
if (get_cache_ref_count() > 0 &&
|
if (get_cache_ref_count() > 0 &&
|
||||||
get_ref_count() == get_cache_ref_count() + 1) {
|
get_ref_count() == get_cache_ref_count() + 1) {
|
||||||
// If we are about to remove the one reference that is not in the
|
// If we are about to remove the one reference that is not in the
|
||||||
@ -598,11 +603,6 @@ unref() const {
|
|||||||
// it exists.
|
// it exists.
|
||||||
|
|
||||||
if (auto_break_cycles) {
|
if (auto_break_cycles) {
|
||||||
// There might be a tiny race condition if multiple different
|
|
||||||
// threads perform cycle detects on related nodes at the same
|
|
||||||
// time. But the cost of failing the race condition is low--we
|
|
||||||
// end up with a tiny leak that may eventually be discovered, big
|
|
||||||
// deal.
|
|
||||||
++_last_cycle_detect;
|
++_last_cycle_detect;
|
||||||
if (r_detect_cycles(this, this, 1, _last_cycle_detect, NULL)) {
|
if (r_detect_cycles(this, this, 1, _last_cycle_detect, NULL)) {
|
||||||
// Ok, we have a cycle. This will be a leak unless we break the
|
// Ok, we have a cycle. This will be a leak unless we break the
|
||||||
@ -611,6 +611,7 @@ unref() const {
|
|||||||
pgraph_cat.debug()
|
pgraph_cat.debug()
|
||||||
<< "Breaking cycle involving " << (*this) << "\n";
|
<< "Breaking cycle involving " << (*this) << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
((RenderState *)this)->remove_cache_pointers();
|
((RenderState *)this)->remove_cache_pointers();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -684,6 +685,7 @@ get_num_states() {
|
|||||||
if (_states == (States *)NULL) {
|
if (_states == (States *)NULL) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
ReMutexHolder holder(*_states_lock);
|
||||||
return _states->size();
|
return _states->size();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -710,6 +712,7 @@ get_num_unused_states() {
|
|||||||
if (_states == (States *)NULL) {
|
if (_states == (States *)NULL) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
ReMutexHolder holder(*_states_lock);
|
||||||
|
|
||||||
// First, we need to count the number of times each RenderState
|
// First, we need to count the number of times each RenderState
|
||||||
// object is recorded in the cache.
|
// object is recorded in the cache.
|
||||||
@ -802,6 +805,7 @@ clear_cache() {
|
|||||||
if (_states == (States *)NULL) {
|
if (_states == (States *)NULL) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
ReMutexHolder holder(*_states_lock);
|
||||||
|
|
||||||
PStatTimer timer(_cache_update_pcollector);
|
PStatTimer timer(_cache_update_pcollector);
|
||||||
int orig_size = _states->size();
|
int orig_size = _states->size();
|
||||||
@ -878,6 +882,11 @@ clear_cache() {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void RenderState::
|
void RenderState::
|
||||||
list_cycles(ostream &out) {
|
list_cycles(ostream &out) {
|
||||||
|
if (_states == (States *)NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ReMutexHolder holder(*_states_lock);
|
||||||
|
|
||||||
typedef pset<const RenderState *> VisitedStates;
|
typedef pset<const RenderState *> VisitedStates;
|
||||||
VisitedStates visited;
|
VisitedStates visited;
|
||||||
CompositionCycleDesc cycle_desc;
|
CompositionCycleDesc cycle_desc;
|
||||||
@ -928,6 +937,12 @@ list_cycles(ostream &out) {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void RenderState::
|
void RenderState::
|
||||||
list_states(ostream &out) {
|
list_states(ostream &out) {
|
||||||
|
if (_states == (States *)NULL) {
|
||||||
|
out << "0 states:\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ReMutexHolder holder(*_states_lock);
|
||||||
|
|
||||||
out << _states->size() << " states:\n";
|
out << _states->size() << " states:\n";
|
||||||
States::const_iterator si;
|
States::const_iterator si;
|
||||||
for (si = _states->begin(); si != _states->end(); ++si) {
|
for (si = _states->begin(); si != _states->end(); ++si) {
|
||||||
@ -948,6 +963,11 @@ list_states(ostream &out) {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
bool RenderState::
|
bool RenderState::
|
||||||
validate_states() {
|
validate_states() {
|
||||||
|
if (_states == (States *)NULL) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReMutexHolder holder(*_states_lock);
|
||||||
if (_states->empty()) {
|
if (_states->empty()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -1021,7 +1041,7 @@ bin_removed(int bin_index) {
|
|||||||
// Do something here.
|
// Do something here.
|
||||||
nassertv(false);
|
nassertv(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: RenderState::return_new
|
// Function: RenderState::return_new
|
||||||
// Access: Private, Static
|
// Access: Private, Static
|
||||||
@ -1038,16 +1058,18 @@ CPT(RenderState) RenderState::
|
|||||||
return_new(RenderState *state) {
|
return_new(RenderState *state) {
|
||||||
nassertr(state != (RenderState *)NULL, state);
|
nassertr(state != (RenderState *)NULL, state);
|
||||||
|
|
||||||
// This should be a newly allocated pointer, not one that was used
|
|
||||||
// for anything else.
|
|
||||||
nassertr(state->_saved_entry == _states->end(), state);
|
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
if (paranoid_const) {
|
if (paranoid_const) {
|
||||||
nassertr(validate_states(), state);
|
nassertr(validate_states(), state);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
ReMutexHolder holder(*_states_lock);
|
||||||
|
|
||||||
|
// This should be a newly allocated pointer, not one that was used
|
||||||
|
// for anything else.
|
||||||
|
nassertr(state->_saved_entry == _states->end(), state);
|
||||||
|
|
||||||
// Save the state in a local PointerTo so that it will be freed at
|
// Save the state in a local PointerTo so that it will be freed at
|
||||||
// the end of this function if no one else uses it.
|
// the end of this function if no one else uses it.
|
||||||
CPT(RenderState) pt_state = state;
|
CPT(RenderState) pt_state = state;
|
||||||
@ -1273,12 +1295,13 @@ r_detect_cycles(const RenderState *start_state,
|
|||||||
// particular RenderState. The pointers to this
|
// particular RenderState. The pointers to this
|
||||||
// object may be scattered around in the various
|
// object may be scattered around in the various
|
||||||
// CompositionCaches from other RenderState objects.
|
// CompositionCaches from other RenderState objects.
|
||||||
|
//
|
||||||
|
// You must already be holding _states_lock before you
|
||||||
|
// call this method.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void RenderState::
|
void RenderState::
|
||||||
remove_cache_pointers() {
|
remove_cache_pointers() {
|
||||||
// Now make sure we clean up all other floating pointers to the
|
nassertv(_states_lock->debug_is_locked());
|
||||||
// RenderState. These may be scattered around in the various
|
|
||||||
// CompositionCaches from other RenderState objects.
|
|
||||||
|
|
||||||
// Fortunately, since we added CompositionCache records in pairs, we
|
// Fortunately, since we added CompositionCache records in pairs, we
|
||||||
// know exactly the set of RenderState objects that have us in their
|
// know exactly the set of RenderState objects that have us in their
|
||||||
@ -1633,6 +1656,29 @@ update_pstats(int old_referenced_bits, int new_referenced_bits) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: RenderState::init_states
|
||||||
|
// Access: Public, Static
|
||||||
|
// Description: Make sure the global _states map is allocated. This
|
||||||
|
// only has to be done once. We could make this map
|
||||||
|
// static, but then we run into problems if anyone
|
||||||
|
// creates a RenderState object at static init time;
|
||||||
|
// it also seems to cause problems when the Panda shared
|
||||||
|
// library is unloaded at application exit time.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
void RenderState::
|
||||||
|
init_states() {
|
||||||
|
_states = new States;
|
||||||
|
|
||||||
|
// TODO: we should have a global Panda mutex to allow us to safely
|
||||||
|
// create _states_lock without a startup race condition. For the
|
||||||
|
// meantime, this is OK because we guarantee that this method is
|
||||||
|
// called at static init time, presumably when there is still only
|
||||||
|
// one thread in the world.
|
||||||
|
_states_lock = new ReMutex;
|
||||||
|
nassertv(Thread::get_current_thread() == Thread::get_main_thread());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: RenderState::register_with_read_factory
|
// Function: RenderState::register_with_read_factory
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
#include "geomMunger.h"
|
#include "geomMunger.h"
|
||||||
#include "weakPointerTo.h"
|
#include "weakPointerTo.h"
|
||||||
#include "shaderExpansion.h"
|
#include "shaderExpansion.h"
|
||||||
|
#include "reMutex.h"
|
||||||
|
|
||||||
class GraphicsStateGuardianBase;
|
class GraphicsStateGuardianBase;
|
||||||
class FogAttrib;
|
class FogAttrib;
|
||||||
@ -195,7 +196,14 @@ private:
|
|||||||
INLINE void consider_update_pstats(int old_referenced_bits) const;
|
INLINE void consider_update_pstats(int old_referenced_bits) const;
|
||||||
static void update_pstats(int old_referenced_bits, int new_referenced_bits);
|
static void update_pstats(int old_referenced_bits, int new_referenced_bits);
|
||||||
|
|
||||||
|
public:
|
||||||
|
static void init_states();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
// This mutex protects _states. It also protects any modification
|
||||||
|
// to the cache, which is encoded in _composition_cache and
|
||||||
|
// _invert_composition_cache.
|
||||||
|
static ReMutex *_states_lock;
|
||||||
typedef pset<const RenderState *, indirect_less<const RenderState *> > States;
|
typedef pset<const RenderState *, indirect_less<const RenderState *> > States;
|
||||||
static States *_states;
|
static States *_states;
|
||||||
static CPT(RenderState) _empty_state;
|
static CPT(RenderState) _empty_state;
|
||||||
|
@ -25,7 +25,10 @@
|
|||||||
#include "compareTo.h"
|
#include "compareTo.h"
|
||||||
#include "pStatTimer.h"
|
#include "pStatTimer.h"
|
||||||
#include "config_pgraph.h"
|
#include "config_pgraph.h"
|
||||||
|
#include "reMutexHolder.h"
|
||||||
|
#include "thread.h"
|
||||||
|
|
||||||
|
ReMutex *TransformState::_states_lock = NULL;
|
||||||
TransformState::States *TransformState::_states = NULL;
|
TransformState::States *TransformState::_states = NULL;
|
||||||
CPT(TransformState) TransformState::_identity_state;
|
CPT(TransformState) TransformState::_identity_state;
|
||||||
UpdateSeq TransformState::_last_cycle_detect;
|
UpdateSeq TransformState::_last_cycle_detect;
|
||||||
@ -47,12 +50,7 @@ TypeHandle TransformState::_type_handle;
|
|||||||
TransformState::
|
TransformState::
|
||||||
TransformState() {
|
TransformState() {
|
||||||
if (_states == (States *)NULL) {
|
if (_states == (States *)NULL) {
|
||||||
// Make sure the global _states map is allocated. This only has
|
init_states();
|
||||||
// to be done once. We could make this map static, but then we
|
|
||||||
// run into problems if anyone creates a TransformState object at
|
|
||||||
// static init time; it also seems to cause problems when the
|
|
||||||
// Panda shared library is unloaded at application exit time.
|
|
||||||
_states = new States;
|
|
||||||
}
|
}
|
||||||
_saved_entry = _states->end();
|
_saved_entry = _states->end();
|
||||||
_flags = F_is_identity | F_singular_known | F_is_2d;
|
_flags = F_is_identity | F_singular_known | F_is_2d;
|
||||||
@ -97,12 +95,13 @@ TransformState::
|
|||||||
_inv_mat = (LMatrix4f *)NULL;
|
_inv_mat = (LMatrix4f *)NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ReMutexHolder holder(*_states_lock);
|
||||||
if (_saved_entry != _states->end()) {
|
if (_saved_entry != _states->end()) {
|
||||||
nassertv(_states->find(this) == _saved_entry);
|
nassertv(_states->find(this) == _saved_entry);
|
||||||
_states->erase(_saved_entry);
|
_states->erase(_saved_entry);
|
||||||
_saved_entry = _states->end();
|
_saved_entry = _states->end();
|
||||||
}
|
}
|
||||||
|
|
||||||
remove_cache_pointers();
|
remove_cache_pointers();
|
||||||
|
|
||||||
// If this was true at the beginning of the destructor, but is no
|
// If this was true at the beginning of the destructor, but is no
|
||||||
@ -631,6 +630,8 @@ compose(const TransformState *other) const {
|
|||||||
return other;
|
return other;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ReMutexHolder holder(*_states_lock);
|
||||||
|
|
||||||
// Is this composition already cached?
|
// Is this composition already cached?
|
||||||
CompositionCache::const_iterator ci = _composition_cache.find(other);
|
CompositionCache::const_iterator ci = _composition_cache.find(other);
|
||||||
if (ci != _composition_cache.end()) {
|
if (ci != _composition_cache.end()) {
|
||||||
@ -717,6 +718,8 @@ invert_compose(const TransformState *other) const {
|
|||||||
return make_identity();
|
return make_identity();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ReMutexHolder holder(*_states_lock);
|
||||||
|
|
||||||
// Is this composition already cached?
|
// Is this composition already cached?
|
||||||
CompositionCache::const_iterator ci = _invert_composition_cache.find(other);
|
CompositionCache::const_iterator ci = _invert_composition_cache.find(other);
|
||||||
if (ci != _invert_composition_cache.end()) {
|
if (ci != _invert_composition_cache.end()) {
|
||||||
@ -784,6 +787,8 @@ invert_compose(const TransformState *other) const {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
int TransformState::
|
int TransformState::
|
||||||
unref() const {
|
unref() const {
|
||||||
|
ReMutexHolder holder(*_states_lock);
|
||||||
|
|
||||||
if (get_cache_ref_count() > 0 &&
|
if (get_cache_ref_count() > 0 &&
|
||||||
get_ref_count() == get_cache_ref_count() + 1) {
|
get_ref_count() == get_cache_ref_count() + 1) {
|
||||||
// If we are about to remove the one reference that is not in the
|
// If we are about to remove the one reference that is not in the
|
||||||
@ -792,11 +797,6 @@ unref() const {
|
|||||||
// it exists.
|
// it exists.
|
||||||
|
|
||||||
if (auto_break_cycles) {
|
if (auto_break_cycles) {
|
||||||
// There might be a tiny race condition if multiple different
|
|
||||||
// threads perform cycle detects on related nodes at the same
|
|
||||||
// time. But the cost of failing the race condition is low--we
|
|
||||||
// end up with a tiny leak that may eventually be discovered, big
|
|
||||||
// deal.
|
|
||||||
++_last_cycle_detect;
|
++_last_cycle_detect;
|
||||||
if (r_detect_cycles(this, this, 1, _last_cycle_detect, NULL)) {
|
if (r_detect_cycles(this, this, 1, _last_cycle_detect, NULL)) {
|
||||||
// Ok, we have a cycle. This will be a leak unless we break the
|
// Ok, we have a cycle. This will be a leak unless we break the
|
||||||
@ -805,6 +805,7 @@ unref() const {
|
|||||||
pgraph_cat.debug()
|
pgraph_cat.debug()
|
||||||
<< "Breaking cycle involving " << (*this) << "\n";
|
<< "Breaking cycle involving " << (*this) << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
((TransformState *)this)->remove_cache_pointers();
|
((TransformState *)this)->remove_cache_pointers();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -928,6 +929,7 @@ get_num_states() {
|
|||||||
if (_states == (States *)NULL) {
|
if (_states == (States *)NULL) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
ReMutexHolder holder(*_states_lock);
|
||||||
return _states->size();
|
return _states->size();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -954,6 +956,7 @@ get_num_unused_states() {
|
|||||||
if (_states == (States *)NULL) {
|
if (_states == (States *)NULL) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
ReMutexHolder holder(*_states_lock);
|
||||||
|
|
||||||
// First, we need to count the number of times each TransformState
|
// First, we need to count the number of times each TransformState
|
||||||
// object is recorded in the cache. We could just trust
|
// object is recorded in the cache. We could just trust
|
||||||
@ -1047,6 +1050,7 @@ clear_cache() {
|
|||||||
if (_states == (States *)NULL) {
|
if (_states == (States *)NULL) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
ReMutexHolder holder(*_states_lock);
|
||||||
|
|
||||||
PStatTimer timer(_cache_update_pcollector);
|
PStatTimer timer(_cache_update_pcollector);
|
||||||
int orig_size = _states->size();
|
int orig_size = _states->size();
|
||||||
@ -1123,6 +1127,11 @@ clear_cache() {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void TransformState::
|
void TransformState::
|
||||||
list_cycles(ostream &out) {
|
list_cycles(ostream &out) {
|
||||||
|
if (_states == (States *)NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ReMutexHolder holder(*_states_lock);
|
||||||
|
|
||||||
typedef pset<const TransformState *> VisitedStates;
|
typedef pset<const TransformState *> VisitedStates;
|
||||||
VisitedStates visited;
|
VisitedStates visited;
|
||||||
CompositionCycleDesc cycle_desc;
|
CompositionCycleDesc cycle_desc;
|
||||||
@ -1173,6 +1182,12 @@ list_cycles(ostream &out) {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void TransformState::
|
void TransformState::
|
||||||
list_states(ostream &out) {
|
list_states(ostream &out) {
|
||||||
|
if (_states == (States *)NULL) {
|
||||||
|
out << "0 states:\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ReMutexHolder holder(*_states_lock);
|
||||||
|
|
||||||
out << _states->size() << " states:\n";
|
out << _states->size() << " states:\n";
|
||||||
States::const_iterator si;
|
States::const_iterator si;
|
||||||
for (si = _states->begin(); si != _states->end(); ++si) {
|
for (si = _states->begin(); si != _states->end(); ++si) {
|
||||||
@ -1193,6 +1208,11 @@ list_states(ostream &out) {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
bool TransformState::
|
bool TransformState::
|
||||||
validate_states() {
|
validate_states() {
|
||||||
|
if (_states == (States *)NULL) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReMutexHolder holder(*_states_lock);
|
||||||
if (_states->empty()) {
|
if (_states->empty()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -1217,6 +1237,29 @@ validate_states() {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: TransformState::init_states
|
||||||
|
// Access: Public, Static
|
||||||
|
// Description: Make sure the global _states map is allocated. This
|
||||||
|
// only has to be done once. We could make this map
|
||||||
|
// static, but then we run into problems if anyone
|
||||||
|
// creates a TransformState object at static init time;
|
||||||
|
// it also seems to cause problems when the Panda shared
|
||||||
|
// library is unloaded at application exit time.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
void TransformState::
|
||||||
|
init_states() {
|
||||||
|
_states = new States;
|
||||||
|
|
||||||
|
// TODO: we should have a global Panda mutex to allow us to safely
|
||||||
|
// create _states_lock without a startup race condition. For the
|
||||||
|
// meantime, this is OK because we guarantee that this method is
|
||||||
|
// called at static init time, presumably when there is still only
|
||||||
|
// one thread in the world.
|
||||||
|
_states_lock = new ReMutex;
|
||||||
|
nassertv(Thread::get_current_thread() == Thread::get_main_thread());
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: TransformState::return_new
|
// Function: TransformState::return_new
|
||||||
// Access: Private, Static
|
// Access: Private, Static
|
||||||
@ -1233,16 +1276,18 @@ CPT(TransformState) TransformState::
|
|||||||
return_new(TransformState *state) {
|
return_new(TransformState *state) {
|
||||||
nassertr(state != (TransformState *)NULL, state);
|
nassertr(state != (TransformState *)NULL, state);
|
||||||
|
|
||||||
// This should be a newly allocated pointer, not one that was used
|
|
||||||
// for anything else.
|
|
||||||
nassertr(state->_saved_entry == _states->end(), state);
|
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
if (paranoid_const) {
|
if (paranoid_const) {
|
||||||
nassertr(validate_states(), state);
|
nassertr(validate_states(), state);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
ReMutexHolder holder(*_states_lock);
|
||||||
|
|
||||||
|
// This should be a newly allocated pointer, not one that was used
|
||||||
|
// for anything else.
|
||||||
|
nassertr(state->_saved_entry == _states->end(), state);
|
||||||
|
|
||||||
// Save the state in a local PointerTo so that it will be freed at
|
// Save the state in a local PointerTo so that it will be freed at
|
||||||
// the end of this function if no one else uses it.
|
// the end of this function if no one else uses it.
|
||||||
CPT(TransformState) pt_state = state;
|
CPT(TransformState) pt_state = state;
|
||||||
@ -1544,9 +1589,14 @@ r_detect_cycles(const TransformState *start_state,
|
|||||||
// particular TransformState. The pointers to this
|
// particular TransformState. The pointers to this
|
||||||
// object may be scattered around in the various
|
// object may be scattered around in the various
|
||||||
// CompositionCaches from other TransformState objects.
|
// CompositionCaches from other TransformState objects.
|
||||||
|
//
|
||||||
|
// You must already be holding _states_lock before you
|
||||||
|
// call this method.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void TransformState::
|
void TransformState::
|
||||||
remove_cache_pointers() {
|
remove_cache_pointers() {
|
||||||
|
nassertv(_states_lock->debug_is_locked());
|
||||||
|
|
||||||
// Fortunately, since we added CompositionCache records in pairs, we
|
// Fortunately, since we added CompositionCache records in pairs, we
|
||||||
// know exactly the set of TransformState objects that have us in their
|
// know exactly the set of TransformState objects that have us in their
|
||||||
// cache: it's the same set of TransformState objects that we have in
|
// cache: it's the same set of TransformState objects that we have in
|
||||||
|
@ -29,6 +29,7 @@
|
|||||||
#include "updateSeq.h"
|
#include "updateSeq.h"
|
||||||
#include "pStatCollector.h"
|
#include "pStatCollector.h"
|
||||||
#include "geomEnums.h"
|
#include "geomEnums.h"
|
||||||
|
#include "reMutex.h"
|
||||||
|
|
||||||
class GraphicsStateGuardianBase;
|
class GraphicsStateGuardianBase;
|
||||||
class FactoryParams;
|
class FactoryParams;
|
||||||
@ -182,6 +183,9 @@ PUBLISHED:
|
|||||||
static void list_states(ostream &out);
|
static void list_states(ostream &out);
|
||||||
static bool validate_states();
|
static bool validate_states();
|
||||||
|
|
||||||
|
public:
|
||||||
|
static void init_states();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class CompositionCycleDescEntry {
|
class CompositionCycleDescEntry {
|
||||||
public:
|
public:
|
||||||
@ -206,6 +210,10 @@ private:
|
|||||||
void remove_cache_pointers();
|
void remove_cache_pointers();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
// This mutex protects _states. It also protects any modification
|
||||||
|
// to the cache, which is encoded in _composition_cache and
|
||||||
|
// _invert_composition_cache.
|
||||||
|
static ReMutex *_states_lock;
|
||||||
typedef phash_set<const TransformState *, indirect_less_hash<const TransformState *> > States;
|
typedef phash_set<const TransformState *, indirect_less_hash<const TransformState *> > States;
|
||||||
static States *_states;
|
static States *_states;
|
||||||
static CPT(TransformState) _identity_state;
|
static CPT(TransformState) _identity_state;
|
||||||
|
@ -79,6 +79,7 @@ get_max_rate() const {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
INLINE int PStatClient::
|
INLINE int PStatClient::
|
||||||
get_num_collectors() const {
|
get_num_collectors() const {
|
||||||
|
ReMutexHolder holder(_lock);
|
||||||
return _collectors.size();
|
return _collectors.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -89,6 +90,7 @@ get_num_collectors() const {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
INLINE PStatCollectorDef *PStatClient::
|
INLINE PStatCollectorDef *PStatClient::
|
||||||
get_collector_def(int index) const {
|
get_collector_def(int index) const {
|
||||||
|
ReMutexHolder holder(_lock);
|
||||||
nassertr(index >= 0 && index < (int)_collectors.size(), NULL);
|
nassertr(index >= 0 && index < (int)_collectors.size(), NULL);
|
||||||
|
|
||||||
return _collectors[index].get_def(this, index);
|
return _collectors[index].get_def(this, index);
|
||||||
@ -102,6 +104,7 @@ get_collector_def(int index) const {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
INLINE int PStatClient::
|
INLINE int PStatClient::
|
||||||
get_num_threads() const {
|
get_num_threads() const {
|
||||||
|
ReMutexHolder holder(_lock);
|
||||||
return _threads.size();
|
return _threads.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -112,6 +115,7 @@ get_num_threads() const {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
INLINE string PStatClient::
|
INLINE string PStatClient::
|
||||||
get_thread_name(int index) const {
|
get_thread_name(int index) const {
|
||||||
|
ReMutexHolder holder(_lock);
|
||||||
nassertr(index >= 0 && index < (int)_threads.size(), string());
|
nassertr(index >= 0 && index < (int)_threads.size(), string());
|
||||||
return _threads[index]._name;
|
return _threads[index]._name;
|
||||||
}
|
}
|
||||||
@ -183,6 +187,7 @@ resume_after_pause() {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
INLINE bool PStatClient::
|
INLINE bool PStatClient::
|
||||||
client_connect(string hostname, int port) {
|
client_connect(string hostname, int port) {
|
||||||
|
ReMutexHolder holder(_lock);
|
||||||
client_disconnect();
|
client_disconnect();
|
||||||
return get_impl()->client_connect(hostname, port);
|
return get_impl()->client_connect(hostname, port);
|
||||||
}
|
}
|
||||||
@ -194,6 +199,7 @@ client_connect(string hostname, int port) {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
INLINE bool PStatClient::
|
INLINE bool PStatClient::
|
||||||
client_is_connected() const {
|
client_is_connected() const {
|
||||||
|
ReMutexHolder holder(_lock);
|
||||||
return has_impl() && _impl->client_is_connected();
|
return has_impl() && _impl->client_is_connected();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -232,6 +238,7 @@ has_impl() const {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
INLINE PStatClientImpl *PStatClient::
|
INLINE PStatClientImpl *PStatClient::
|
||||||
get_impl() {
|
get_impl() {
|
||||||
|
ReMutexHolder holder(_lock);
|
||||||
if (_impl == (PStatClientImpl *)NULL) {
|
if (_impl == (PStatClientImpl *)NULL) {
|
||||||
_impl = new PStatClientImpl(this);
|
_impl = new PStatClientImpl(this);
|
||||||
}
|
}
|
||||||
|
@ -93,6 +93,7 @@ PStatClient::
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
PStatCollector PStatClient::
|
PStatCollector PStatClient::
|
||||||
get_collector(int index) const {
|
get_collector(int index) const {
|
||||||
|
ReMutexHolder holder(_lock);
|
||||||
nassertr(index >= 0 && index < (int)_collectors.size(), PStatCollector());
|
nassertr(index >= 0 && index < (int)_collectors.size(), PStatCollector());
|
||||||
return PStatCollector((PStatClient *)this, index);
|
return PStatCollector((PStatClient *)this, index);
|
||||||
}
|
}
|
||||||
@ -104,6 +105,7 @@ get_collector(int index) const {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
string PStatClient::
|
string PStatClient::
|
||||||
get_collector_name(int index) const {
|
get_collector_name(int index) const {
|
||||||
|
ReMutexHolder holder(_lock);
|
||||||
nassertr(index >= 0 && index < (int)_collectors.size(), string());
|
nassertr(index >= 0 && index < (int)_collectors.size(), string());
|
||||||
|
|
||||||
return _collectors[index].get_name();
|
return _collectors[index].get_name();
|
||||||
@ -119,6 +121,7 @@ get_collector_name(int index) const {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
string PStatClient::
|
string PStatClient::
|
||||||
get_collector_fullname(int index) const {
|
get_collector_fullname(int index) const {
|
||||||
|
ReMutexHolder holder(_lock);
|
||||||
nassertr(index >= 0 && index < (int)_collectors.size(), string());
|
nassertr(index >= 0 && index < (int)_collectors.size(), string());
|
||||||
|
|
||||||
int parent_index = _collectors[index].get_parent_index();
|
int parent_index = _collectors[index].get_parent_index();
|
||||||
@ -137,6 +140,7 @@ get_collector_fullname(int index) const {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
PStatThread PStatClient::
|
PStatThread PStatClient::
|
||||||
get_thread(int index) const {
|
get_thread(int index) const {
|
||||||
|
ReMutexHolder holder(_lock);
|
||||||
nassertr(index >= 0 && index < (int)_threads.size(), PStatThread());
|
nassertr(index >= 0 && index < (int)_threads.size(), PStatThread());
|
||||||
return PStatThread((PStatClient *)this, index);
|
return PStatThread((PStatClient *)this, index);
|
||||||
}
|
}
|
||||||
@ -189,6 +193,7 @@ main_tick() {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void PStatClient::
|
void PStatClient::
|
||||||
client_main_tick() {
|
client_main_tick() {
|
||||||
|
ReMutexHolder holder(_lock);
|
||||||
if (has_impl()) {
|
if (has_impl()) {
|
||||||
_impl->client_main_tick();
|
_impl->client_main_tick();
|
||||||
}
|
}
|
||||||
@ -202,6 +207,7 @@ client_main_tick() {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void PStatClient::
|
void PStatClient::
|
||||||
client_disconnect() {
|
client_disconnect() {
|
||||||
|
ReMutexHolder holder(_lock);
|
||||||
if (has_impl()) {
|
if (has_impl()) {
|
||||||
_impl->client_disconnect();
|
_impl->client_disconnect();
|
||||||
}
|
}
|
||||||
@ -254,6 +260,8 @@ get_global_pstats() {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
PStatCollector PStatClient::
|
PStatCollector PStatClient::
|
||||||
make_collector_with_relname(int parent_index, string relname) {
|
make_collector_with_relname(int parent_index, string relname) {
|
||||||
|
ReMutexHolder holder(_lock);
|
||||||
|
|
||||||
if (relname.empty()) {
|
if (relname.empty()) {
|
||||||
relname = "Unnamed";
|
relname = "Unnamed";
|
||||||
}
|
}
|
||||||
@ -292,6 +300,8 @@ make_collector_with_relname(int parent_index, string relname) {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
PStatCollector PStatClient::
|
PStatCollector PStatClient::
|
||||||
make_collector_with_name(int parent_index, const string &name) {
|
make_collector_with_name(int parent_index, const string &name) {
|
||||||
|
ReMutexHolder holder(_lock);
|
||||||
|
|
||||||
nassertr(parent_index >= 0 && parent_index < (int)_collectors.size(),
|
nassertr(parent_index >= 0 && parent_index < (int)_collectors.size(),
|
||||||
PStatCollector());
|
PStatCollector());
|
||||||
|
|
||||||
@ -343,6 +353,8 @@ make_collector_with_name(int parent_index, const string &name) {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
PStatThread PStatClient::
|
PStatThread PStatClient::
|
||||||
make_thread(const string &name) {
|
make_thread(const string &name) {
|
||||||
|
ReMutexHolder holder(_lock);
|
||||||
|
|
||||||
ThingsByName::const_iterator ni =
|
ThingsByName::const_iterator ni =
|
||||||
_threads_by_name.find(name);
|
_threads_by_name.find(name);
|
||||||
|
|
||||||
@ -388,6 +400,8 @@ make_thread(const string &name) {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
bool PStatClient::
|
bool PStatClient::
|
||||||
is_active(int collector_index, int thread_index) const {
|
is_active(int collector_index, int thread_index) const {
|
||||||
|
ReMutexHolder holder(_lock);
|
||||||
|
|
||||||
nassertr(collector_index >= 0 && collector_index < (int)_collectors.size(), false);
|
nassertr(collector_index >= 0 && collector_index < (int)_collectors.size(), false);
|
||||||
nassertr(thread_index >= 0 && thread_index < (int)_threads.size(), false);
|
nassertr(thread_index >= 0 && thread_index < (int)_threads.size(), false);
|
||||||
|
|
||||||
@ -407,6 +421,8 @@ is_active(int collector_index, int thread_index) const {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
bool PStatClient::
|
bool PStatClient::
|
||||||
is_started(int collector_index, int thread_index) const {
|
is_started(int collector_index, int thread_index) const {
|
||||||
|
ReMutexHolder holder(_lock);
|
||||||
|
|
||||||
nassertr(collector_index >= 0 && collector_index < (int)_collectors.size(), false);
|
nassertr(collector_index >= 0 && collector_index < (int)_collectors.size(), false);
|
||||||
nassertr(thread_index >= 0 && thread_index < (int)_threads.size(), false);
|
nassertr(thread_index >= 0 && thread_index < (int)_threads.size(), false);
|
||||||
|
|
||||||
@ -424,6 +440,8 @@ is_started(int collector_index, int thread_index) const {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void PStatClient::
|
void PStatClient::
|
||||||
start(int collector_index, int thread_index) {
|
start(int collector_index, int thread_index) {
|
||||||
|
ReMutexHolder holder(_lock);
|
||||||
|
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
nassertv(collector_index >= 0 && collector_index < (int)_collectors.size());
|
nassertv(collector_index >= 0 && collector_index < (int)_collectors.size());
|
||||||
nassertv(thread_index >= 0 && thread_index < (int)_threads.size());
|
nassertv(thread_index >= 0 && thread_index < (int)_threads.size());
|
||||||
@ -451,6 +469,8 @@ start(int collector_index, int thread_index) {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void PStatClient::
|
void PStatClient::
|
||||||
start(int collector_index, int thread_index, float as_of) {
|
start(int collector_index, int thread_index, float as_of) {
|
||||||
|
ReMutexHolder holder(_lock);
|
||||||
|
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
nassertv(collector_index >= 0 && collector_index < (int)_collectors.size());
|
nassertv(collector_index >= 0 && collector_index < (int)_collectors.size());
|
||||||
nassertv(thread_index >= 0 && thread_index < (int)_threads.size());
|
nassertv(thread_index >= 0 && thread_index < (int)_threads.size());
|
||||||
@ -477,6 +497,8 @@ start(int collector_index, int thread_index, float as_of) {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void PStatClient::
|
void PStatClient::
|
||||||
stop(int collector_index, int thread_index) {
|
stop(int collector_index, int thread_index) {
|
||||||
|
ReMutexHolder holder(_lock);
|
||||||
|
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
nassertv(collector_index >= 0 && collector_index < (int)_collectors.size());
|
nassertv(collector_index >= 0 && collector_index < (int)_collectors.size());
|
||||||
nassertv(thread_index >= 0 && thread_index < (int)_threads.size());
|
nassertv(thread_index >= 0 && thread_index < (int)_threads.size());
|
||||||
@ -513,6 +535,8 @@ stop(int collector_index, int thread_index) {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void PStatClient::
|
void PStatClient::
|
||||||
stop(int collector_index, int thread_index, float as_of) {
|
stop(int collector_index, int thread_index, float as_of) {
|
||||||
|
ReMutexHolder holder(_lock);
|
||||||
|
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
nassertv(collector_index >= 0 && collector_index < (int)_collectors.size());
|
nassertv(collector_index >= 0 && collector_index < (int)_collectors.size());
|
||||||
nassertv(thread_index >= 0 && thread_index < (int)_threads.size());
|
nassertv(thread_index >= 0 && thread_index < (int)_threads.size());
|
||||||
@ -551,6 +575,8 @@ stop(int collector_index, int thread_index, float as_of) {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void PStatClient::
|
void PStatClient::
|
||||||
clear_level(int collector_index, int thread_index) {
|
clear_level(int collector_index, int thread_index) {
|
||||||
|
ReMutexHolder holder(_lock);
|
||||||
|
|
||||||
_collectors[collector_index]._per_thread[thread_index]._has_level = false;
|
_collectors[collector_index]._per_thread[thread_index]._has_level = false;
|
||||||
_collectors[collector_index]._per_thread[thread_index]._level = 0.0;
|
_collectors[collector_index]._per_thread[thread_index]._level = 0.0;
|
||||||
}
|
}
|
||||||
@ -566,6 +592,8 @@ clear_level(int collector_index, int thread_index) {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void PStatClient::
|
void PStatClient::
|
||||||
set_level(int collector_index, int thread_index, float level) {
|
set_level(int collector_index, int thread_index, float level) {
|
||||||
|
ReMutexHolder holder(_lock);
|
||||||
|
|
||||||
// We don't want to condition this on whether the client is already
|
// We don't want to condition this on whether the client is already
|
||||||
// connected or the collector is already active, since we might
|
// connected or the collector is already active, since we might
|
||||||
// connect the client later, and we will want to have an accurate
|
// connect the client later, and we will want to have an accurate
|
||||||
@ -588,6 +616,8 @@ set_level(int collector_index, int thread_index, float level) {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void PStatClient::
|
void PStatClient::
|
||||||
add_level(int collector_index, int thread_index, float increment) {
|
add_level(int collector_index, int thread_index, float increment) {
|
||||||
|
ReMutexHolder holder(_lock);
|
||||||
|
|
||||||
increment *= get_collector_def(collector_index)->_factor;
|
increment *= get_collector_def(collector_index)->_factor;
|
||||||
_collectors[collector_index]._per_thread[thread_index]._has_level = true;
|
_collectors[collector_index]._per_thread[thread_index]._has_level = true;
|
||||||
_collectors[collector_index]._per_thread[thread_index]._level += increment;
|
_collectors[collector_index]._per_thread[thread_index]._level += increment;
|
||||||
@ -603,6 +633,8 @@ add_level(int collector_index, int thread_index, float increment) {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
float PStatClient::
|
float PStatClient::
|
||||||
get_level(int collector_index, int thread_index) const {
|
get_level(int collector_index, int thread_index) const {
|
||||||
|
ReMutexHolder holder(_lock);
|
||||||
|
|
||||||
return _collectors[collector_index]._per_thread[thread_index]._level /
|
return _collectors[collector_index]._per_thread[thread_index]._level /
|
||||||
get_collector_def(collector_index)->_factor;
|
get_collector_def(collector_index)->_factor;
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,8 @@
|
|||||||
#include "pStatFrameData.h"
|
#include "pStatFrameData.h"
|
||||||
#include "pStatClientImpl.h"
|
#include "pStatClientImpl.h"
|
||||||
#include "pStatCollectorDef.h"
|
#include "pStatCollectorDef.h"
|
||||||
|
#include "reMutex.h"
|
||||||
|
#include "reMutexHolder.h"
|
||||||
#include "luse.h"
|
#include "luse.h"
|
||||||
#include "pmap.h"
|
#include "pmap.h"
|
||||||
|
|
||||||
@ -113,6 +115,10 @@ private:
|
|||||||
void add_level(int collector_index, int thread_index, float increment);
|
void add_level(int collector_index, int thread_index, float increment);
|
||||||
float get_level(int collector_index, int thread_index) const;
|
float get_level(int collector_index, int thread_index) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
// This mutex protects everything in this class.
|
||||||
|
ReMutex _lock;
|
||||||
|
|
||||||
// Not a phash_map, so the threads remain sorted by name.
|
// Not a phash_map, so the threads remain sorted by name.
|
||||||
typedef pmap<string, int> ThingsByName;
|
typedef pmap<string, int> ThingsByName;
|
||||||
ThingsByName _threads_by_name;
|
ThingsByName _threads_by_name;
|
||||||
|
@ -997,22 +997,24 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
|
|||||||
set_cursor_out_of_window();
|
set_cursor_out_of_window();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WM_CREATE: {
|
case WM_CREATE:
|
||||||
track_mouse_leaving(hwnd);
|
{
|
||||||
ClearToBlack(hwnd,_properties);
|
track_mouse_leaving(hwnd);
|
||||||
|
ClearToBlack(hwnd, _properties);
|
||||||
POINT cpos;
|
|
||||||
GetCursorPos(&cpos);
|
POINT cpos;
|
||||||
ScreenToClient(hwnd,&cpos);
|
GetCursorPos(&cpos);
|
||||||
RECT clientRect;
|
ScreenToClient(hwnd, &cpos);
|
||||||
GetClientRect(hwnd, &clientRect);
|
RECT clientRect;
|
||||||
if(PtInRect(&clientRect,cpos))
|
GetClientRect(hwnd, &clientRect);
|
||||||
set_cursor_in_window(); // should window focus be true as well?
|
if (PtInRect(&clientRect,cpos)) {
|
||||||
else set_cursor_out_of_window();
|
set_cursor_in_window(); // should window focus be true as well?
|
||||||
|
} else {
|
||||||
|
set_cursor_out_of_window();
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
case WM_CLOSE:
|
case WM_CLOSE:
|
||||||
// This is a message from the system indicating that the user
|
// This is a message from the system indicating that the user
|
||||||
// has requested to close the window (e.g. alt-f4).
|
// has requested to close the window (e.g. alt-f4).
|
||||||
|
Loading…
x
Reference in New Issue
Block a user