name mutexes for debugging; better UpdateSeq thread behavior

This commit is contained in:
David Rose 2006-04-09 23:23:15 +00:00
parent b4f84135d6
commit 889228f403
33 changed files with 253 additions and 121 deletions

View File

@ -45,7 +45,7 @@ TypeHandle CollisionSolid::_type_handle;
// Description:
////////////////////////////////////////////////////////////////////
CollisionSolid::
CollisionSolid() {
CollisionSolid() : _lock("CollisionSolid") {
_flags = F_viz_geom_stale | F_tangible | F_internal_bounds_stale;
}
@ -58,7 +58,8 @@ CollisionSolid::
CollisionSolid(const CollisionSolid &copy) :
_effective_normal(copy._effective_normal),
_internal_bounds(copy._internal_bounds),
_flags(copy._flags)
_flags(copy._flags),
_lock("CollisionSolid")
{
_flags |= F_viz_geom_stale;
}

View File

@ -100,7 +100,9 @@ PStatCollector GraphicsEngine::_test_geom_pcollector("Collision Tests:CollisionG
////////////////////////////////////////////////////////////////////
GraphicsEngine::
GraphicsEngine(Pipeline *pipeline) :
_pipeline(pipeline)
_pipeline(pipeline),
_app("app"),
_lock("GraphicsEngine")
{
if (_pipeline == (Pipeline *)NULL) {
_pipeline = Pipeline::get_render_pipeline();
@ -1727,6 +1729,17 @@ get_window_renderer(const string &name, int pipeline_stage) {
return thread.p();
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsEngine::WindowRenderer::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
GraphicsEngine::WindowRenderer::
WindowRenderer(const string &name) :
_wl_lock(string("GraphicsEngine::WindowRenderer ") + name)
{
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsEngine::WindowRenderer::add_gsg
// Access: Public
@ -2026,7 +2039,9 @@ do_callbacks(GraphicsEngine::CallbackTime callback_time) {
GraphicsEngine::RenderThread::
RenderThread(const string &name, GraphicsEngine *engine) :
Thread(name, "Main"),
WindowRenderer(name),
_engine(engine),
_cv_mutex(string("GraphicsEngine::RenderThread ") + name),
_cv_start(_cv_mutex),
_cv_done(_cv_mutex)
{

View File

@ -269,6 +269,8 @@ private:
class WindowRenderer {
public:
WindowRenderer(const string &name);
void add_gsg(GraphicsStateGuardian *gsg);
void add_window(Windows &wlist, GraphicsOutput *window);
void remove_window(GraphicsOutput *window);

View File

@ -74,7 +74,9 @@ GraphicsOutput(GraphicsPipe *pipe,
const FrameBufferProperties &properties,
int x_size, int y_size, int flags,
GraphicsStateGuardian *gsg,
GraphicsOutput *host) {
GraphicsOutput *host) :
_lock("GraphicsOutput")
{
#ifdef DO_MEMORY_USAGE
MemoryUsage::update_type(this, this);
#endif

View File

@ -66,7 +66,9 @@ const int GraphicsPipe::strip_properties[] = {
// Description:
////////////////////////////////////////////////////////////////////
GraphicsPipe::
GraphicsPipe() {
GraphicsPipe() :
_lock("GraphicsPipe")
{
// Initially, we assume the GraphicsPipe is valid. A derived class
// should set this to false if it determines otherwise.
_is_valid = true;

View File

@ -34,7 +34,7 @@ GraphicsPipeSelection *GraphicsPipeSelection::_global_ptr = NULL;
// Description:
////////////////////////////////////////////////////////////////////
GraphicsPipeSelection::
GraphicsPipeSelection() {
GraphicsPipeSelection() : _lock("GraphicsPipeSelection") {
// We declare these variables here instead of in config_display, in
// case this constructor is running at static init time.
ConfigVariableString load_display

View File

@ -42,7 +42,8 @@ GraphicsWindow(GraphicsPipe *pipe,
int x_size, int y_size, int flags,
GraphicsStateGuardian *gsg,
GraphicsOutput *host) :
GraphicsOutput(pipe, name, properties, x_size, y_size, flags, gsg, host)
GraphicsOutput(pipe, name, properties, x_size, y_size, flags, gsg, host),
_input_lock("GraphicsWindow::_input_lock")
{
#ifdef DO_MEMORY_USAGE
MemoryUsage::update_type(this, this);

View File

@ -79,7 +79,7 @@ Lru::Lru (int maximum_memory, int maximum_pages, int maximum_page_types)
}
#if ENABLE_MUTEX
this -> _m.mutex = new Mutex ( );
this -> _m.mutex = new Mutex ("lru");
#endif
}

View File

@ -29,7 +29,7 @@ EventQueue *EventQueue::_global_event_queue = NULL;
// Description:
////////////////////////////////////////////////////////////////////
EventQueue::
EventQueue() {
EventQueue() : _lock("EventQueue") {
}
////////////////////////////////////////////////////////////////////

View File

@ -301,7 +301,7 @@ has_weak_list() const {
INLINE WeakReferenceList *ReferenceCount::
get_weak_list() const {
if (_weak_list == (WeakReferenceList *)NULL) {
((ReferenceCount *)this)->_weak_list = new WeakReferenceList;
((ReferenceCount *)this)->create_weak_list();
}
return _weak_list;
}

View File

@ -16,8 +16,9 @@
//
////////////////////////////////////////////////////////////////////
#include "referenceCount.h"
#include "atomicAdjust.h"
#include "mutexImpl.h"
TypeHandle ReferenceCount::_type_handle;
@ -48,3 +49,30 @@ do_test_ref_count_integrity() const {
return true;
}
////////////////////////////////////////////////////////////////////
// Function: ReferenceCount::create_weak_list
// Access: Private
// Description: Allocates a new WeakReferenceList structure and
// stores it on the object.
////////////////////////////////////////////////////////////////////
void ReferenceCount::
create_weak_list() {
#ifdef HAVE_ATOMIC_COMPARE_AND_EXCHANGE_PTR
WeakReferenceList *weak_list = new WeakReferenceList;
void *orig =
AtomicAdjust::compare_and_exchange_ptr((void *&)_weak_list, NULL, weak_list);
if (orig != (void *)NULL) {
// Someone else created it first.
delete weak_list;
}
#else
static MutexImpl lock("ReferenceCount::create_weak_list");
lock.lock();
if (_weak_list != (WeakReferenceList *)NULL) {
_weak_list = new WeakReferenceList;
}
lock.release();
#endif // HAVE_ATOMIC_COMPARE_AND_EXCHANGE_PTR
}

View File

@ -66,6 +66,9 @@ public:
protected:
bool do_test_ref_count_integrity() const;
private:
void create_weak_list();
private:
enum {
// We use this value as a flag to indicate an object has been

View File

@ -37,10 +37,12 @@ WeakReferenceList() {
////////////////////////////////////////////////////////////////////
WeakReferenceList::
~WeakReferenceList() {
_lock.lock();
Pointers::iterator pi;
for (pi = _pointers.begin(); pi != _pointers.end(); ++pi) {
(*pi)->mark_deleted();
}
_lock.release();
}
////////////////////////////////////////////////////////////////////
@ -58,7 +60,9 @@ WeakReferenceList::
////////////////////////////////////////////////////////////////////
void WeakReferenceList::
add_reference(WeakPointerToVoid *ptv) {
_lock.lock();
bool inserted = _pointers.insert(ptv).second;
_lock.release();
nassertv(inserted);
}
@ -73,7 +77,12 @@ add_reference(WeakPointerToVoid *ptv) {
////////////////////////////////////////////////////////////////////
void WeakReferenceList::
clear_reference(WeakPointerToVoid *ptv) {
_lock.lock();
Pointers::iterator pi = _pointers.find(ptv);
nassertv_always(pi != _pointers.end());
_pointers.erase(pi);
bool valid = (pi != _pointers.end());
if (valid) {
_pointers.erase(pi);
}
_lock.release();
nassertv(valid);
}

View File

@ -21,6 +21,7 @@
#include "pandabase.h"
#include "pset.h"
#include "mutexImpl.h"
class WeakPointerToVoid;
@ -45,6 +46,7 @@ public:
private:
typedef pset<WeakPointerToVoid *> Pointers;
Pointers _pointers;
MutexImpl _lock;
};
#include "weakReferenceList.I"

View File

@ -35,7 +35,8 @@ PStatCollector GeomCacheManager::_geom_cache_evict_pcollector("Geom cache operat
////////////////////////////////////////////////////////////////////
GeomCacheManager::
GeomCacheManager() :
_total_size(0)
_total_size(0),
_lock("GeomCacheManager")
{
// We deliberately hang on to this pointer forever.
_list = new GeomCacheEntry;

View File

@ -22,7 +22,7 @@
// We start the key counters off at 1, since 0 is reserved for an
// empty NodePath (and also for an unassigned key).
int NodePathComponent::_next_key = 1;
Mutex NodePathComponent::_key_lock;
Mutex NodePathComponent::_key_lock("NodePathComponent::_key_lock");
TypeHandle NodePathComponent::_type_handle;

View File

@ -67,7 +67,8 @@ TypeHandle PandaNode::_type_handle;
////////////////////////////////////////////////////////////////////
PandaNode::
PandaNode(const string &name) :
Namable(name)
Namable(name),
_paths_lock("PandaNode::_paths_lock")
{
if (pgraph_cat.is_debug()) {
pgraph_cat.debug()
@ -113,7 +114,8 @@ PandaNode::
PandaNode(const PandaNode &copy) :
ReferenceCount(copy),
TypedWritable(copy),
Namable(copy)
Namable(copy),
_paths_lock("PandaNode::_paths_lock")
{
if (pgraph_cat.is_debug()) {
pgraph_cat.debug()

View File

@ -1696,7 +1696,7 @@ init_states() {
// 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;
_states_lock = new ReMutex("RenderState");
nassertv(Thread::get_current_thread() == Thread::get_main_thread());
}

View File

@ -1274,7 +1274,7 @@ init_states() {
// 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;
_states_lock = new ReMutex("TransformState");
nassertv(Thread::get_current_thread() == Thread::get_main_thread());
}

View File

@ -17,20 +17,6 @@
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: MutexDebug::Constructor
// Access: Protected
// Description:
////////////////////////////////////////////////////////////////////
INLINE MutexDebug::
MutexDebug(bool allow_recursion) :
_allow_recursion(allow_recursion),
_locking_thread(NULL),
_lock_count(0),
_cvar(_global_mutex)
{
}
////////////////////////////////////////////////////////////////////
// Function: MutexDebug::Copy Constructor
// Access: Private

View File

@ -27,6 +27,21 @@ MutexDebug::VoidFunc *MutexDebug::_pstats_wait_stop;
MutexImpl MutexDebug::_global_mutex;
////////////////////////////////////////////////////////////////////
// Function: MutexDebug::Constructor
// Access: Protected
// Description:
////////////////////////////////////////////////////////////////////
MutexDebug::
MutexDebug(const string &name, bool allow_recursion) :
_name(name),
_allow_recursion(allow_recursion),
_locking_thread(NULL),
_lock_count(0),
_cvar(_global_mutex)
{
}
////////////////////////////////////////////////////////////////////
// Function: MutexDebug::Destructor
// Access: Protected, Virtual
@ -50,9 +65,9 @@ MutexDebug::
void MutexDebug::
output(ostream &out) const {
if (_allow_recursion) {
out << "ReMutex " << (void *)this;
out << "ReMutex " << _name << " " << (void *)this;
} else {
out << "Mutex " << (void *)this;
out << "Mutex " << _name << " " << (void *)this;
}
}
@ -152,7 +167,8 @@ do_lock() {
if (thread_cat.is_spam()) {
thread_cat.spam()
<< *this_thread << " blocking on " << *this << "\n";
<< *this_thread << " blocking on " << *this << " (held by "
<< *_locking_thread << ")\n";
}
while (_locking_thread != (Thread *)NULL) {
_cvar.wait();

View File

@ -35,7 +35,7 @@ class Thread;
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA MutexDebug {
protected:
INLINE MutexDebug(bool allow_recursion);
MutexDebug(const string &name, bool allow_recursion);
virtual ~MutexDebug();
private:
INLINE MutexDebug(const MutexDebug &copy);
@ -59,6 +59,7 @@ private:
void report_deadlock(Thread *this_thread);
private:
string _name;
bool _allow_recursion;
Thread *_locking_thread;
int _lock_count;

View File

@ -32,6 +32,9 @@ Pipeline *Pipeline::_render_pipeline = (Pipeline *)NULL;
Pipeline::
Pipeline(const string &name, int num_stages) :
Namable(name)
#ifdef THREADED_PIPELINE
, _lock("Pipeline")
#endif
{
#ifdef THREADED_PIPELINE
// Set up the linked list of cyclers to be a circular list that

View File

@ -24,13 +24,41 @@
////////////////////////////////////////////////////////////////////
INLINE Mutex::
#ifdef DEBUG_THREADS
Mutex() : MutexDebug(false)
Mutex() : MutexDebug(string(), false)
#else
Mutex()
#endif // DEBUG_THREADS
{
}
////////////////////////////////////////////////////////////////////
// Function: Mutex::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE Mutex::
#ifdef DEBUG_THREADS
Mutex(const char *name) : MutexDebug(string(name), false)
#else
Mutex(const char *)
#endif // DEBUG_THREADS
{
}
////////////////////////////////////////////////////////////////////
// Function: Mutex::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE Mutex::
#ifdef DEBUG_THREADS
Mutex(const string &name) : MutexDebug(name, false)
#else
Mutex(const string &)
#endif // DEBUG_THREADS
{
}
////////////////////////////////////////////////////////////////////
// Function: Mutex::Destructor
// Access: Public
@ -47,7 +75,7 @@ INLINE Mutex::
////////////////////////////////////////////////////////////////////
INLINE Mutex::
#ifdef DEBUG_THREADS
Mutex(const Mutex &copy) : MutexDebug(false)
Mutex(const Mutex &copy) : MutexDebug(string(), false)
#else
Mutex(const Mutex &copy)
#endif // DEBUG_THREADS

View File

@ -50,6 +50,8 @@ class EXPCL_PANDA Mutex : public MutexDirect
{
public:
INLINE Mutex();
INLINE Mutex(const char *name);
INLINE Mutex(const string &name);
INLINE ~Mutex();
private:
INLINE Mutex(const Mutex &copy);

View File

@ -24,13 +24,41 @@
////////////////////////////////////////////////////////////////////
INLINE ReMutex::
#ifdef DEBUG_THREADS
ReMutex() : MutexDebug(true)
ReMutex() : MutexDebug(string(), true)
#else
ReMutex()
#endif // DEBUG_THREADS
{
}
////////////////////////////////////////////////////////////////////
// Function: ReMutex::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE ReMutex::
#ifdef DEBUG_THREADS
ReMutex(const char *name) : MutexDebug(string(name), true)
#else
ReMutex(const char *)
#endif // DEBUG_THREADS
{
}
////////////////////////////////////////////////////////////////////
// Function: ReMutex::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE ReMutex::
#ifdef DEBUG_THREADS
ReMutex(const string &name) : MutexDebug(name, true)
#else
ReMutex(const string &)
#endif // DEBUG_THREADS
{
}
////////////////////////////////////////////////////////////////////
// Function: ReMutex::Destructor
// Access: Public
@ -40,21 +68,6 @@ INLINE ReMutex::
~ReMutex() {
}
////////////////////////////////////////////////////////////////////
// Function: ReMutex::Copy Constructor
// Access: Private
// Description: Do not attempt to copy mutexes.
////////////////////////////////////////////////////////////////////
INLINE ReMutex::
#ifdef DEBUG_THREADS
ReMutex(const ReMutex &copy) : MutexDebug(true)
#else
ReMutex(const ReMutex &copy)
#endif // DEBUG_THREADS
{
nassertv(false);
}
////////////////////////////////////////////////////////////////////
// Function: ReMutex::Copy Assignment Operator
// Access: Private

View File

@ -42,6 +42,8 @@ class EXPCL_PANDA ReMutex : public ReMutexDirect
{
public:
INLINE ReMutex();
INLINE ReMutex(const char *name);
INLINE ReMutex(const string &name);
INLINE ~ReMutex();
private:
INLINE ReMutex(const ReMutex &copy);

View File

@ -58,7 +58,8 @@ PerThreadData() {
////////////////////////////////////////////////////////////////////
PStatClient::
PStatClient() :
_impl(NULL)
_impl(NULL),
_lock("PStatClient")
{
_collectors = NULL;
_collectors_size = 0;
@ -489,14 +490,7 @@ do_make_thread(Thread *thread) {
_threads_by_name[thread->get_name()].push_back(new_index);
_threads_by_sync_name[thread->get_sync_name()].push_back(new_index);
InternalThread *pthread = new InternalThread;
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;
InternalThread *pthread = new InternalThread(thread);
add_thread(pthread);
// We need an additional PerThreadData for this thread in all of the
@ -899,4 +893,21 @@ make_def(const PStatClient *client, int this_index) {
}
}
////////////////////////////////////////////////////////////////////
// Function: PStatClient::Collector::make_def
// Access: Private
// Description: Creates the new PStatCollectorDef for this collector.
////////////////////////////////////////////////////////////////////
PStatClient::InternalThread::
InternalThread(Thread *thread) :
_thread(thread),
_name(thread->get_name()),
_sync_name(thread->get_sync_name()),
_is_active(false),
_next_packet(0.0),
_frame_number(0),
_thread_lock(string("PStatClient::InternalThread ") + thread->get_name())
{
}
#endif // DO_PSTATS

View File

@ -194,6 +194,8 @@ private:
// maintained separately for each thread.
class InternalThread {
public:
InternalThread(Thread *thread);
WPT(Thread) _thread;
string _name;
string _sync_name;

View File

@ -23,7 +23,7 @@
// Description: Creates an UpdateSeq in the 'initial' state.
////////////////////////////////////////////////////////////////////
INLINE UpdateSeq::
UpdateSeq() {
UpdateSeq() : _lock("UpdateSeq") {
_seq = (unsigned int)SC_initial;
}
@ -67,9 +67,8 @@ fresh() {
// Description:
////////////////////////////////////////////////////////////////////
INLINE UpdateSeq::
UpdateSeq(const UpdateSeq &copy) {
MutexHolder holder(_lock);
_seq = copy._seq;
UpdateSeq(const UpdateSeq &copy) : _lock("UpdateSeq") {
_seq = AtomicAdjust::get(copy._seq);
}
////////////////////////////////////////////////////////////////////
@ -79,8 +78,7 @@ UpdateSeq(const UpdateSeq &copy) {
////////////////////////////////////////////////////////////////////
INLINE UpdateSeq &UpdateSeq::
operator = (const UpdateSeq &copy) {
MutexHolder holder(_lock);
_seq = copy._seq;
AtomicAdjust::set(_seq, AtomicAdjust::get(copy._seq));
return *this;
}
@ -91,8 +89,7 @@ operator = (const UpdateSeq &copy) {
////////////////////////////////////////////////////////////////////
INLINE void UpdateSeq::
clear() {
MutexHolder holder(_lock);
_seq = (unsigned int)SC_initial;
AtomicAdjust::set(_seq, (PN_int32)SC_initial);
}
////////////////////////////////////////////////////////////////////
@ -103,8 +100,7 @@ clear() {
////////////////////////////////////////////////////////////////////
INLINE bool UpdateSeq::
is_initial() const {
MutexHolder holder(_lock);
return _seq == (unsigned int)SC_initial;
return AtomicAdjust::get(_seq) == (PN_int32)SC_initial;
}
////////////////////////////////////////////////////////////////////
@ -114,8 +110,7 @@ is_initial() const {
////////////////////////////////////////////////////////////////////
INLINE bool UpdateSeq::
is_old() const {
MutexHolder holder(_lock);
return _seq == (unsigned int)SC_old;
return AtomicAdjust::get(_seq) == (PN_int32)SC_old;
}
////////////////////////////////////////////////////////////////////
@ -126,8 +121,7 @@ is_old() const {
////////////////////////////////////////////////////////////////////
INLINE bool UpdateSeq::
is_fresh() const {
MutexHolder holder(_lock);
return _seq == (unsigned int)SC_fresh;
return AtomicAdjust::get(_seq) == (PN_int32)SC_fresh;
}
////////////////////////////////////////////////////////////////////
@ -138,8 +132,8 @@ is_fresh() const {
////////////////////////////////////////////////////////////////////
INLINE bool UpdateSeq::
is_special() const {
MutexHolder holder(_lock);
return priv_is_special();
// This relies on the assumption that (~0 + 1) == 0.
return ((AtomicAdjust::get(_seq) + 1) <= 2);
}
////////////////////////////////////////////////////////////////////
@ -149,8 +143,7 @@ is_special() const {
////////////////////////////////////////////////////////////////////
INLINE bool UpdateSeq::
operator == (const UpdateSeq &other) const {
MutexHolder holder(_lock);
return (_seq == other._seq);
return AtomicAdjust::get(_seq) == AtomicAdjust::get(other._seq);
}
////////////////////////////////////////////////////////////////////
@ -160,8 +153,7 @@ operator == (const UpdateSeq &other) const {
////////////////////////////////////////////////////////////////////
INLINE bool UpdateSeq::
operator != (const UpdateSeq &other) const {
MutexHolder holder(_lock);
return (_seq != other._seq);
return AtomicAdjust::get(_seq) != AtomicAdjust::get(other._seq);
}
////////////////////////////////////////////////////////////////////
@ -171,8 +163,7 @@ operator != (const UpdateSeq &other) const {
////////////////////////////////////////////////////////////////////
INLINE bool UpdateSeq::
operator < (const UpdateSeq &other) const {
MutexHolder holder(_lock);
return priv_lt(other);
return priv_lt(AtomicAdjust::get(_seq), AtomicAdjust::get(other._seq));
}
////////////////////////////////////////////////////////////////////
@ -182,8 +173,7 @@ operator < (const UpdateSeq &other) const {
////////////////////////////////////////////////////////////////////
INLINE bool UpdateSeq::
operator <= (const UpdateSeq &other) const {
MutexHolder holder(_lock);
return _seq == other._seq || priv_lt(other);
return priv_le(AtomicAdjust::get(_seq), AtomicAdjust::get(other._seq));
}
////////////////////////////////////////////////////////////////////
@ -215,11 +205,14 @@ INLINE UpdateSeq UpdateSeq::
operator ++ () {
{
MutexHolder holder(_lock);
++_seq;
if (priv_is_special()) {
PN_int32 new_seq = _seq + 1;
if (priv_is_special(new_seq)) {
// Oops, wraparound. We don't want to confuse the new value
// with our special cases.
_seq = (unsigned int)SC_old + 1;
AtomicAdjust::set(_seq, (PN_int32)SC_old + 1);
} else {
AtomicAdjust::set(_seq, new_seq);
}
}
@ -237,10 +230,12 @@ operator ++ (int) {
{
MutexHolder holder(_lock);
temp._seq = _seq;
++_seq;
if (priv_is_special()) {
_seq = (unsigned int)SC_old + 1;
PN_int32 new_seq = _seq + 1;
if (priv_is_special(new_seq)) {
AtomicAdjust::set(_seq, (PN_int32)SC_old + 1);
} else {
AtomicAdjust::set(_seq, new_seq);
}
}
@ -254,11 +249,7 @@ operator ++ (int) {
////////////////////////////////////////////////////////////////////
INLINE void UpdateSeq::
output(ostream &out) const {
unsigned int seq;
{
MutexHolder holder(_lock);
seq = _seq;
}
PN_int32 seq = AtomicAdjust::get(_seq);
switch (seq) {
case SC_initial:
out << "initial";
@ -273,38 +264,46 @@ output(ostream &out) const {
break;
default:
out << (long unsigned int)seq;
out << (unsigned int)seq;
}
}
////////////////////////////////////////////////////////////////////
// Function: UpdateSeq::priv_is_special
// Access: Published
// Description: The private implementation of is_special(). Assumes
// the lock is already held.
// Access: Private, Static
// Description: The private implementation of is_special().
////////////////////////////////////////////////////////////////////
INLINE bool UpdateSeq::
priv_is_special() const {
priv_is_special(PN_int32 seq) {
// This relies on the assumption that (~0 + 1) == 0.
return ((_seq + 1) <= 2);
return (((unsigned int)seq + 1) <= 2);
}
////////////////////////////////////////////////////////////////////
// Function: UpdateSeq::priv_lt
// Access: Published
// Description: The private implementation of operator < (). Assumes
// the lock is already held.
// Access: Private, Static
// Description: The private implementation of operator < ().
////////////////////////////////////////////////////////////////////
INLINE bool UpdateSeq::
priv_lt(const UpdateSeq &other) const {
priv_lt(PN_int32 a, PN_int32 b) {
// The special cases of SC_initial or SC_old are less than all other
// non-special numbers, and SC_initial is less than SC_old. The
// special case of SC_fresh is greater than all other non-special
// numbers. For all other cases, we use a circular comparision such
// that n < m iff (signed)(n - m) < 0.
return
(priv_is_special() || other.priv_is_special()) ? (_seq < other._seq) :
((signed int)(_seq - other._seq) < 0);
(priv_is_special(a) || priv_is_special(b)) ? ((unsigned int)a < (unsigned int)b) :
((signed int)(a - b) < 0);
}
////////////////////////////////////////////////////////////////////
// Function: UpdateSeq::priv_le
// Access: Private, Static
// Description: The private implementation of operator <= ().
////////////////////////////////////////////////////////////////////
INLINE bool UpdateSeq::
priv_le(PN_int32 a, PN_int32 b) {
return (a == b) || priv_lt(a, b);
}
INLINE ostream &operator << (ostream &out, const UpdateSeq &value) {

View File

@ -17,5 +17,3 @@
////////////////////////////////////////////////////////////////////
#include "updateSeq.h"
Mutex UpdateSeq::_lock;

View File

@ -22,6 +22,8 @@
#include "pandabase.h"
#include "pmutex.h"
#include "mutexHolder.h"
#include "atomicAdjust.h"
#include "numeric_types.h"
////////////////////////////////////////////////////////////////////
// Class : UpdateSeq
@ -72,8 +74,9 @@ PUBLISHED:
INLINE void output(ostream &out) const;
private:
INLINE bool priv_is_special() const;
INLINE bool priv_lt(const UpdateSeq &other) const;
INLINE static bool priv_is_special(PN_int32 seq);
INLINE static bool priv_lt(PN_int32 a, PN_int32 b);
INLINE static bool priv_le(PN_int32 a, PN_int32 b);
private:
enum SpecialCases {
@ -82,10 +85,8 @@ private:
SC_fresh = ~(unsigned int)0,
};
unsigned int _seq;
// This mutex globally protects all UpdateSeqs in the world.
static Mutex _lock;
PN_int32 _seq;
Mutex _lock;
};
INLINE ostream &operator << (ostream &out, const UpdateSeq &value);

View File

@ -29,7 +29,9 @@ TypeHandle MouseWatcherGroup::_type_handle;
// Description:
////////////////////////////////////////////////////////////////////
MouseWatcherGroup::
MouseWatcherGroup() {
MouseWatcherGroup() :
_lock("MouseWatcherGroup")
{
#ifndef NDEBUG
_show_regions = false;
_color.set(0.4f, 0.6f, 1.0f, 1.0f);