mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-04 02:42:49 -04:00
improved memory tracking tools
This commit is contained in:
parent
b560a14680
commit
22288e7e48
@ -93,3 +93,6 @@
|
||||
|
||||
// Do we have RTTI (and <typeinfo>)?
|
||||
#define HAVE_RTTI 1
|
||||
|
||||
// Must global operator new and delete functions throw exceptions?
|
||||
#define GLOBAL_OPERATOR_NEW_EXCEPTIONS
|
||||
|
@ -93,3 +93,9 @@
|
||||
|
||||
// Do we have RTTI (and <typeinfo>)?
|
||||
#define HAVE_RTTI 1
|
||||
|
||||
// Must global operator new and delete functions throw exceptions?
|
||||
#define GLOBAL_OPERATOR_NEW_EXCEPTIONS 1
|
||||
|
||||
// Do we expect the old gcc custom STL allocator?
|
||||
#define GCC_STYLE_ALLOCATOR 1
|
||||
|
@ -94,8 +94,9 @@
|
||||
// Do we have RTTI (and <typeinfo>)?
|
||||
#define HAVE_RTTI 1
|
||||
|
||||
// Must global operator new and delete functions throw exceptions?
|
||||
#define GLOBAL_OPERATOR_NEW_EXCEPTIONS
|
||||
|
||||
// can Intel C++ build this directory successfully (if not, change CC to msvc)
|
||||
#define NOT_INTEL_BUILDABLE false
|
||||
|
||||
|
||||
|
||||
|
@ -181,6 +181,12 @@ $[cdefine HAVE_SYS_SOUNDCARD_H]
|
||||
/* Do we have RTTI (and <typeinfo>)? */
|
||||
$[cdefine HAVE_RTTI]
|
||||
|
||||
/* Must global operator new and delete functions throw exceptions? */
|
||||
$[cdefine GLOBAL_OPERATOR_NEW_EXCEPTIONS]
|
||||
|
||||
/* Do we expect the old gcc custom STL allocator? */
|
||||
$[cdefine GCC_STYLE_ALLOCATOR]
|
||||
|
||||
#end dtool_config.h
|
||||
|
||||
#endif // BUILD_TYPE
|
||||
|
@ -6,8 +6,12 @@
|
||||
|
||||
#define SOURCES \
|
||||
dtoolbase.cxx dtoolbase.h dtoolbase_cc.h dtoolsymbols.h \
|
||||
fakestringstream.h
|
||||
fakestringstream.h \
|
||||
pallocator.T pallocator.h \
|
||||
pdeque.h plist.h pmap.h pset.h pvector.h
|
||||
|
||||
#define INSTALL_HEADERS \
|
||||
dtoolbase.h dtoolbase_cc.h dtoolsymbols.h fakestringstream.h
|
||||
dtoolbase.h dtoolbase_cc.h dtoolsymbols.h fakestringstream.h \
|
||||
pallocator.T pallocator.h \
|
||||
pdeque.h plist.h pmap.h pset.h pvector.h
|
||||
#end lib_target
|
||||
|
@ -17,3 +17,21 @@
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "dtoolbase.h"
|
||||
|
||||
|
||||
#ifndef NDEBUG
|
||||
|
||||
void *default_operator_new(size_t size) {
|
||||
return malloc(size);
|
||||
}
|
||||
|
||||
void default_operator_delete(void *ptr) {
|
||||
free(ptr);
|
||||
}
|
||||
|
||||
// We absolutely depend on the static initialization of these pointers
|
||||
// to happen at load time, before any static constructors are called.
|
||||
void *(*global_operator_new)(size_t size) = &default_operator_new;
|
||||
void (*global_operator_delete)(void *ptr) = &default_operator_delete;
|
||||
|
||||
#endif // NDEBUG
|
||||
|
@ -95,5 +95,45 @@ using namespace std;
|
||||
|
||||
#endif // CPPPARSER
|
||||
|
||||
// Now redefine global operators new and delete so we can optionally
|
||||
// provide custom handlers for them. The MemoryUsage class in Panda
|
||||
// takes advantage of this to track the size of allocated pointers.
|
||||
#ifndef NDEBUG
|
||||
EXPCL_DTOOL void *default_operator_new(size_t size);
|
||||
EXPCL_DTOOL void default_operator_delete(void *ptr);
|
||||
|
||||
extern EXPCL_DTOOL void *(*global_operator_new)(size_t size);
|
||||
extern EXPCL_DTOOL void (*global_operator_delete)(void *ptr);
|
||||
|
||||
#ifdef GLOBAL_OPERATOR_NEW_EXCEPTIONS
|
||||
INLINE void *operator new(size_t size) throw (std::bad_alloc) {
|
||||
return (*global_operator_new)(size);
|
||||
}
|
||||
INLINE void *operator new[](size_t size) throw (std::bad_alloc) {
|
||||
return (*global_operator_new)(size);
|
||||
}
|
||||
|
||||
INLINE void operator delete(void *ptr) throw() {
|
||||
(*global_operator_delete)(ptr);
|
||||
}
|
||||
INLINE void operator delete[](void *ptr) throw() {
|
||||
(*global_operator_delete)(ptr);
|
||||
}
|
||||
#else // GLOBAL_OPERATOR_NEW_EXCEPTIONS
|
||||
INLINE void *operator new(size_t size) {
|
||||
return (*global_operator_new)(size);
|
||||
}
|
||||
INLINE void *operator new[](size_t size) {
|
||||
return (*global_operator_new)(size);
|
||||
}
|
||||
|
||||
INLINE void operator delete(void *ptr) {
|
||||
(*global_operator_delete)(ptr);
|
||||
}
|
||||
INLINE void operator delete[](void *ptr) {
|
||||
(*global_operator_delete)(ptr);
|
||||
}
|
||||
#endif // GLOBAL_OPERATOR_NEW_EXCEPTIONS
|
||||
#endif // NDEBUG
|
||||
|
||||
#endif
|
||||
|
51
dtool/src/dtoolbase/pallocator.T
Normal file
51
dtool/src/dtoolbase/pallocator.T
Normal file
@ -0,0 +1,51 @@
|
||||
// Filename: pallocator.T
|
||||
// Created by: drose (05Jun01)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef GCC_STYLE_ALLOCATOR
|
||||
|
||||
#ifndef NDEBUG
|
||||
template<class Type>
|
||||
INLINE void *pallocator<Type>::
|
||||
allocate(size_t n) {
|
||||
return (*global_operator_new)(n);
|
||||
}
|
||||
|
||||
template<class Type>
|
||||
INLINE void pallocator<Type>::
|
||||
deallocate(void *p, size_t) {
|
||||
return (*global_operator_delete)(p);
|
||||
}
|
||||
#endif // NDEBUG
|
||||
|
||||
#else // GCC_STYLE_ALLOCATOR
|
||||
|
||||
#ifndef NDEBUG
|
||||
template<class Type>
|
||||
INLINE pallocator<Type>::pointer pallocator<Type>::
|
||||
allocate(pallocator<Type>::size_type n, allocator<void>::const_pointer) {
|
||||
return (*global_operator_new)(n * sizeof(Type));
|
||||
}
|
||||
|
||||
template<class Type>
|
||||
INLINE void pallocator<Type>::
|
||||
deallocate(pallocator<Type>::pointer p, allocator<Type>::size_type) {
|
||||
return (*global_operator_delete)(p);
|
||||
}
|
||||
#endif // NDEBUG
|
||||
|
||||
#endif // GCC_STYLE_ALLOCATOR
|
66
dtool/src/dtoolbase/pallocator.h
Normal file
66
dtool/src/dtoolbase/pallocator.h
Normal file
@ -0,0 +1,66 @@
|
||||
// Filename: pallocator.h
|
||||
// Created by: drose (05Jun01)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef PALLOCATOR_H
|
||||
#define PALLOCATOR_H
|
||||
|
||||
#include "dtoolbase.h"
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : pallocator
|
||||
// Description : This is our own Panda specialization on the default
|
||||
// STL allocator. Its main purpose is to call the hooks
|
||||
// for MemoryUsage to properly track STL-allocated
|
||||
// memory.
|
||||
//
|
||||
// pvector, pmap, etc. are all defined in this directory
|
||||
// to use a pallocator.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef GCC_STYLE_ALLOCATOR
|
||||
// Early versions of gcc used its own kind of allocator, somewhat
|
||||
// different from the STL standard.
|
||||
|
||||
template<class Type>
|
||||
class pallocator : public alloc {
|
||||
public:
|
||||
#ifndef NDEBUG
|
||||
static void *allocate(size_t n);
|
||||
static void deallocate(void *p, size_t n);
|
||||
#endif // NDEBUG
|
||||
};
|
||||
|
||||
#else // GCC_STYLE_ALLOCATOR
|
||||
|
||||
template<class Type>
|
||||
class pallocator : public allocator<Type> {
|
||||
public:
|
||||
#ifndef NDEBUG
|
||||
INLINE pointer allocate(size_type n, allocator<void>::const_pointer hint = 0);
|
||||
INLINE void deallocate(pointer p, size_type n);
|
||||
#endif // NDEBUG
|
||||
};
|
||||
#endif // GCC_STYLE_ALLOCATOR
|
||||
|
||||
#include "pallocator.T"
|
||||
|
||||
#endif
|
||||
|
44
dtool/src/dtoolbase/pdeque.h
Normal file
44
dtool/src/dtoolbase/pdeque.h
Normal file
@ -0,0 +1,44 @@
|
||||
// Filename: pdeque.h
|
||||
// Created by: drose (05Jun01)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef PDEQUE_H
|
||||
#define PDEQUE_H
|
||||
|
||||
#include "dtoolbase.h"
|
||||
#include "pallocator.h"
|
||||
|
||||
#include <deque>
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : pdeque
|
||||
// Description : This is our own Panda specialization on the default
|
||||
// STL deque. Its main purpose is to call the hooks
|
||||
// for MemoryUsage to properly track STL-allocated
|
||||
// memory.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class Type>
|
||||
class pdeque : public deque<Type, pallocator<Type> > {
|
||||
public:
|
||||
pdeque() : deque<Type, pallocator<Type> >() { }
|
||||
pdeque(const pdeque<Type> ©) : deque<Type, pallocator<Type> >(copy) { }
|
||||
pdeque(size_type n) : deque<Type, pallocator<Type> >(n) { }
|
||||
pdeque(size_type n, const Type &value) : deque<Type, pallocator<Type> >(n, value) { }
|
||||
};
|
||||
|
||||
#endif
|
||||
|
44
dtool/src/dtoolbase/plist.h
Normal file
44
dtool/src/dtoolbase/plist.h
Normal file
@ -0,0 +1,44 @@
|
||||
// Filename: plist.h
|
||||
// Created by: drose (05Jun01)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef PLIST_H
|
||||
#define PLIST_H
|
||||
|
||||
#include "dtoolbase.h"
|
||||
#include "pallocator.h"
|
||||
|
||||
#include <list>
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : plist
|
||||
// Description : This is our own Panda specialization on the default
|
||||
// STL list. Its main purpose is to call the hooks
|
||||
// for MemoryUsage to properly track STL-allocated
|
||||
// memory.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class Type>
|
||||
class plist : public list<Type, pallocator<Type> > {
|
||||
public:
|
||||
plist() : list<Type, pallocator<Type> >() { }
|
||||
plist(const plist<Type> ©) : list<Type, pallocator<Type> >(copy) { }
|
||||
plist(size_type n) : list<Type, pallocator<Type> >(n) { }
|
||||
plist(size_type n, const Type &value) : list<Type, pallocator<Type> >(n, value) { }
|
||||
};
|
||||
|
||||
#endif
|
||||
|
56
dtool/src/dtoolbase/pmap.h
Normal file
56
dtool/src/dtoolbase/pmap.h
Normal file
@ -0,0 +1,56 @@
|
||||
// Filename: pmap.h
|
||||
// Created by: drose (05Jun01)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef PMAP_H
|
||||
#define PMAP_H
|
||||
|
||||
#include "dtoolbase.h"
|
||||
#include "pallocator.h"
|
||||
|
||||
#include <map>
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : pmap
|
||||
// Description : This is our own Panda specialization on the default
|
||||
// STL map. Its main purpose is to call the hooks
|
||||
// for MemoryUsage to properly track STL-allocated
|
||||
// memory.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class Key, class Value, class Compare = less<Key> >
|
||||
class pmap : public map<Key, Value, Compare, pallocator<pair<Key, Value> > > {
|
||||
public:
|
||||
pmap() : map<Key, Value, Compare, pallocator<pair<Key, Value> > >() { }
|
||||
pmap(const pmap<Key> ©) : map<Key, Value, Compare, pallocator<pair<Key, Value> > >(copy) { }
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : pmultimap
|
||||
// Description : This is our own Panda specialization on the default
|
||||
// STL multimap. Its main purpose is to call the hooks
|
||||
// for MemoryUsage to properly track STL-allocated
|
||||
// memory.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class Key, class Value, class Compare = less<Key> >
|
||||
class pmultimap : public multimap<Key, Value, Compare, pallocator<pair<Key, Value> > > {
|
||||
public:
|
||||
pmultimap() : multimap<Key, Value, Compare, pallocator<pair<Key, Value> > >() { }
|
||||
pmultimap(const pmultimap<Key> ©) : multimap<Key, Value, Compare, pallocator<pair<Key, Value> > >(copy) { }
|
||||
};
|
||||
|
||||
#endif
|
||||
|
56
dtool/src/dtoolbase/pset.h
Normal file
56
dtool/src/dtoolbase/pset.h
Normal file
@ -0,0 +1,56 @@
|
||||
// Filename: pset.h
|
||||
// Created by: drose (05Jun01)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef PSET_H
|
||||
#define PSET_H
|
||||
|
||||
#include "dtoolbase.h"
|
||||
#include "pallocator.h"
|
||||
|
||||
#include <set>
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : pset
|
||||
// Description : This is our own Panda specialization on the default
|
||||
// STL set. Its main purpose is to call the hooks
|
||||
// for MemoryUsage to properly track STL-allocated
|
||||
// memory.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class Key, class Compare = less<Key> >
|
||||
class pset : public set<Key, Compare, pallocator<Key> > {
|
||||
public:
|
||||
pset() : set<Key, Compare, pallocator<Key> >() { }
|
||||
pset(const pset<Key> ©) : set<Key, Compare, pallocator<Key> >(copy) { }
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : pmultiset
|
||||
// Description : This is our own Panda specialization on the default
|
||||
// STL multiset. Its main purpose is to call the hooks
|
||||
// for MemoryUsage to properly track STL-allocated
|
||||
// memory.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class Key, class Compare = less<Key> >
|
||||
class pmultiset : public multiset<Key, Compare, pallocator<Key> > {
|
||||
public:
|
||||
pmultiset() : multiset<Key, Compare, pallocator<Key> >() { }
|
||||
pmultiset(const pmultiset<Key> ©) : multiset<Key, Compare, pallocator<Key> >(copy) { }
|
||||
};
|
||||
|
||||
#endif
|
||||
|
44
dtool/src/dtoolbase/pvector.h
Normal file
44
dtool/src/dtoolbase/pvector.h
Normal file
@ -0,0 +1,44 @@
|
||||
// Filename: pvector.h
|
||||
// Created by: drose (05Jun01)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef PVECTOR_H
|
||||
#define PVECTOR_H
|
||||
|
||||
#include "dtoolbase.h"
|
||||
#include "pallocator.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : pvector
|
||||
// Description : This is our own Panda specialization on the default
|
||||
// STL vector. Its main purpose is to call the hooks
|
||||
// for MemoryUsage to properly track STL-allocated
|
||||
// memory.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class Type>
|
||||
class pvector : public vector<Type, pallocator<Type> > {
|
||||
public:
|
||||
pvector() : vector<Type, pallocator<Type> >() { }
|
||||
pvector(const pvector<Type> ©) : vector<Type, pallocator<Type> >(copy) { }
|
||||
pvector(size_type n) : vector<Type, pallocator<Type> >(n) { }
|
||||
pvector(size_type n, const Type &value) : vector<Type, pallocator<Type> >(n, value) { }
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -45,7 +45,7 @@
|
||||
//
|
||||
// They will automatically be undefined at the end of the file.
|
||||
|
||||
#include <vector>
|
||||
#include "pvector.h"
|
||||
|
||||
#if defined(WIN32_VC) && !defined(CPPPARSER)
|
||||
|
||||
@ -65,7 +65,7 @@ EXPORT_TEMPLATE_CLASS(EXPCL, EXPTP, std::vector<TYPE>)
|
||||
#endif
|
||||
|
||||
// Now make a typedef for the vector.
|
||||
typedef std::vector<TYPE> NAME;
|
||||
typedef pvector<TYPE> NAME;
|
||||
|
||||
// Finally, we must define a non-inline function that performs the
|
||||
// insert operation given a range of pointers. We do this because
|
||||
|
@ -143,6 +143,35 @@ clear_bins() {
|
||||
nassertv(_default_bin == (GeomBin *)NULL);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CullTraverser::clear_state
|
||||
// Access: Public
|
||||
// Description: Removes all the cached state information stored
|
||||
// within the CullTraverser, and forces it to rebuild
|
||||
// this state from scratch the next frame.
|
||||
//
|
||||
// This can be used to clear out state that has gone
|
||||
// bad, as well as to free up memory pointers that
|
||||
// otherwise may be held for another frame.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void CullTraverser::
|
||||
clear_state() {
|
||||
_states.clear();
|
||||
_lookup.clear();
|
||||
|
||||
ToplevelBins::const_iterator tbi;
|
||||
for (tbi = _toplevel_bins.begin(); tbi != _toplevel_bins.end(); ++tbi) {
|
||||
(*tbi).second->clear_current_states();
|
||||
}
|
||||
SubBins::const_iterator sbi;
|
||||
for (sbi = _sub_bins.begin(); sbi != _sub_bins.end(); ++sbi) {
|
||||
(*sbi).second->clear_current_states();
|
||||
}
|
||||
_default_bin->clear_current_states();
|
||||
|
||||
_initial_state = AllAttributesWrapper();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CullTraverser::output
|
||||
// Access: Public
|
||||
|
@ -59,6 +59,8 @@ PUBLISHED:
|
||||
GeomBin *get_bin(const string &name) const;
|
||||
void clear_bins();
|
||||
|
||||
void clear_state();
|
||||
|
||||
void output(ostream &out) const;
|
||||
void write(ostream &out, int indent_level = 0) const;
|
||||
|
||||
|
@ -125,6 +125,27 @@ release_all_textures() {
|
||||
nassertv(_prepared_textures.empty());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsStateGuardian::clear_attribute
|
||||
// Access: Public
|
||||
// Description: Explicitly clear the indicated attribute, specified
|
||||
// by the TypeHandle of its associated transition. If
|
||||
// the attribute is not set already, this does nothing;
|
||||
// if it is set, it resets it to its default value.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void GraphicsStateGuardian::
|
||||
clear_attribute(TypeHandle type) {
|
||||
NodeAttributes::iterator ai = _state.find(type);
|
||||
if (ai != _state.end()) {
|
||||
// The state is already set; get the initial value and reset it.
|
||||
PT(NodeAttribute) initial = (*ai).second->make_initial();
|
||||
initial->issue(this);
|
||||
|
||||
// Now remove the state entry from the set.
|
||||
_state.erase(ai);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsStateGuardian::reset
|
||||
// Access: Public, Virtual
|
||||
|
@ -78,10 +78,11 @@ PUBLISHED:
|
||||
}
|
||||
|
||||
void enable_frame_clear(bool clear_color, bool clear_depth);
|
||||
|
||||
public:
|
||||
void release_all_textures();
|
||||
|
||||
void clear_attribute(TypeHandle type);
|
||||
|
||||
public:
|
||||
virtual void clear(const RenderBuffer &buffer)=0;
|
||||
virtual void clear(const RenderBuffer &buffer, const DisplayRegion* region)=0;
|
||||
|
||||
|
@ -16,9 +16,11 @@
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef WIN32_VC
|
||||
#define WINDOWS_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#undef WINDOWS_LEAN_AND_MEAN
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
#include <error_utils.h>
|
||||
|
@ -20,8 +20,11 @@
|
||||
datagramOutputFile.h datagramSink.I datagramSink.h \
|
||||
get_config_path.h hashGeneratorBase.I hashGeneratorBase.h \
|
||||
hashVal.I hashVal.h indent.I indent.h littleEndian.h \
|
||||
memoryUsage.I memoryUsage.h memoryUsagePointers.I \
|
||||
memoryUsagePointers.h multifile.I multifile.h namable.I \
|
||||
memoryInfo.I memoryInfo.h \
|
||||
memoryUsage.I memoryUsage.h \
|
||||
memoryUsagePointerCounts.I memoryUsagePointerCounts.h \
|
||||
memoryUsagePointers.I memoryUsagePointers.h \
|
||||
multifile.I multifile.h namable.I \
|
||||
namable.h nativeNumericData.I nativeNumericData.h \
|
||||
numeric_types.h pointerTo.I pointerTo.h referenceCount.I \
|
||||
profileTimer.I profileTimer.h referenceCount.h \
|
||||
@ -36,7 +39,8 @@
|
||||
config_express.cxx datagram.cxx datagramGenerator.cxx \
|
||||
datagramInputFile.cxx datagramIterator.cxx \
|
||||
datagramOutputFile.cxx datagramSink.cxx get_config_path.cxx \
|
||||
hashGeneratorBase.cxx hashVal.cxx indent.cxx memoryUsage.cxx \
|
||||
hashGeneratorBase.cxx hashVal.cxx indent.cxx \
|
||||
memoryInfo.cxx memoryUsage.cxx memoryUsagePointerCounts.cxx \
|
||||
memoryUsagePointers.cxx multifile.cxx namable.cxx \
|
||||
nativeNumericData.cxx profileTimer.cxx referenceCount.cxx \
|
||||
reversedNumericData.cxx trueClock.cxx typeHandle.cxx \
|
||||
@ -58,9 +62,11 @@
|
||||
datagramGenerator.h get_config_path.h \
|
||||
hashGeneratorBase.I hashGeneratorBase.h \
|
||||
hashVal.I hashVal.h \
|
||||
indent.I indent.h littleEndian.h \
|
||||
memoryUsage.I memoryUsage.h memoryUsagePointers.I \
|
||||
memoryUsagePointers.h multifile.I multifile.h \
|
||||
indent.I indent.h littleEndian.h \
|
||||
memoryInfo.I memoryInfo.h \
|
||||
memoryUsage.I memoryUsage.h \
|
||||
memoryUsagePointerCounts.I memoryUsagePointerCounts.h \
|
||||
memoryUsagePointers.I memoryUsagePointers.h multifile.I multifile.h \
|
||||
nativeNumericData.I nativeNumericData.h \
|
||||
numeric_types.h \
|
||||
pointerTo.I pointerTo.h referenceCount.I referenceCount.h \
|
||||
|
83
panda/src/express/memoryInfo.I
Normal file
83
panda/src/express/memoryInfo.I
Normal file
@ -0,0 +1,83 @@
|
||||
// Filename: memoryInfo.I
|
||||
// Created by: drose (04Jun01)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MemoryInfo::get_void_ptr
|
||||
// Access: Public
|
||||
// Description: Returns the data pointer as a void pointer. This
|
||||
// should always be non-NULL.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void *MemoryInfo::get_void_ptr() const {
|
||||
return _void_ptr;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MemoryInfo::get_ref_ptr
|
||||
// Access: Public
|
||||
// Description: Returns the data pointer as a ReferenceCount pointer.
|
||||
// This may be NULL if the data pointer does not
|
||||
// represent a ReferenceCount object.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
ReferenceCount *MemoryInfo::get_ref_ptr() const {
|
||||
return _ref_ptr;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MemoryInfo::get_typed_ptr
|
||||
// Access: Public
|
||||
// Description: Returns the data pointer as a TypedObject pointer.
|
||||
// This may be NULL if the data pointer does not
|
||||
// represent a pointer to a TypedObject.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
TypedObject *MemoryInfo::get_typed_ptr() const {
|
||||
return _typed_ptr;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MemoryInfo::is_size_known
|
||||
// Access: Public
|
||||
// Description: Returns true if the size of the memory block
|
||||
// referenced by this pointer is known. Most pointers'
|
||||
// sizes should be known, but some may not be.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool MemoryInfo::is_size_known() const {
|
||||
return (_flags & F_size_known) != 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MemoryInfo::get_size
|
||||
// Access: Public
|
||||
// Description: Returns the size in bytes of the memory block
|
||||
// referenced by this pointer, if it is known. Returns
|
||||
// zero if the size is not known.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
size_t MemoryInfo::get_size() const {
|
||||
return _size;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MemoryInfo::get_time
|
||||
// Access: Public
|
||||
// Description: Returns the time in seconds (based on the
|
||||
// GlobalClock) at which the pointer was allocated.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
double MemoryInfo::get_time() const {
|
||||
return _time;
|
||||
}
|
||||
|
149
panda/src/express/memoryInfo.cxx
Normal file
149
panda/src/express/memoryInfo.cxx
Normal file
@ -0,0 +1,149 @@
|
||||
// Filename: memoryInfo.cxx
|
||||
// Created by: drose (04Jun01)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "memoryInfo.h"
|
||||
#include "typedReferenceCount.h"
|
||||
#include "typeHandle.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MemoryInfo::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
MemoryInfo::
|
||||
MemoryInfo() {
|
||||
_void_ptr = (void *)NULL;
|
||||
_ref_ptr = (ReferenceCount *)NULL;
|
||||
_typed_ptr = (TypedObject *)NULL;
|
||||
_size = 0;
|
||||
_static_type = TypeHandle::none();
|
||||
_dynamic_type = TypeHandle::none();
|
||||
|
||||
_flags = 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MemoryInfo::get_type
|
||||
// Access: Public
|
||||
// Description: Returns the best known type, dynamic or static, of
|
||||
// the pointer.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
TypeHandle MemoryInfo::
|
||||
get_type() {
|
||||
// If we don't want to consider the dynamic type any further, use
|
||||
// what we've got.
|
||||
if ((_flags & F_reconsider_dynamic_type) == 0) {
|
||||
if (_dynamic_type == TypeHandle::none()) {
|
||||
return _static_type;
|
||||
}
|
||||
return _dynamic_type;
|
||||
}
|
||||
|
||||
// Otherwise, examine the pointer again and make sure it's still the
|
||||
// best information we have. We have to do this each time because
|
||||
// if we happen to be examining the pointer from within the
|
||||
// constructor or destructor, its dynamic type will appear to be
|
||||
// less-specific than it actually is, so our idea of what type this
|
||||
// thing is could change from time to time.
|
||||
determine_dynamic_type();
|
||||
|
||||
// Now return the more specific of the two.
|
||||
TypeHandle type = _static_type;
|
||||
update_type_handle(type, _dynamic_type);
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MemoryInfo::determine_dynamic_type
|
||||
// Access: Public
|
||||
// Description: Tries to determine the actual type of the object to
|
||||
// which this thing is pointed, if possible.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void MemoryInfo::
|
||||
determine_dynamic_type() {
|
||||
if ((_flags & F_reconsider_dynamic_type) != 0 &&
|
||||
_static_type != TypeHandle::none()) {
|
||||
// See if we know enough now to infer the dynamic type from the
|
||||
// pointer.
|
||||
|
||||
if (_typed_ptr == (TypedObject *)NULL) {
|
||||
// If our static type is known to inherit from
|
||||
// TypedReferenceCount, then we can directly downcast to get the
|
||||
// TypedObject pointer.
|
||||
if (_static_type.is_derived_from(TypedReferenceCount::get_class_type())) {
|
||||
_typed_ptr = (TypedReferenceCount *)_ref_ptr;
|
||||
}
|
||||
}
|
||||
|
||||
if (_typed_ptr != (TypedObject *)NULL) {
|
||||
// If we have a TypedObject pointer, we can determine the type.
|
||||
// This might still not return the exact type, particularly if
|
||||
// we are being called within the destructor or constructor of
|
||||
// this object.
|
||||
TypeHandle got_type = _typed_ptr->get_type();
|
||||
|
||||
if (got_type == TypeHandle::none()) {
|
||||
express_cat.warning()
|
||||
<< "Found an unregistered type in a " << _static_type
|
||||
<< " pointer:\n"
|
||||
<< "Check derived types of " << _static_type
|
||||
<< " and make sure that all are being initialized.\n";
|
||||
_dynamic_type = _static_type;
|
||||
_flags &= ~F_reconsider_dynamic_type;
|
||||
return;
|
||||
}
|
||||
|
||||
update_type_handle(_dynamic_type, got_type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MemoryInfo::update_type_handle
|
||||
// Access: Public
|
||||
// Description: Updates the given destination TypeHandle with the
|
||||
// refined TypeHandle, if it is in fact more specific
|
||||
// than the original value for the destination.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void MemoryInfo::
|
||||
update_type_handle(TypeHandle &destination, TypeHandle refined) {
|
||||
if (refined == TypeHandle::none()) {
|
||||
express_cat.error()
|
||||
<< "Attempt to update type of " << (void *)_ref_ptr
|
||||
<< "(type is " << get_type()
|
||||
<< ") to an undefined type!\n";
|
||||
|
||||
} else if (destination == refined) {
|
||||
// Updating with the same type, no problem.
|
||||
|
||||
} else if (destination.is_derived_from(refined)) {
|
||||
// Updating with a less-specific type, no problem.
|
||||
|
||||
} else if (refined.is_derived_from(destination)) {
|
||||
// Updating with a more-specific type, no problem.
|
||||
destination = refined;
|
||||
|
||||
} else {
|
||||
express_cat.error()
|
||||
<< "Pointer " << (void *)_ref_ptr << " previously indicated as type "
|
||||
<< destination << " is now type " << refined << "!\n";
|
||||
destination = refined;
|
||||
}
|
||||
}
|
88
panda/src/express/memoryInfo.h
Normal file
88
panda/src/express/memoryInfo.h
Normal file
@ -0,0 +1,88 @@
|
||||
// Filename: memoryInfo.h
|
||||
// Created by: drose (04Jun01)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef MEMORYINFO_H
|
||||
#define MEMORYINFO_H
|
||||
|
||||
#include <pandabase.h>
|
||||
#include "typeHandle.h"
|
||||
|
||||
class ReferenceCount;
|
||||
class TypedObject;
|
||||
|
||||
#ifndef NDEBUG
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : MemoryInfo
|
||||
// Description : This is a supporting class for MemoryUsage. It
|
||||
// records the detailed information for a particular
|
||||
// pointer allocated by Panda code. This record is only
|
||||
// kept if track-mem-usage is configured #t.
|
||||
//
|
||||
// It's not exported from the DLL, and it doesn't even
|
||||
// exist if we're compiling NDEBUG.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class MemoryInfo {
|
||||
public:
|
||||
MemoryInfo();
|
||||
|
||||
public:
|
||||
// Members to view the MemoryInfo structure.
|
||||
TypeHandle get_type();
|
||||
|
||||
INLINE void *get_void_ptr() const;
|
||||
INLINE ReferenceCount *get_ref_ptr() const;
|
||||
INLINE TypedObject *get_typed_ptr() const;
|
||||
|
||||
INLINE bool is_size_known() const;
|
||||
INLINE size_t get_size() const;
|
||||
|
||||
INLINE double get_time() const;
|
||||
|
||||
public:
|
||||
// Members to set up the MemoryInfo structure.
|
||||
void determine_dynamic_type();
|
||||
void update_type_handle(TypeHandle &destination, TypeHandle refined);
|
||||
|
||||
private:
|
||||
enum Flags {
|
||||
F_got_ref = 0x0001,
|
||||
F_got_void = 0x0002,
|
||||
F_size_known = 0x0004,
|
||||
F_reconsider_dynamic_type = 0x0008,
|
||||
};
|
||||
|
||||
void *_void_ptr;
|
||||
ReferenceCount *_ref_ptr;
|
||||
TypedObject *_typed_ptr;
|
||||
size_t _size;
|
||||
TypeHandle _static_type;
|
||||
TypeHandle _dynamic_type;
|
||||
int _flags;
|
||||
|
||||
double _time;
|
||||
int _freeze_index;
|
||||
|
||||
friend class MemoryUsage;
|
||||
};
|
||||
|
||||
#include "memoryInfo.I"
|
||||
|
||||
#endif // NDEBUG
|
||||
|
||||
#endif
|
||||
|
@ -115,6 +115,40 @@ remove_pointer(ReferenceCount *ptr) {
|
||||
|
||||
#endif // __GNUC__
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MemoryUsage::is_tracking
|
||||
// Access: Public, Static
|
||||
// Description: Returns true if the MemoryUsage object is currently
|
||||
// tracking memory (e.g. track-memory-usage is
|
||||
// configured #t).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool MemoryUsage::
|
||||
is_tracking() {
|
||||
return get_global_ptr()->_track_memory_usage;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MemoryUsage::get_allocated_size
|
||||
// Access: Public, Static
|
||||
// Description: Returns the total number of bytes of allocated memory
|
||||
// as counted, excluding the memory previously frozen.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE size_t MemoryUsage::
|
||||
get_allocated_size() {
|
||||
return get_global_ptr()->ns_get_allocated_size();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MemoryUsage::get_total_size
|
||||
// Access: Public, Static
|
||||
// Description: Returns the total number of bytes of allocated memory
|
||||
// as counted, including the memory previously frozen.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE size_t MemoryUsage::
|
||||
get_total_size() {
|
||||
return get_global_ptr()->ns_get_total_size();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MemoryUsage::get_num_pointers
|
||||
// Access: Public, Static
|
||||
|
@ -49,116 +49,6 @@ double MemoryUsage::AgeHistogram::_cutoff[MemoryUsage::AgeHistogram::num_buckets
|
||||
60.0,
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MemoryUsage::MemoryInfo::get_type
|
||||
// Access: Public
|
||||
// Description: Returns the best known type, dynamic or static, of
|
||||
// the pointer.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
TypeHandle MemoryUsage::MemoryInfo::
|
||||
get_type() {
|
||||
// If we don't want to consider the dynamic type any further, use
|
||||
// what we've got.
|
||||
if (!_reconsider_dynamic_type) {
|
||||
if (_dynamic_type == TypeHandle::none()) {
|
||||
return _static_type;
|
||||
}
|
||||
return _dynamic_type;
|
||||
}
|
||||
|
||||
// Otherwise, examine the pointer again and make sure it's still the
|
||||
// best information we have. We have to do this each time because
|
||||
// if we happen to be examining the pointer from within the
|
||||
// constructor or destructor, its dynamic type will appear to be
|
||||
// less-specific than it actually is, so our idea of what type this
|
||||
// thing is could change from time to time.
|
||||
determine_dynamic_type();
|
||||
|
||||
// Now return the more specific of the two.
|
||||
TypeHandle type = _static_type;
|
||||
update_type_handle(type, _dynamic_type);
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MemoryUsage::MemoryInfo::determine_dynamic_type
|
||||
// Access: Public
|
||||
// Description: Tries to determine the actual type of the object to
|
||||
// which this thing is pointed, if possible.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void MemoryUsage::MemoryInfo::
|
||||
determine_dynamic_type() {
|
||||
if (_reconsider_dynamic_type && _static_type != TypeHandle::none()) {
|
||||
// See if we know enough now to infer the dynamic type from the
|
||||
// pointer.
|
||||
|
||||
if (_typed_ptr == (TypedObject *)NULL) {
|
||||
// If our static type is known to inherit from
|
||||
// TypedReferenceCount, then we can directly downcast to get the
|
||||
// TypedObject pointer.
|
||||
if (_static_type.is_derived_from(TypedReferenceCount::get_class_type())) {
|
||||
_typed_ptr = (TypedReferenceCount *)_ptr;
|
||||
}
|
||||
}
|
||||
|
||||
if (_typed_ptr != (TypedObject *)NULL) {
|
||||
// If we have a TypedObject pointer, we can determine the type.
|
||||
// This might still not return the exact type, particularly if
|
||||
// we are being called within the destructor or constructor of
|
||||
// this object.
|
||||
TypeHandle got_type = _typed_ptr->get_type();
|
||||
|
||||
if (got_type == TypeHandle::none()) {
|
||||
express_cat.warning()
|
||||
<< "Found an unregistered type in a " << _static_type
|
||||
<< " pointer:\n"
|
||||
<< "Check derived types of " << _static_type
|
||||
<< " and make sure that all are being initialized.\n";
|
||||
_dynamic_type = _static_type;
|
||||
_reconsider_dynamic_type = false;
|
||||
return;
|
||||
}
|
||||
|
||||
update_type_handle(_dynamic_type, got_type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MemoryUsage::MemoryInfo::update_type_handle
|
||||
// Access: Public
|
||||
// Description: Updates the given destination TypeHandle with the
|
||||
// refined TypeHandle, if it is in fact more specific
|
||||
// than the original value for the destination.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void MemoryUsage::MemoryInfo::
|
||||
update_type_handle(TypeHandle &destination, TypeHandle refined) {
|
||||
if (refined == TypeHandle::none()) {
|
||||
express_cat.error()
|
||||
<< "Attempt to update type of " << (void *)_ptr
|
||||
<< "(type is " << get_type()
|
||||
<< ") to an undefined type!\n";
|
||||
|
||||
} else if (destination == refined) {
|
||||
// Updating with the same type, no problem.
|
||||
|
||||
} else if (destination.is_derived_from(refined)) {
|
||||
// Updating with a less-specific type, no problem.
|
||||
|
||||
} else if (refined.is_derived_from(destination)) {
|
||||
// Updating with a more-specific type, no problem.
|
||||
destination = refined;
|
||||
|
||||
} else {
|
||||
express_cat.error()
|
||||
<< "Pointer " << (void *)_ptr << " previously indicated as type "
|
||||
<< destination << " is now type " << refined << "!\n";
|
||||
destination = refined;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MemoryUsage::TypeHistogram::add_info
|
||||
@ -166,8 +56,8 @@ update_type_handle(TypeHandle &destination, TypeHandle refined) {
|
||||
// Description: Adds a single entry to the histogram.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void MemoryUsage::TypeHistogram::
|
||||
add_info(TypeHandle type) {
|
||||
_counts[type]++;
|
||||
add_info(TypeHandle type, MemoryInfo &info) {
|
||||
_counts[type].add_info(info);
|
||||
}
|
||||
|
||||
|
||||
@ -175,14 +65,16 @@ add_info(TypeHandle type) {
|
||||
// below, to sort the types in descending order by counts.
|
||||
class TypeHistogramCountSorter {
|
||||
public:
|
||||
TypeHistogramCountSorter(int count, TypeHandle type) {
|
||||
_count = count;
|
||||
_type = type;
|
||||
TypeHistogramCountSorter(const MemoryUsagePointerCounts &count,
|
||||
TypeHandle type) :
|
||||
_count(count),
|
||||
_type(type)
|
||||
{
|
||||
}
|
||||
bool operator < (const TypeHistogramCountSorter &other) const {
|
||||
return _count > other._count;
|
||||
}
|
||||
int _count;
|
||||
MemoryUsagePointerCounts _count;
|
||||
TypeHandle _type;
|
||||
};
|
||||
|
||||
@ -206,7 +98,13 @@ show() const {
|
||||
|
||||
vector<TypeHistogramCountSorter>::const_iterator vi;
|
||||
for (vi = count_sorter.begin(); vi != count_sorter.end(); ++vi) {
|
||||
nout << (*vi)._type << " : " << (*vi)._count << " pointers.\n";
|
||||
TypeHandle type = (*vi)._type;
|
||||
if (type == TypeHandle::none()) {
|
||||
nout << "unknown";
|
||||
} else {
|
||||
nout << type;
|
||||
}
|
||||
nout << " : " << (*vi)._count << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
@ -236,10 +134,10 @@ AgeHistogram() {
|
||||
// Description: Adds a single entry to the histogram.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void MemoryUsage::AgeHistogram::
|
||||
add_info(double age) {
|
||||
add_info(double age, MemoryInfo &info) {
|
||||
int bucket = choose_bucket(age);
|
||||
nassertv(bucket >= 0 && bucket < num_buckets);
|
||||
_counts[bucket]++;
|
||||
_counts[bucket].add_info(info);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -250,11 +148,13 @@ add_info(double age) {
|
||||
void MemoryUsage::AgeHistogram::
|
||||
show() const {
|
||||
for (int i = 0; i < num_buckets - 1; i++) {
|
||||
nout << _cutoff[i] << " to " << _cutoff[i + 1] << " seconds old : "
|
||||
<< _counts[i] << " pointers.\n";
|
||||
nout << _cutoff[i] << " to " << _cutoff[i + 1] << " seconds old : ";
|
||||
_counts[i].output(nout);
|
||||
nout << "\n";
|
||||
}
|
||||
nout << _cutoff[num_buckets - 1] << " seconds old and up : "
|
||||
<< _counts[num_buckets - 1] << " pointers.\n";
|
||||
nout << _cutoff[num_buckets - 1] << " seconds old and up : ";
|
||||
_counts[num_buckets - 1].output(nout);
|
||||
nout << "\n";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -265,7 +165,7 @@ show() const {
|
||||
void MemoryUsage::AgeHistogram::
|
||||
clear() {
|
||||
for (int i = 0; i < num_buckets; i++) {
|
||||
_counts[i] = 0;
|
||||
_counts[i].clear();
|
||||
}
|
||||
}
|
||||
|
||||
@ -341,6 +241,37 @@ remove_pointer(ReferenceCount *ptr) {
|
||||
|
||||
#endif // __GNUC__ && !NDEBUG
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MemoryUsage::operator_new_handler
|
||||
// Access: Public, Static
|
||||
// Description: This is set up as a global handler function (by
|
||||
// redefining a function pointer in Dtool) for the
|
||||
// operator new function. If track-memory-usage is
|
||||
// enabled, this function will be called whenever any
|
||||
// new operator within the Panda source is invoked.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void *MemoryUsage::
|
||||
operator_new_handler(size_t size) {
|
||||
void *ptr = default_operator_new(size);
|
||||
get_global_ptr()->ns_record_void_pointer(ptr, size);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MemoryUsage::operator_delete_handler
|
||||
// Access: Public, Static
|
||||
// Description: This is set up as a global handler function (by
|
||||
// redefining a function pointer in Dtool) for the
|
||||
// operator delete function. If track-memory-usage is
|
||||
// enabled, this function will be called whenever any
|
||||
// delete operator within the Panda source is invoked.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void MemoryUsage::
|
||||
operator_delete_handler(void *ptr) {
|
||||
get_global_ptr()->ns_remove_void_pointer(ptr);
|
||||
return default_operator_delete(ptr);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MemoryUsage::Constructor
|
||||
// Access: Private
|
||||
@ -354,8 +285,18 @@ MemoryUsage() {
|
||||
_track_memory_usage =
|
||||
config_express.GetBool("track-memory-usage", false);
|
||||
|
||||
if (_track_memory_usage) {
|
||||
// Redefine the global pointers for operator new and operator
|
||||
// delete (these pointers are defined up in DTOOL) to vector into
|
||||
// this class.
|
||||
global_operator_new = &operator_new_handler;
|
||||
global_operator_delete = &operator_delete_handler;
|
||||
}
|
||||
|
||||
_freeze_index = 0;
|
||||
_count = 0;
|
||||
_allocated_size = 0;
|
||||
_total_size = 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -382,24 +323,31 @@ get_global_ptr() {
|
||||
void MemoryUsage::
|
||||
ns_record_pointer(ReferenceCount *ptr) {
|
||||
if (_track_memory_usage) {
|
||||
MemoryInfo info;
|
||||
info._ptr = ptr;
|
||||
info._typed_ptr = (TypedObject *)NULL;
|
||||
pair<Table::iterator, bool> insert_result =
|
||||
_table.insert(Table::value_type((void *)ptr, MemoryInfo()));
|
||||
|
||||
// This shouldn't fail.
|
||||
assert(insert_result.first != _table.end());
|
||||
|
||||
if (insert_result.second) {
|
||||
_count++;
|
||||
}
|
||||
|
||||
MemoryInfo &info = (*insert_result.first).second;
|
||||
|
||||
// We shouldn't already have a ReferenceCount pointer.
|
||||
if ((info._flags & MemoryInfo::F_got_ref) != 0) {
|
||||
express_cat.error()
|
||||
<< "Pointer " << (void *)ptr << " recorded twice!\n";
|
||||
}
|
||||
|
||||
info._void_ptr = (void *)ptr;
|
||||
info._ref_ptr = ptr;
|
||||
info._static_type = ReferenceCount::get_class_type();
|
||||
info._dynamic_type = ReferenceCount::get_class_type();
|
||||
info._time = TrueClock::get_ptr()->get_real_time();
|
||||
info._freeze_index = _freeze_index;
|
||||
info._reconsider_dynamic_type = true;
|
||||
|
||||
Table::iterator ti;
|
||||
ti = _table.find(ptr);
|
||||
if (ti != _table.end()) {
|
||||
express_cat.error() << "Pointer " << (void *)ptr << " recorded twice!\n";
|
||||
(*ti).second = info;
|
||||
} else {
|
||||
_table[ptr] = info;
|
||||
_count++;
|
||||
}
|
||||
info._flags |= (MemoryInfo::F_reconsider_dynamic_type | MemoryInfo::F_got_ref);
|
||||
}
|
||||
}
|
||||
|
||||
@ -427,6 +375,8 @@ ns_update_type(ReferenceCount *ptr, TypeHandle type) {
|
||||
MemoryInfo &info = (*ti).second;
|
||||
info.update_type_handle(info._static_type, type);
|
||||
info.determine_dynamic_type();
|
||||
|
||||
consolidate_void_ptr(info);
|
||||
}
|
||||
}
|
||||
|
||||
@ -456,6 +406,8 @@ ns_update_type(ReferenceCount *ptr, TypedObject *typed_ptr) {
|
||||
MemoryInfo &info = (*ti).second;
|
||||
info._typed_ptr = typed_ptr;
|
||||
info.determine_dynamic_type();
|
||||
|
||||
consolidate_void_ptr(info);
|
||||
}
|
||||
}
|
||||
|
||||
@ -481,6 +433,14 @@ ns_remove_pointer(ReferenceCount *ptr) {
|
||||
|
||||
MemoryInfo &info = (*ti).second;
|
||||
|
||||
if ((info._flags & MemoryInfo::F_got_ref) == 0) {
|
||||
express_cat.error()
|
||||
<< "Pointer " << (void *)ptr << " deleted twice!\n";
|
||||
return;
|
||||
}
|
||||
|
||||
info._flags &= ~MemoryInfo::F_got_ref;
|
||||
|
||||
// Since the pointer has been destructed, we can't safely call its
|
||||
// TypedObject virtual methods any more. Better clear out the
|
||||
// typed_ptr for good measure.
|
||||
@ -488,15 +448,143 @@ ns_remove_pointer(ReferenceCount *ptr) {
|
||||
|
||||
if (info._freeze_index == _freeze_index) {
|
||||
double now = TrueClock::get_ptr()->get_real_time();
|
||||
_count--;
|
||||
_trend_types.add_info(info.get_type());
|
||||
_trend_ages.add_info(now - info._time);
|
||||
_trend_types.add_info(info.get_type(), info);
|
||||
_trend_ages.add_info(now - info._time, info);
|
||||
}
|
||||
|
||||
_table.erase(ti);
|
||||
if ((info._flags & (MemoryInfo::F_got_ref | MemoryInfo::F_got_void)) == 0) {
|
||||
// If we don't expect to call any more remove_*_pointer on this
|
||||
// pointer, remove it from the table.
|
||||
if (info._freeze_index == _freeze_index) {
|
||||
_count--;
|
||||
_allocated_size -= info._size;
|
||||
}
|
||||
_total_size -= info._size;
|
||||
|
||||
_table.erase(ti);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MemoryUsage::ns_record_void_pointer
|
||||
// Access: Private
|
||||
// Description: Records a pointer that's not even necessarily a
|
||||
// ReferenceCount object (but for which we know the size
|
||||
// of the allocated structure).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void MemoryUsage::
|
||||
ns_record_void_pointer(void *ptr, size_t size) {
|
||||
if (_track_memory_usage) {
|
||||
pair<Table::iterator, bool> insert_result =
|
||||
_table.insert(Table::value_type((void *)ptr, MemoryInfo()));
|
||||
|
||||
// This shouldn't fail.
|
||||
assert(insert_result.first != _table.end());
|
||||
|
||||
if (insert_result.second) {
|
||||
_count++;
|
||||
}
|
||||
|
||||
MemoryInfo &info = (*insert_result.first).second;
|
||||
|
||||
// We shouldn't already have a void pointer.
|
||||
if ((info._flags & MemoryInfo::F_got_void) != 0) {
|
||||
express_cat.error()
|
||||
<< "Pointer " << (void *)ptr << " recorded twice!\n";
|
||||
}
|
||||
|
||||
if (info._freeze_index == _freeze_index) {
|
||||
_allocated_size += size - info._size;
|
||||
} else {
|
||||
_allocated_size += size;
|
||||
}
|
||||
_total_size += size - info._size;
|
||||
|
||||
info._void_ptr = ptr;
|
||||
info._size = size;
|
||||
info._time = TrueClock::get_ptr()->get_real_time();
|
||||
info._freeze_index = _freeze_index;
|
||||
info._flags |= (MemoryInfo::F_got_void | MemoryInfo::F_size_known);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MemoryUsage::ns_remove_void_pointer
|
||||
// Access: Private
|
||||
// Description: Removes a pointer previously recorded via
|
||||
// record_void_pointer.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void MemoryUsage::
|
||||
ns_remove_void_pointer(void *ptr) {
|
||||
if (_track_memory_usage) {
|
||||
Table::iterator ti;
|
||||
ti = _table.find(ptr);
|
||||
if (ti == _table.end()) {
|
||||
// The pointer we tried to delete was not recorded in the table.
|
||||
|
||||
// We can't report this as an error, because (a) we might have
|
||||
// removed the void pointer entry already when we consolidated,
|
||||
// and (b) a few objects might have been created during static
|
||||
// init time, before we grabbed the operator new/delete function
|
||||
// handlers.
|
||||
return;
|
||||
}
|
||||
|
||||
MemoryInfo &info = (*ti).second;
|
||||
|
||||
if ((info._flags & MemoryInfo::F_got_void) == 0) {
|
||||
express_cat.error()
|
||||
<< "Pointer " << (void *)ptr << " deleted twice!\n";
|
||||
return;
|
||||
}
|
||||
|
||||
if ((info._flags & MemoryInfo::F_got_ref) != 0) {
|
||||
express_cat.error()
|
||||
<< "Pointer " << (void *)ptr << " did not destruct before being deleted!\n";
|
||||
}
|
||||
|
||||
info._flags &= ~MemoryInfo::F_got_void;
|
||||
|
||||
if ((info._flags & (MemoryInfo::F_got_ref | MemoryInfo::F_got_void)) == 0) {
|
||||
// If we don't expect to call any more remove_*_pointer on this
|
||||
// pointer, remove it from the table.
|
||||
|
||||
if (info._freeze_index == _freeze_index) {
|
||||
_count--;
|
||||
_allocated_size -= info._size;
|
||||
}
|
||||
_total_size -= info._size;
|
||||
|
||||
_table.erase(ti);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MemoryUsage::ns_get_allocated_size
|
||||
// Access: Private
|
||||
// Description: Returns the total number of bytes of allocated memory
|
||||
// as counted, excluding the memory previously frozen.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
size_t MemoryUsage::
|
||||
ns_get_allocated_size() {
|
||||
nassertr(_track_memory_usage, 0);
|
||||
return _allocated_size;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MemoryUsage::ns_get_total_size
|
||||
// Access: Private
|
||||
// Description: Returns the total number of bytes of allocated memory
|
||||
// as counted, including the memory previously frozen.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
size_t MemoryUsage::
|
||||
ns_get_total_size() {
|
||||
nassertr(_track_memory_usage, 0);
|
||||
return _total_size;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MemoryUsage::ns_get_num_pointers
|
||||
// Access: Private
|
||||
@ -523,8 +611,9 @@ ns_get_pointers(MemoryUsagePointers &result) {
|
||||
Table::iterator ti;
|
||||
for (ti = _table.begin(); ti != _table.end(); ++ti) {
|
||||
MemoryInfo &info = (*ti).second;
|
||||
if (info._freeze_index == _freeze_index) {
|
||||
result.add_entry(info._ptr, info._typed_ptr, info.get_type(),
|
||||
if (info._freeze_index == _freeze_index &&
|
||||
info._ref_ptr != (ReferenceCount *)NULL) {
|
||||
result.add_entry(info._ref_ptr, info._typed_ptr, info.get_type(),
|
||||
now - info._time);
|
||||
}
|
||||
}
|
||||
@ -546,11 +635,12 @@ ns_get_pointers_of_type(MemoryUsagePointers &result, TypeHandle type) {
|
||||
Table::iterator ti;
|
||||
for (ti = _table.begin(); ti != _table.end(); ++ti) {
|
||||
MemoryInfo &info = (*ti).second;
|
||||
if (info._freeze_index == _freeze_index) {
|
||||
if (info._freeze_index == _freeze_index &&
|
||||
info._ref_ptr != (ReferenceCount *)NULL) {
|
||||
TypeHandle info_type = info.get_type();
|
||||
if (info_type != TypeHandle::none() &&
|
||||
info_type.is_derived_from(type)) {
|
||||
result.add_entry(info._ptr, info._typed_ptr, info_type,
|
||||
result.add_entry(info._ref_ptr, info._typed_ptr, info_type,
|
||||
now - info._time);
|
||||
}
|
||||
}
|
||||
@ -574,11 +664,12 @@ ns_get_pointers_of_age(MemoryUsagePointers &result,
|
||||
Table::iterator ti;
|
||||
for (ti = _table.begin(); ti != _table.end(); ++ti) {
|
||||
MemoryInfo &info = (*ti).second;
|
||||
if (info._freeze_index == _freeze_index) {
|
||||
if (info._freeze_index == _freeze_index &&
|
||||
info._ref_ptr != (ReferenceCount *)NULL) {
|
||||
double age = now - info._time;
|
||||
if ((age >= from && age <= to) ||
|
||||
(age >= to && age <= from)) {
|
||||
result.add_entry(info._ptr, info._typed_ptr, info.get_type(), age);
|
||||
result.add_entry(info._ref_ptr, info._typed_ptr, info.get_type(), age);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -616,10 +707,11 @@ ns_get_pointers_with_zero_count(MemoryUsagePointers &result) {
|
||||
Table::iterator ti;
|
||||
for (ti = _table.begin(); ti != _table.end(); ++ti) {
|
||||
MemoryInfo &info = (*ti).second;
|
||||
if (info._freeze_index == _freeze_index) {
|
||||
if ((*ti).first->get_ref_count() == 0) {
|
||||
(*ti).first->ref();
|
||||
result.add_entry(info._ptr, info._typed_ptr, info.get_type(),
|
||||
if (info._freeze_index == _freeze_index &&
|
||||
info._ref_ptr != (ReferenceCount *)NULL) {
|
||||
if (info._ref_ptr->get_ref_count() == 0) {
|
||||
info._ref_ptr->ref();
|
||||
result.add_entry(info._ref_ptr, info._typed_ptr, info.get_type(),
|
||||
now - info._time);
|
||||
}
|
||||
}
|
||||
@ -639,6 +731,7 @@ ns_get_pointers_with_zero_count(MemoryUsagePointers &result) {
|
||||
void MemoryUsage::
|
||||
ns_freeze() {
|
||||
_count = 0;
|
||||
_allocated_size = 0;
|
||||
_trend_types.clear();
|
||||
_trend_ages.clear();
|
||||
_freeze_index++;
|
||||
@ -658,7 +751,7 @@ ns_show_current_types() {
|
||||
for (ti = _table.begin(); ti != _table.end(); ++ti) {
|
||||
MemoryInfo &info = (*ti).second;
|
||||
if (info._freeze_index == _freeze_index) {
|
||||
hist.add_info(info.get_type());
|
||||
hist.add_info(info.get_type(), info);
|
||||
}
|
||||
}
|
||||
|
||||
@ -692,7 +785,7 @@ ns_show_current_ages() {
|
||||
for (ti = _table.begin(); ti != _table.end(); ++ti) {
|
||||
MemoryInfo &info = (*ti).second;
|
||||
if (info._freeze_index == _freeze_index) {
|
||||
hist.add_info(now - info._time);
|
||||
hist.add_info(now - info._time, info);
|
||||
}
|
||||
}
|
||||
|
||||
@ -711,6 +804,68 @@ ns_show_trend_ages() {
|
||||
_trend_ages.show();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MemoryUsage::consolidate_void_ptr
|
||||
// Access: Private
|
||||
// Description: If the size information has not yet been determined
|
||||
// for this pointer, checks to see if it has possible
|
||||
// been recorded under the TypedObject pointer (this
|
||||
// will happen when the class inherits from TypedObject
|
||||
// before ReferenceCount, e.g. TypedReferenceCount).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void MemoryUsage::
|
||||
consolidate_void_ptr(MemoryInfo &info) {
|
||||
if (info.is_size_known()) {
|
||||
// We already know the size, so no sweat.
|
||||
return;
|
||||
}
|
||||
|
||||
if (info.get_typed_ptr() == (TypedObject *)NULL) {
|
||||
// We don't have a typed pointer for this thing yet.
|
||||
return;
|
||||
}
|
||||
|
||||
void *typed_ptr = (void *)info.get_typed_ptr();
|
||||
|
||||
if (typed_ptr == (void *)info.get_ref_ptr()) {
|
||||
// The TypedObject pointer is the same pointer as the
|
||||
// ReferenceCount pointer, so there's no point in looking it up
|
||||
// separately. Actually, this really shouldn't even be possible.
|
||||
return;
|
||||
}
|
||||
|
||||
Table::iterator ti;
|
||||
ti = _table.find(typed_ptr);
|
||||
if (ti == _table.end()) {
|
||||
// No entry for the typed pointer, either.
|
||||
return;
|
||||
}
|
||||
|
||||
// We do have an entry! Copy over the relevant pieces.
|
||||
MemoryInfo &typed_info = (*ti).second;
|
||||
|
||||
if (typed_info.is_size_known()) {
|
||||
info._size = typed_info.get_size();
|
||||
info._flags |= MemoryInfo::F_size_known;
|
||||
if (typed_info._freeze_index == _freeze_index) {
|
||||
_allocated_size += info._size;
|
||||
}
|
||||
}
|
||||
|
||||
// The typed_ptr is clearly the more accurate pointer to the
|
||||
// beginning of the structure.
|
||||
info._void_ptr = typed_ptr;
|
||||
|
||||
// Now that we've consolidated the pointers, remove the void pointer
|
||||
// entry.
|
||||
if (info._freeze_index == _freeze_index) {
|
||||
_count--;
|
||||
_allocated_size -= info._size;
|
||||
}
|
||||
|
||||
|
||||
_table.erase(ti);
|
||||
}
|
||||
|
||||
|
||||
#endif // NDEBUG
|
||||
|
@ -22,6 +22,8 @@
|
||||
#include <pandabase.h>
|
||||
|
||||
#include "typedObject.h"
|
||||
#include "memoryInfo.h"
|
||||
#include "memoryUsagePointerCounts.h"
|
||||
|
||||
#include <map>
|
||||
|
||||
@ -42,7 +44,6 @@ class EXPCL_PANDAEXPRESS MemoryUsage {
|
||||
public:
|
||||
INLINE static bool get_track_memory_usage();
|
||||
|
||||
PUBLISHED:
|
||||
#if defined(__GNUC__) && !defined(NDEBUG)
|
||||
// There seems to be a problem with egcs-2.91.66: it gets confused
|
||||
// with too many nested inline functions, and sets the wrong pointer
|
||||
@ -62,7 +63,20 @@ PUBLISHED:
|
||||
INLINE static void remove_pointer(ReferenceCount *ptr);
|
||||
#endif // __GNUC__ && !NDEBUG
|
||||
|
||||
#ifndef NDEBUG
|
||||
#ifdef NDEBUG
|
||||
public:
|
||||
INLINE static bool is_tracking() { return false; }
|
||||
INLINE static size_t get_allocated_size() { return 0; }
|
||||
|
||||
#else // NDEBUG
|
||||
public:
|
||||
static void *operator_new_handler(size_t size);
|
||||
static void operator_delete_handler(void *ptr);
|
||||
|
||||
PUBLISHED:
|
||||
INLINE static bool is_tracking();
|
||||
INLINE static size_t get_allocated_size();
|
||||
INLINE static size_t get_total_size();
|
||||
INLINE static int get_num_pointers();
|
||||
INLINE static void get_pointers(MemoryUsagePointers &result);
|
||||
INLINE static void get_pointers_of_type(MemoryUsagePointers &result,
|
||||
@ -87,6 +101,11 @@ private:
|
||||
void ns_update_type(ReferenceCount *ptr, TypedObject *typed_ptr);
|
||||
void ns_remove_pointer(ReferenceCount *ptr);
|
||||
|
||||
void ns_record_void_pointer(void *ptr, size_t size);
|
||||
void ns_remove_void_pointer(void *ptr);
|
||||
|
||||
size_t ns_get_allocated_size();
|
||||
size_t ns_get_total_size();
|
||||
int ns_get_num_pointers();
|
||||
void ns_get_pointers(MemoryUsagePointers &result);
|
||||
void ns_get_pointers_of_type(MemoryUsagePointers &result,
|
||||
@ -101,38 +120,25 @@ private:
|
||||
void ns_show_current_ages();
|
||||
void ns_show_trend_ages();
|
||||
|
||||
void consolidate_void_ptr(MemoryInfo &info);
|
||||
|
||||
static MemoryUsage *_global_ptr;
|
||||
|
||||
class MemoryInfo {
|
||||
public:
|
||||
TypeHandle get_type();
|
||||
void determine_dynamic_type();
|
||||
void update_type_handle(TypeHandle &destination, TypeHandle refined);
|
||||
|
||||
ReferenceCount *_ptr;
|
||||
TypedObject *_typed_ptr;
|
||||
TypeHandle _static_type;
|
||||
TypeHandle _dynamic_type;
|
||||
|
||||
double _time;
|
||||
int _freeze_index;
|
||||
bool _reconsider_dynamic_type;
|
||||
};
|
||||
|
||||
typedef map<ReferenceCount *, MemoryInfo> Table;
|
||||
typedef map<void *, MemoryInfo> Table;
|
||||
Table _table;
|
||||
int _freeze_index;
|
||||
int _count;
|
||||
|
||||
size_t _allocated_size;
|
||||
size_t _total_size;
|
||||
|
||||
class TypeHistogram {
|
||||
public:
|
||||
void add_info(TypeHandle type);
|
||||
void add_info(TypeHandle type, MemoryInfo &info);
|
||||
void show() const;
|
||||
void clear();
|
||||
|
||||
private:
|
||||
typedef map<TypeHandle, int> Counts;
|
||||
typedef map<TypeHandle, MemoryUsagePointerCounts> Counts;
|
||||
Counts _counts;
|
||||
};
|
||||
TypeHistogram _trend_types;
|
||||
@ -140,7 +146,7 @@ private:
|
||||
class AgeHistogram {
|
||||
public:
|
||||
AgeHistogram();
|
||||
void add_info(double age);
|
||||
void add_info(double age, MemoryInfo &info);
|
||||
void show() const;
|
||||
void clear();
|
||||
|
||||
@ -148,7 +154,7 @@ private:
|
||||
int choose_bucket(double age) const;
|
||||
|
||||
enum { num_buckets = 5 };
|
||||
int _counts[num_buckets];
|
||||
MemoryUsagePointerCounts _counts[num_buckets];
|
||||
static double _cutoff[num_buckets];
|
||||
};
|
||||
AgeHistogram _trend_ages;
|
||||
@ -156,7 +162,7 @@ private:
|
||||
|
||||
bool _track_memory_usage;
|
||||
|
||||
#endif
|
||||
#endif // NDEBUG
|
||||
};
|
||||
|
||||
#include "memoryUsage.I"
|
||||
|
128
panda/src/express/memoryUsagePointerCounts.I
Normal file
128
panda/src/express/memoryUsagePointerCounts.I
Normal file
@ -0,0 +1,128 @@
|
||||
// Filename: memoryUsagePointerCounts.I
|
||||
// Created by: drose (04Jun01)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MemoryUsagePointerCounts::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE MemoryUsagePointerCounts::
|
||||
MemoryUsagePointerCounts() {
|
||||
_count = 0;
|
||||
_unknown_size_count = 0;
|
||||
_size = 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MemoryUsagePointerCounts::Copy Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE MemoryUsagePointerCounts::
|
||||
MemoryUsagePointerCounts(const MemoryUsagePointerCounts ©) :
|
||||
_count(copy._count),
|
||||
_unknown_size_count(copy._unknown_size_count),
|
||||
_size(copy._size)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MemoryUsagePointerCounts::Copy Assignment
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void MemoryUsagePointerCounts::
|
||||
operator = (const MemoryUsagePointerCounts ©) {
|
||||
_count = copy._count;
|
||||
_unknown_size_count = copy._unknown_size_count;
|
||||
_size = copy._size;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MemoryUsagePointerCounts::clear
|
||||
// Access: Public
|
||||
// Description: Resets the counter to empty.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void MemoryUsagePointerCounts::
|
||||
clear() {
|
||||
_count = 0;
|
||||
_unknown_size_count = 0;
|
||||
_size = 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MemoryUsagePointerCounts::is_size_unknown
|
||||
// Access: Public
|
||||
// Description: Returns true if none of the pointers in the count
|
||||
// have a known size, or false if at least one of them
|
||||
// does.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool MemoryUsagePointerCounts::
|
||||
is_size_unknown() const {
|
||||
return _unknown_size_count == _count;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MemoryUsagePointerCounts::get_size
|
||||
// Access: Public
|
||||
// Description: Returns the total allocated size of all pointers in
|
||||
// the count whose size is known.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE size_t MemoryUsagePointerCounts::
|
||||
get_size() const {
|
||||
return _size;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MemoryUsagePointerCounts::get_count
|
||||
// Access: Public
|
||||
// Description: Returns the total number of pointers in the count.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE int MemoryUsagePointerCounts::
|
||||
get_count() const {
|
||||
return _count;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MemoryUsagePointerCounts::Ordering Operator
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool MemoryUsagePointerCounts::
|
||||
operator < (const MemoryUsagePointerCounts &other) const {
|
||||
if (is_size_unknown() != other.is_size_unknown()) {
|
||||
return is_size_unknown() > other.is_size_unknown();
|
||||
}
|
||||
|
||||
if (get_size() != other.get_size()) {
|
||||
return get_size() < other.get_size();
|
||||
}
|
||||
|
||||
if (get_count() != other.get_count()) {
|
||||
return get_count() != other.get_count();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
INLINE ostream &
|
||||
operator << (ostream &out, const MemoryUsagePointerCounts &c) {
|
||||
c.output(out);
|
||||
return out;
|
||||
}
|
77
panda/src/express/memoryUsagePointerCounts.cxx
Normal file
77
panda/src/express/memoryUsagePointerCounts.cxx
Normal file
@ -0,0 +1,77 @@
|
||||
// Filename: memoryUsagePointerCounts.cxx
|
||||
// Created by: drose (04Jun01)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#include "memoryUsagePointerCounts.h"
|
||||
#include "memoryInfo.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MemoryUsagePointerCounts::add_info
|
||||
// Access: Public
|
||||
// Description: Adds a pointer definition to the counter.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void MemoryUsagePointerCounts::
|
||||
add_info(MemoryInfo &info) {
|
||||
_count++;
|
||||
|
||||
if (info.is_size_known()) {
|
||||
_size += info.get_size();
|
||||
} else {
|
||||
_unknown_size_count++;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MemoryUsagePointerCounts::output
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void MemoryUsagePointerCounts::
|
||||
output(ostream &out) const {
|
||||
out << _count << " pointers";
|
||||
if (_unknown_size_count < _count) {
|
||||
out << ", ";
|
||||
output_bytes(out, _size);
|
||||
out << ", ";
|
||||
output_bytes(out, _size / (_count - _unknown_size_count));
|
||||
out << " each";
|
||||
|
||||
if (_unknown_size_count != 0) {
|
||||
out << " (" << _unknown_size_count << " of unknown size)";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MemoryUsagePointerCounts::output_bytes
|
||||
// Access: Private, Static
|
||||
// Description: Formats a size in bytes in a meaningful and concise
|
||||
// way for output, with units.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void MemoryUsagePointerCounts::
|
||||
output_bytes(ostream &out, size_t size) {
|
||||
if (size < 4 * 1024) {
|
||||
out << size << " bytes";
|
||||
|
||||
} else if (size < 4 * 1024 * 1024) {
|
||||
out << size / 1024 << " Kb";
|
||||
|
||||
} else {
|
||||
out << size / (1024 * 1024) << " Mb";
|
||||
}
|
||||
}
|
67
panda/src/express/memoryUsagePointerCounts.h
Normal file
67
panda/src/express/memoryUsagePointerCounts.h
Normal file
@ -0,0 +1,67 @@
|
||||
// Filename: memoryUsagePointerCounts.h
|
||||
// Created by: drose (04Jun01)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef MEMORYUSAGEPOINTERCOUNTS_H
|
||||
#define MEMORYUSAGEPOINTERCOUNTS_H
|
||||
|
||||
#include <pandabase.h>
|
||||
|
||||
class MemoryInfo;
|
||||
|
||||
#ifndef NDEBUG
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : MemoryUsagePointerCounts
|
||||
// Description : This is a supporting class for MemoryUsage. It
|
||||
// tracks the relative counts of a number of pointers of
|
||||
// some type (or age), for use by TypeHistogram and
|
||||
// AgeHistogram. It's not exported from the DLL, and it
|
||||
// doesn't even exist if we're compiling NDEBUG.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class MemoryUsagePointerCounts {
|
||||
public:
|
||||
INLINE MemoryUsagePointerCounts();
|
||||
INLINE MemoryUsagePointerCounts(const MemoryUsagePointerCounts ©);
|
||||
INLINE void operator = (const MemoryUsagePointerCounts ©);
|
||||
|
||||
INLINE void clear();
|
||||
void add_info(MemoryInfo &info);
|
||||
void output(ostream &out) const;
|
||||
|
||||
INLINE bool is_size_unknown() const;
|
||||
INLINE size_t get_size() const;
|
||||
INLINE int get_count() const;
|
||||
|
||||
INLINE bool operator < (const MemoryUsagePointerCounts &other) const;
|
||||
|
||||
private:
|
||||
static void output_bytes(ostream &out, size_t size);
|
||||
|
||||
private:
|
||||
int _count;
|
||||
int _unknown_size_count;
|
||||
size_t _size;
|
||||
};
|
||||
|
||||
INLINE ostream &operator << (ostream &out, const MemoryUsagePointerCounts &c);
|
||||
|
||||
#include "memoryUsagePointerCounts.I"
|
||||
|
||||
#endif // NDEBUG
|
||||
|
||||
#endif
|
||||
|
@ -22,14 +22,14 @@
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE MemoryUsagePointers::Entry::
|
||||
Entry(ReferenceCount *ptr, TypedObject *typed_ptr,
|
||||
Entry(ReferenceCount *ref_ptr, TypedObject *typed_ptr,
|
||||
TypeHandle type, double age) :
|
||||
_ptr(ptr),
|
||||
_ref_ptr(ref_ptr),
|
||||
_typed_ptr(typed_ptr),
|
||||
_type(type),
|
||||
_age(age)
|
||||
{
|
||||
_ptr->ref();
|
||||
_ref_ptr->ref();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -39,12 +39,12 @@ Entry(ReferenceCount *ptr, TypedObject *typed_ptr,
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE MemoryUsagePointers::Entry::
|
||||
Entry(const Entry ©) :
|
||||
_ptr(copy._ptr),
|
||||
_ref_ptr(copy._ref_ptr),
|
||||
_typed_ptr(copy._typed_ptr),
|
||||
_type(copy._type),
|
||||
_age(copy._age)
|
||||
{
|
||||
_ptr->ref();
|
||||
_ref_ptr->ref();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -54,12 +54,12 @@ Entry(const Entry ©) :
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void MemoryUsagePointers::Entry::
|
||||
operator = (const Entry ©) {
|
||||
if (_ptr != copy._ptr) {
|
||||
_ptr->unref();
|
||||
_ptr = copy._ptr;
|
||||
if (_ref_ptr != copy._ref_ptr) {
|
||||
_ref_ptr->unref();
|
||||
_ref_ptr = copy._ref_ptr;
|
||||
// We can't call unref_delete(), because we don't know what kind
|
||||
// of pointer it is precisely. Potential leak.
|
||||
_ptr->ref();
|
||||
_ref_ptr->ref();
|
||||
}
|
||||
_typed_ptr = copy._typed_ptr;
|
||||
_type = copy._type;
|
||||
@ -75,6 +75,6 @@ INLINE MemoryUsagePointers::Entry::
|
||||
~Entry() {
|
||||
// We can't call unref_delete(), because we don't know what kind
|
||||
// of pointer it is precisely. Potential leak.
|
||||
_ptr->unref();
|
||||
_ref_ptr->unref();
|
||||
}
|
||||
|
||||
|
@ -78,7 +78,7 @@ get_num_pointers() const {
|
||||
ReferenceCount *MemoryUsagePointers::
|
||||
get_pointer(int n) const {
|
||||
nassertr(n >= 0 && n < get_num_pointers(), NULL);
|
||||
return _entries[n]._ptr;
|
||||
return _entries[n]._ref_ptr;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -98,7 +98,7 @@ get_typed_pointer(int n) const {
|
||||
return typed_ptr;
|
||||
}
|
||||
|
||||
ReferenceCount *ptr = _entries[n]._ptr;
|
||||
ReferenceCount *ref_ptr = _entries[n]._ref_ptr;
|
||||
|
||||
TypeHandle type = _entries[n]._type;
|
||||
|
||||
@ -116,7 +116,7 @@ get_typed_pointer(int n) const {
|
||||
|
||||
if (type != TypeHandle::none() &&
|
||||
type.is_derived_from(TypedReferenceCount::get_class_type())) {
|
||||
return (TypedReferenceCount *)ptr;
|
||||
return (TypedReferenceCount *)ref_ptr;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
@ -176,13 +176,13 @@ clear() {
|
||||
// only by MemoryUsage.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void MemoryUsagePointers::
|
||||
add_entry(ReferenceCount *ptr, TypedObject *typed_ptr,
|
||||
add_entry(ReferenceCount *ref_ptr, TypedObject *typed_ptr,
|
||||
TypeHandle type, double age) {
|
||||
// We can't safly add pointers with a zero reference count. They
|
||||
// might be statically-allocated or something, and if we try to add
|
||||
// them they'll try to destruct when the PointerTo later goes away.
|
||||
if (ptr->get_ref_count() != 0) {
|
||||
_entries.push_back(Entry(ptr, typed_ptr, type, age));
|
||||
if (ref_ptr->get_ref_count() != 0) {
|
||||
_entries.push_back(Entry(ref_ptr, typed_ptr, type, age));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -64,12 +64,12 @@ PUBLISHED:
|
||||
void clear();
|
||||
|
||||
private:
|
||||
void add_entry(ReferenceCount *ptr, TypedObject *typed_ptr,
|
||||
void add_entry(ReferenceCount *ref_ptr, TypedObject *typed_ptr,
|
||||
TypeHandle type, double age);
|
||||
|
||||
class Entry {
|
||||
public:
|
||||
INLINE Entry(ReferenceCount *ptr, TypedObject *typed_ptr,
|
||||
INLINE Entry(ReferenceCount *ref_ptr, TypedObject *typed_ptr,
|
||||
TypeHandle type, double age);
|
||||
INLINE Entry(const Entry ©);
|
||||
INLINE void operator = (const Entry ©);
|
||||
@ -80,7 +80,7 @@ private:
|
||||
// (since ReferenceCount has no public destructor). If we can't
|
||||
// delete it, we can't make a PointerTo it, since PointerTo wants
|
||||
// to be able to delete things.
|
||||
ReferenceCount *_ptr;
|
||||
ReferenceCount *_ref_ptr;
|
||||
TypedObject *_typed_ptr;
|
||||
TypeHandle _type;
|
||||
double _age;
|
||||
|
@ -118,7 +118,7 @@ private:
|
||||
// only works when the base type is, in fact, a class.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class Base>
|
||||
class EXPCL_PANDAEXPRESS RefCountObj : public Base, public ReferenceCount {
|
||||
class EXPCL_PANDAEXPRESS RefCountObj : public ReferenceCount, public Base {
|
||||
public:
|
||||
INLINE RefCountObj();
|
||||
INLINE RefCountObj(const Base ©);
|
||||
|
@ -495,9 +495,7 @@ render_frame(const AllAttributesWrapper &initial_state) {
|
||||
// texture state has changed, we have to be sure to clear the
|
||||
// current texture state now. A bit unfortunate, but probably not
|
||||
// measurably expensive.
|
||||
NodeAttributes state;
|
||||
state.set_attribute(TextureTransition::get_class_type(), new TextureAttribute);
|
||||
set_state(state, false);
|
||||
clear_attribute(TextureTransition::get_class_type());
|
||||
#endif
|
||||
|
||||
if (_clear_buffer_type != 0) {
|
||||
@ -558,9 +556,7 @@ render_frame(const AllAttributesWrapper &initial_state) {
|
||||
// Also force the lighting state to unlit, so that issue_light()
|
||||
// will be guaranteed to be called next frame even if we have the
|
||||
// same set of light pointers we had this frame.
|
||||
NodeAttributes state;
|
||||
state.set_attribute(LightTransition::get_class_type(), new LightAttribute);
|
||||
set_state(state, false);
|
||||
clear_attribute(LightTransition::get_class_type());
|
||||
|
||||
// All this work to undo the lighting state each frame doesn't seem
|
||||
// ideal--there may be a better way. Maybe if the lights were just
|
||||
@ -1997,15 +1993,11 @@ copy_pixel_buffer(PixelBuffer *pb, const DisplayRegion *dr) {
|
||||
// activate();
|
||||
set_pack_alignment(1);
|
||||
|
||||
NodeAttributes state;
|
||||
|
||||
// Bug fix for RE, RE2, and VTX - need to disable texturing in order
|
||||
// for glReadPixels() to work
|
||||
// NOTE: reading the depth buffer is *much* slower than reading the
|
||||
// color buffer
|
||||
state.set_attribute(TextureTransition::get_class_type(),
|
||||
new TextureAttribute);
|
||||
set_state(state, false);
|
||||
clear_attribute(TextureTransition::get_class_type());
|
||||
|
||||
int xo, yo, w, h;
|
||||
dr->get_region_pixels(xo, yo, w, h);
|
||||
|
@ -77,6 +77,16 @@ insert(NodeAttributes::iterator position,
|
||||
return _attributes.insert(position, x);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NodeAttributes::find
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE_GRAPH NodeAttributes::iterator NodeAttributes::
|
||||
find(const key_type &k) {
|
||||
return _attributes.find(k);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NodeAttributes::erase
|
||||
// Access: Public
|
||||
|
@ -64,6 +64,7 @@ public:
|
||||
// of PANDA.DLL.
|
||||
typedef Attributes::iterator iterator;
|
||||
typedef Attributes::const_iterator const_iterator;
|
||||
typedef Attributes::key_type key_type;
|
||||
typedef Attributes::value_type value_type;
|
||||
typedef Attributes::size_type size_type;
|
||||
|
||||
@ -73,6 +74,7 @@ public:
|
||||
INLINE_GRAPH const_iterator begin() const;
|
||||
INLINE_GRAPH const_iterator end() const;
|
||||
INLINE_GRAPH iterator insert(iterator position, const value_type &x);
|
||||
INLINE_GRAPH iterator find(const key_type &k);
|
||||
INLINE_GRAPH void erase(iterator position);
|
||||
|
||||
public:
|
||||
|
@ -289,6 +289,21 @@ get_last_update() const {
|
||||
return _last_update;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NodeRelation::clear_wrt_cache
|
||||
// Access: Public
|
||||
// Description: Blows away the wrt cache information on this arc.
|
||||
// This forces the wrt to be recomputed next time it is
|
||||
// asked for.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE_GRAPH void NodeRelation::
|
||||
clear_wrt_cache() {
|
||||
_net_transitions.clear();
|
||||
_top_subtree = (Node *)NULL;
|
||||
_all_verified = UpdateSeq::initial();
|
||||
_last_update = ++last_graph_update(_graph_type);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NodeRelation::create_typed_arc
|
||||
// Access: Public, Static
|
||||
|
@ -122,6 +122,7 @@ PUBLISHED:
|
||||
INLINE_GRAPH int compare_transitions_to(const NodeRelation *arc) const;
|
||||
|
||||
INLINE_GRAPH UpdateSeq get_last_update() const;
|
||||
INLINE_GRAPH void clear_wrt_cache();
|
||||
|
||||
public:
|
||||
bool sub_render_trans(const AllAttributesWrapper &attrib,
|
||||
|
@ -39,6 +39,10 @@
|
||||
|
||||
PStatClient *PStatClient::_global_pstats = NULL;
|
||||
|
||||
#ifndef CPPPARSER
|
||||
PStatCollector _memory_usage_pcollector("Panda memory usage");
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatClient::PerThreadData::Constructor
|
||||
// Access: Public
|
||||
@ -363,6 +367,14 @@ make_thread(const string &name) {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PStatClient::
|
||||
main_tick() {
|
||||
// We have code here to report the memory usage. We can't put this
|
||||
// code inside the MemoryUsage class, where it fits a little better,
|
||||
// simply because MemoryUsage is a very low-level class that doesn't
|
||||
// know about PStatClient.
|
||||
if (MemoryUsage::is_tracking()) {
|
||||
_memory_usage_pcollector.set_level(MemoryUsage::get_total_size());
|
||||
}
|
||||
|
||||
get_global_pstats()->get_main_thread().new_frame();
|
||||
}
|
||||
|
||||
|
@ -147,6 +147,7 @@ static LevelCollectorProperties level_properties[] = {
|
||||
{ 1, "State changes", { 1.0, 0.5, 0.2 }, "", 500.0 },
|
||||
{ 1, "State changes:Transforms", { 0.2, 0.2, 0.8 }, },
|
||||
{ 1, "State changes:Textures", { 0.8, 0.2, 0.2 }, },
|
||||
{ 1, "Panda memory usage", { 0.8, 0.2, 0.5 }, "MB", 64, 1048576 },
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
|
@ -17,10 +17,10 @@
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<class Element>
|
||||
vector<Element> PointerToArray<Element>::_empty_array;
|
||||
pvector<Element> PointerToArray<Element>::_empty_array;
|
||||
|
||||
template<class Element>
|
||||
vector<Element> ConstPointerToArray<Element>::_empty_array;
|
||||
pvector<Element> ConstPointerToArray<Element>::_empty_array;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PointerToArray::Constructor
|
||||
@ -30,7 +30,7 @@ vector<Element> ConstPointerToArray<Element>::_empty_array;
|
||||
template<class Element>
|
||||
INLINE PointerToArray<Element>::
|
||||
PointerToArray() :
|
||||
PointerToBase<RefCountObj<vector<Element> > >((RefCountObj<vector<Element> > *)NULL)
|
||||
PointerToBase<RefCountObj<pvector<Element> > >((RefCountObj<pvector<Element> > *)NULL)
|
||||
{
|
||||
}
|
||||
|
||||
@ -42,7 +42,7 @@ PointerToArray() :
|
||||
template<class Element>
|
||||
INLINE PointerToArray<Element>::
|
||||
PointerToArray(size_type n) :
|
||||
PointerToBase<RefCountObj<vector<Element> > >(new RefCountObj<vector<Element> >) {
|
||||
PointerToBase<RefCountObj<pvector<Element> > >(new RefCountObj<pvector<Element> >) {
|
||||
_ptr->reserve(n);
|
||||
insert(begin(), n, Element());
|
||||
}
|
||||
@ -55,7 +55,7 @@ PointerToArray(size_type n) :
|
||||
template<class Element>
|
||||
INLINE PointerToArray<Element>::
|
||||
PointerToArray(size_type n, const Element &value) :
|
||||
PointerToBase<RefCountObj<vector<Element> > >(new RefCountObj<vector<Element> >) {
|
||||
PointerToBase<RefCountObj<pvector<Element> > >(new RefCountObj<pvector<Element> >) {
|
||||
_ptr->reserve(n);
|
||||
insert(begin(), n, value);
|
||||
}
|
||||
@ -68,7 +68,7 @@ PointerToArray(size_type n, const Element &value) :
|
||||
template<class Element>
|
||||
INLINE PointerToArray<Element>::
|
||||
PointerToArray(const PointerToArray<Element> ©) :
|
||||
PointerToBase<RefCountObj<vector<Element> > >(copy)
|
||||
PointerToBase<RefCountObj<pvector<Element> > >(copy)
|
||||
{
|
||||
}
|
||||
|
||||
@ -148,7 +148,7 @@ template<class Element>
|
||||
INLINE PointerToArray<Element>::size_type PointerToArray<Element>::
|
||||
max_size() const {
|
||||
nassertd(_ptr != NULL) {
|
||||
((PointerToArray<Element> *)this)->reassign(new RefCountObj<vector<Element> >);
|
||||
((PointerToArray<Element> *)this)->reassign(new RefCountObj<pvector<Element> >);
|
||||
}
|
||||
return _ptr->max_size();
|
||||
}
|
||||
@ -173,7 +173,7 @@ template<class Element>
|
||||
INLINE void PointerToArray<Element>::
|
||||
reserve(PointerToArray<Element>::size_type n) {
|
||||
if (_ptr == NULL) {
|
||||
reassign(new RefCountObj<vector<Element> >);
|
||||
reassign(new RefCountObj<pvector<Element> >);
|
||||
}
|
||||
_ptr->reserve(n);
|
||||
}
|
||||
@ -199,7 +199,7 @@ template<class Element>
|
||||
INLINE PointerToArray<Element>::reference PointerToArray<Element>::
|
||||
front() const {
|
||||
nassertd(_ptr != NULL) {
|
||||
((PointerToArray<Element> *)this)->reassign(new RefCountObj<vector<Element> >);
|
||||
((PointerToArray<Element> *)this)->reassign(new RefCountObj<pvector<Element> >);
|
||||
}
|
||||
nassertd(!_ptr->empty()) {
|
||||
_ptr->push_back(Element());
|
||||
@ -216,7 +216,7 @@ template<class Element>
|
||||
INLINE PointerToArray<Element>::reference PointerToArray<Element>::
|
||||
back() const {
|
||||
nassertd(_ptr != NULL) {
|
||||
((PointerToArray<Element> *)this)->reassign(new RefCountObj<vector<Element> >);
|
||||
((PointerToArray<Element> *)this)->reassign(new RefCountObj<pvector<Element> >);
|
||||
}
|
||||
nassertd(!_ptr->empty()) {
|
||||
_ptr->push_back(Element());
|
||||
@ -261,7 +261,7 @@ template<class Element>
|
||||
INLINE void PointerToArray<Element>::
|
||||
erase(iterator position) const {
|
||||
nassertd(_ptr != NULL) {
|
||||
((PointerToArray<Element> *)this)->reassign(new RefCountObj<vector<Element> >);
|
||||
((PointerToArray<Element> *)this)->reassign(new RefCountObj<pvector<Element> >);
|
||||
}
|
||||
nassertv(position >= _ptr->begin() &&
|
||||
position <= _ptr->end());
|
||||
@ -277,7 +277,7 @@ template<class Element>
|
||||
INLINE void PointerToArray<Element>::
|
||||
erase(iterator first, iterator last) const {
|
||||
nassertd(_ptr != NULL) {
|
||||
((PointerToArray<Element> *)this)->reassign(new RefCountObj<vector<Element> >);
|
||||
((PointerToArray<Element> *)this)->reassign(new RefCountObj<pvector<Element> >);
|
||||
}
|
||||
nassertv(first >= _ptr->begin() && first <= _ptr->end());
|
||||
nassertv(last >= _ptr->begin() && last <= _ptr->end());
|
||||
@ -294,7 +294,7 @@ template<class Element>
|
||||
INLINE PointerToArray<Element>::reference PointerToArray<Element>::
|
||||
operator [](size_type n) const {
|
||||
nassertd(_ptr != NULL) {
|
||||
((PointerToArray<Element> *)this)->reassign(new RefCountObj<vector<Element> >);
|
||||
((PointerToArray<Element> *)this)->reassign(new RefCountObj<pvector<Element> >);
|
||||
}
|
||||
nassertd(!_ptr->empty()) {
|
||||
_ptr->push_back(Element());
|
||||
@ -313,7 +313,7 @@ template<class Element>
|
||||
INLINE void PointerToArray<Element>::
|
||||
push_back(const Element &x) {
|
||||
if (_ptr == NULL) {
|
||||
reassign(new RefCountObj<vector<Element> >);
|
||||
reassign(new RefCountObj<pvector<Element> >);
|
||||
}
|
||||
_ptr->push_back(x);
|
||||
}
|
||||
@ -327,7 +327,7 @@ template<class Element>
|
||||
INLINE void PointerToArray<Element>::
|
||||
pop_back() {
|
||||
nassertd(_ptr != NULL) {
|
||||
((PointerToArray<Element> *)this)->reassign(new RefCountObj<vector<Element> >);
|
||||
((PointerToArray<Element> *)this)->reassign(new RefCountObj<pvector<Element> >);
|
||||
}
|
||||
nassertv(!_ptr->empty());
|
||||
_ptr->pop_back();
|
||||
@ -344,7 +344,7 @@ template<class Element>
|
||||
INLINE void PointerToArray<Element>::
|
||||
make_empty() {
|
||||
nassertd(_ptr != NULL) {
|
||||
((PointerToArray<Element> *)this)->reassign(new RefCountObj<vector<Element> >);
|
||||
((PointerToArray<Element> *)this)->reassign(new RefCountObj<pvector<Element> >);
|
||||
}
|
||||
nassertv(!_ptr->empty());
|
||||
_ptr->clear();
|
||||
@ -385,10 +385,10 @@ p() const {
|
||||
// with some of the vector's esoteric functionality.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class Element>
|
||||
INLINE vector<Element> &PointerToArray<Element>::
|
||||
INLINE pvector<Element> &PointerToArray<Element>::
|
||||
v() const {
|
||||
nassertd(_ptr != NULL) {
|
||||
((PointerToArray<Element> *)this)->reassign(new RefCountObj<vector<Element> >);
|
||||
((PointerToArray<Element> *)this)->reassign(new RefCountObj<pvector<Element> >);
|
||||
}
|
||||
return *_ptr;
|
||||
}
|
||||
@ -403,7 +403,7 @@ template<class Element>
|
||||
INLINE void* PointerToArray<Element>::
|
||||
get_void_ptr() const
|
||||
{
|
||||
return PointerToBase<RefCountObj<vector<Element> > >::_ptr;
|
||||
return PointerToBase<RefCountObj<pvector<Element> > >::_ptr;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -415,7 +415,7 @@ template<class Element>
|
||||
INLINE void PointerToArray<Element>::
|
||||
set_void_ptr(void* p)
|
||||
{
|
||||
reassign((RefCountObj<vector<Element> > *)p);
|
||||
reassign((RefCountObj<pvector<Element> > *)p);
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PointerToArray::get_ref_count
|
||||
@ -435,7 +435,7 @@ get_ref_count() const {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class Element>
|
||||
INLINE PointerToArray<Element> &PointerToArray<Element>::
|
||||
operator = (RefCountObj<vector<Element> > *ptr) {
|
||||
operator = (RefCountObj<pvector<Element> > *ptr) {
|
||||
reassign(ptr);
|
||||
return *this;
|
||||
}
|
||||
@ -462,7 +462,7 @@ operator = (const PointerToArray<Element> ©) {
|
||||
template<class Element>
|
||||
INLINE void PointerToArray<Element>::
|
||||
clear() {
|
||||
reassign((RefCountObj<vector<Element> > *)NULL);
|
||||
reassign((RefCountObj<pvector<Element> > *)NULL);
|
||||
}
|
||||
|
||||
|
||||
@ -475,7 +475,7 @@ clear() {
|
||||
template<class Element>
|
||||
INLINE ConstPointerToArray<Element>::
|
||||
ConstPointerToArray() :
|
||||
PointerToBase<RefCountObj<vector<Element> > >((RefCountObj<vector<Element> > *)NULL)
|
||||
PointerToBase<RefCountObj<pvector<Element> > >((RefCountObj<pvector<Element> > *)NULL)
|
||||
{
|
||||
}
|
||||
|
||||
@ -487,7 +487,7 @@ ConstPointerToArray() :
|
||||
template<class Element>
|
||||
INLINE ConstPointerToArray<Element>::
|
||||
ConstPointerToArray(const PointerToArray<Element> ©) :
|
||||
PointerToBase<RefCountObj<vector<Element> > >(copy)
|
||||
PointerToBase<RefCountObj<pvector<Element> > >(copy)
|
||||
{
|
||||
}
|
||||
|
||||
@ -499,7 +499,7 @@ ConstPointerToArray(const PointerToArray<Element> ©) :
|
||||
template<class Element>
|
||||
INLINE ConstPointerToArray<Element>::
|
||||
ConstPointerToArray(const ConstPointerToArray<Element> ©) :
|
||||
PointerToBase<RefCountObj<vector<Element> > >(copy)
|
||||
PointerToBase<RefCountObj<pvector<Element> > >(copy)
|
||||
{
|
||||
}
|
||||
|
||||
@ -579,7 +579,7 @@ template<class Element>
|
||||
INLINE ConstPointerToArray<Element>::size_type ConstPointerToArray<Element>::
|
||||
max_size() const {
|
||||
nassertd(_ptr != NULL) {
|
||||
((ConstPointerToArray<Element> *)this)->reassign(new RefCountObj<vector<Element> >);
|
||||
((ConstPointerToArray<Element> *)this)->reassign(new RefCountObj<pvector<Element> >);
|
||||
}
|
||||
return _ptr->max_size();
|
||||
}
|
||||
@ -604,7 +604,7 @@ template<class Element>
|
||||
INLINE ConstPointerToArray<Element>::size_type ConstPointerToArray<Element>::
|
||||
capacity() const {
|
||||
nassertd(_ptr != NULL) {
|
||||
((ConstPointerToArray<Element> *)this)->reassign(new RefCountObj<vector<Element> >);
|
||||
((ConstPointerToArray<Element> *)this)->reassign(new RefCountObj<pvector<Element> >);
|
||||
}
|
||||
return _ptr->capacity();
|
||||
}
|
||||
@ -619,7 +619,7 @@ template<class Element>
|
||||
INLINE ConstPointerToArray<Element>::reference ConstPointerToArray<Element>::
|
||||
operator[](size_type n) const {
|
||||
nassertd(_ptr != NULL) {
|
||||
((ConstPointerToArray<Element> *)this)->reassign(new RefCountObj<vector<Element> >);
|
||||
((ConstPointerToArray<Element> *)this)->reassign(new RefCountObj<pvector<Element> >);
|
||||
}
|
||||
nassertd(!_ptr->empty()) {
|
||||
_ptr->push_back(Element());
|
||||
@ -638,7 +638,7 @@ template<class Element>
|
||||
INLINE ConstPointerToArray<Element>::reference ConstPointerToArray<Element>::
|
||||
front() const {
|
||||
nassertd(_ptr != NULL) {
|
||||
((ConstPointerToArray<Element> *)this)->reassign(new RefCountObj<vector<Element> >);
|
||||
((ConstPointerToArray<Element> *)this)->reassign(new RefCountObj<pvector<Element> >);
|
||||
}
|
||||
nassertd(!_ptr->empty()) {
|
||||
_ptr->push_back(Element());
|
||||
@ -655,7 +655,7 @@ template<class Element>
|
||||
INLINE ConstPointerToArray<Element>::reference ConstPointerToArray<Element>::
|
||||
back() const {
|
||||
nassertd(_ptr != NULL) {
|
||||
((ConstPointerToArray<Element> *)this)->reassign(new RefCountObj<vector<Element> >);
|
||||
((ConstPointerToArray<Element> *)this)->reassign(new RefCountObj<pvector<Element> >);
|
||||
}
|
||||
nassertd(!_ptr->empty()) {
|
||||
_ptr->push_back(Element());
|
||||
@ -698,10 +698,10 @@ p() const {
|
||||
// with some of the vector's esoteric functionality.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class Element>
|
||||
INLINE const vector<Element> &ConstPointerToArray<Element>::
|
||||
INLINE const pvector<Element> &ConstPointerToArray<Element>::
|
||||
v() const {
|
||||
nassertd(_ptr != NULL) {
|
||||
((ConstPointerToArray<Element> *)this)->reassign(new RefCountObj<vector<Element> >);
|
||||
((ConstPointerToArray<Element> *)this)->reassign(new RefCountObj<pvector<Element> >);
|
||||
}
|
||||
return *_ptr;
|
||||
}
|
||||
@ -724,7 +724,7 @@ get_ref_count() const {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class Element>
|
||||
INLINE ConstPointerToArray<Element> &ConstPointerToArray<Element>::
|
||||
operator = (RefCountObj<vector<Element> > *ptr) {
|
||||
operator = (RefCountObj<pvector<Element> > *ptr) {
|
||||
reassign(ptr);
|
||||
return *this;
|
||||
}
|
||||
@ -763,6 +763,6 @@ operator = (const ConstPointerToArray<Element> ©) {
|
||||
template<class Element>
|
||||
INLINE void ConstPointerToArray<Element>::
|
||||
clear() {
|
||||
reassign((RefCountObj<vector<Element> > *)NULL);
|
||||
reassign((RefCountObj<pvector<Element> > *)NULL);
|
||||
}
|
||||
|
||||
|
@ -72,8 +72,7 @@
|
||||
|
||||
#include "referenceCount.h"
|
||||
#include "pointerTo.h"
|
||||
|
||||
#include <vector>
|
||||
#include "pvector.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : PointerToArray
|
||||
@ -84,17 +83,17 @@
|
||||
// with a reference count.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template <class Element>
|
||||
class PointerToArray : public PointerToBase<RefCountObj<vector<Element> > > {
|
||||
class PointerToArray : public PointerToBase<RefCountObj<pvector<Element> > > {
|
||||
public:
|
||||
typedef vector<Element>::value_type value_type;
|
||||
typedef vector<Element>::reference reference;
|
||||
typedef vector<Element>::const_reference const_reference;
|
||||
typedef vector<Element>::iterator iterator;
|
||||
typedef vector<Element>::const_iterator const_iterator;
|
||||
typedef vector<Element>::reverse_iterator reverse_iterator;
|
||||
typedef vector<Element>::const_reverse_iterator const_reverse_iterator;
|
||||
typedef vector<Element>::difference_type difference_type;
|
||||
typedef vector<Element>::size_type size_type;
|
||||
typedef pvector<Element>::value_type value_type;
|
||||
typedef pvector<Element>::reference reference;
|
||||
typedef pvector<Element>::const_reference const_reference;
|
||||
typedef pvector<Element>::iterator iterator;
|
||||
typedef pvector<Element>::const_iterator const_iterator;
|
||||
typedef pvector<Element>::reverse_iterator reverse_iterator;
|
||||
typedef pvector<Element>::const_reverse_iterator const_reverse_iterator;
|
||||
typedef pvector<Element>::difference_type difference_type;
|
||||
typedef pvector<Element>::size_type size_type;
|
||||
|
||||
PUBLISHED:
|
||||
INLINE PointerToArray();
|
||||
@ -153,7 +152,7 @@ public:
|
||||
|
||||
INLINE operator Element *() const;
|
||||
INLINE Element *p() const;
|
||||
INLINE vector<Element> &v() const;
|
||||
INLINE pvector<Element> &v() const;
|
||||
|
||||
//These functions are only to be used in Reading through BamReader.
|
||||
//They are designed to work in pairs, so that you register what is
|
||||
@ -168,7 +167,7 @@ public:
|
||||
|
||||
// Reassignment is by pointer, not memberwise as with a vector.
|
||||
INLINE PointerToArray<Element> &
|
||||
operator = (RefCountObj<vector<Element> > *ptr);
|
||||
operator = (RefCountObj<pvector<Element> > *ptr);
|
||||
INLINE PointerToArray<Element> &
|
||||
operator = (const PointerToArray<Element> ©);
|
||||
INLINE void clear();
|
||||
@ -179,7 +178,7 @@ private:
|
||||
// NULL pointer. It might not be shared properly between different
|
||||
// .so's, since it's a static member of a template class, but we
|
||||
// don't really care.
|
||||
static vector<Element> _empty_array;
|
||||
static pvector<Element> _empty_array;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -188,22 +187,22 @@ private:
|
||||
// may not be modified.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template <class Element>
|
||||
class ConstPointerToArray : public PointerToBase<RefCountObj<vector<Element> > > {
|
||||
class ConstPointerToArray : public PointerToBase<RefCountObj<pvector<Element> > > {
|
||||
public:
|
||||
typedef vector<Element>::value_type value_type;
|
||||
typedef vector<Element>::const_reference reference;
|
||||
typedef vector<Element>::const_reference const_reference;
|
||||
typedef vector<Element>::const_iterator iterator;
|
||||
typedef vector<Element>::const_iterator const_iterator;
|
||||
typedef pvector<Element>::value_type value_type;
|
||||
typedef pvector<Element>::const_reference reference;
|
||||
typedef pvector<Element>::const_reference const_reference;
|
||||
typedef pvector<Element>::const_iterator iterator;
|
||||
typedef pvector<Element>::const_iterator const_iterator;
|
||||
#ifdef WIN32_VC
|
||||
// VC++ seems to break the const_reverse_iterator definition somehow.
|
||||
typedef vector<Element>::reverse_iterator reverse_iterator;
|
||||
typedef pvector<Element>::reverse_iterator reverse_iterator;
|
||||
#else
|
||||
typedef vector<Element>::const_reverse_iterator reverse_iterator;
|
||||
typedef pvector<Element>::const_reverse_iterator reverse_iterator;
|
||||
#endif
|
||||
typedef vector<Element>::const_reverse_iterator const_reverse_iterator;
|
||||
typedef vector<Element>::difference_type difference_type;
|
||||
typedef vector<Element>::size_type size_type;
|
||||
typedef pvector<Element>::const_reverse_iterator const_reverse_iterator;
|
||||
typedef pvector<Element>::difference_type difference_type;
|
||||
typedef pvector<Element>::size_type size_type;
|
||||
|
||||
INLINE ConstPointerToArray();
|
||||
INLINE ConstPointerToArray(const PointerToArray<Element> ©);
|
||||
@ -233,13 +232,13 @@ public:
|
||||
|
||||
INLINE operator const Element *() const;
|
||||
INLINE const Element *p() const;
|
||||
INLINE const vector<Element> &v() const;
|
||||
INLINE const pvector<Element> &v() const;
|
||||
|
||||
INLINE int get_ref_count() const;
|
||||
|
||||
// Reassignment is by pointer, not memberwise as with a vector.
|
||||
INLINE ConstPointerToArray<Element> &
|
||||
operator = (RefCountObj<vector<Element> > *ptr);
|
||||
operator = (RefCountObj<pvector<Element> > *ptr);
|
||||
INLINE ConstPointerToArray<Element> &
|
||||
operator = (const PointerToArray<Element> ©);
|
||||
INLINE ConstPointerToArray<Element> &
|
||||
@ -252,7 +251,7 @@ private:
|
||||
// NULL pointer. It might not be shared properly between different
|
||||
// .so's, since it's a static member of a template class, but we
|
||||
// don't really care.
|
||||
static vector<Element> _empty_array;
|
||||
static pvector<Element> _empty_array;
|
||||
};
|
||||
|
||||
|
||||
|
@ -1446,12 +1446,14 @@ hide_collision_solids() {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NodePath::is_hidden
|
||||
// Access: Public
|
||||
// Description: Returns true if some arc above this bottom node has
|
||||
// been set to 'hide', false if it should be visible.
|
||||
// Description: Returns true if the bottom arc has been hidden,
|
||||
// false otherwise. The bottom node may still be
|
||||
// invisible due to a higher ancestor having been
|
||||
// hidden; use get_hidden_ancestor() to check this.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool NodePath::
|
||||
is_hidden() const {
|
||||
return !get_hidden_ancestor().is_empty();
|
||||
return (arc()->has_transition(PruneTransition::get_class_type()));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -1489,10 +1491,26 @@ unstash() {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NodePath::is_stashed
|
||||
// Access: Public
|
||||
// Description: Returns true if some arc above this bottom node has
|
||||
// been set to 'stash', false if it should be visible.
|
||||
// Description: Returns true if the bottom arc has been 'stashed',
|
||||
// false otherwise.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool NodePath::
|
||||
is_stashed() const {
|
||||
return !get_stashed_ancestor().is_empty();
|
||||
return (arc()->get_graph_type() == NodeRelation::get_stashed_type());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NodePath::clear_wrt_cache
|
||||
// Access: Public
|
||||
// Description: Recursively calls clear_wrt_cache() on every arc
|
||||
// beginning at the bottom arc and below. This wipes
|
||||
// out the cached wrt information, which will make the
|
||||
// next call to wrt() more expensive, but may reclaim
|
||||
// some memory and free up some otherwise unused
|
||||
// pointers.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void NodePath::
|
||||
clear_wrt_cache() {
|
||||
nassertv_always(!is_empty());
|
||||
r_clear_wrt_cache(arc());
|
||||
}
|
||||
|
@ -3147,3 +3147,23 @@ r_adjust_all_priorities(NodeRelation *arc, int adjustment) {
|
||||
r_adjust_all_priorities(child_arc, adjustment);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NodePath::r_clear_wrt_cache
|
||||
// Access: Private
|
||||
// Description: The recursive implementation of
|
||||
// clear_wrt_cache(). This walks through the
|
||||
// subgraph defined by the indicated arc and below.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void NodePath::
|
||||
r_clear_wrt_cache(NodeRelation *arc) {
|
||||
arc->clear_wrt_cache();
|
||||
|
||||
Node *dnode = arc->get_child();
|
||||
|
||||
int num_children = dnode->get_num_children(_graph_type);
|
||||
for (int i = 0; i < num_children; i++) {
|
||||
NodeRelation *child_arc = dnode->get_child(_graph_type, i);
|
||||
r_clear_wrt_cache(child_arc);
|
||||
}
|
||||
}
|
||||
|
@ -510,6 +510,7 @@ PUBLISHED:
|
||||
NodePath get_stashed_ancestor() const;
|
||||
|
||||
void prepare_scene(GraphicsStateGuardianBase *gsg);
|
||||
INLINE void clear_wrt_cache();
|
||||
|
||||
void show_bounds();
|
||||
void hide_bounds();
|
||||
@ -542,6 +543,7 @@ private:
|
||||
void r_list_transitions(ostream &out, int indent_level) const;
|
||||
|
||||
void r_adjust_all_priorities(NodeRelation *arc, int adjustment);
|
||||
void r_clear_wrt_cache(NodeRelation *arc);
|
||||
|
||||
// It's important that there are no data members in this class. Put
|
||||
// them in NodePathBase instead.
|
||||
|
Loading…
x
Reference in New Issue
Block a user