mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-04 10:54:24 -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>)?
|
// Do we have RTTI (and <typeinfo>)?
|
||||||
#define HAVE_RTTI 1
|
#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>)?
|
// Do we have RTTI (and <typeinfo>)?
|
||||||
#define HAVE_RTTI 1
|
#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>)?
|
// Do we have RTTI (and <typeinfo>)?
|
||||||
#define HAVE_RTTI 1
|
#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)
|
// can Intel C++ build this directory successfully (if not, change CC to msvc)
|
||||||
#define NOT_INTEL_BUILDABLE false
|
#define NOT_INTEL_BUILDABLE false
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -181,6 +181,12 @@ $[cdefine HAVE_SYS_SOUNDCARD_H]
|
|||||||
/* Do we have RTTI (and <typeinfo>)? */
|
/* Do we have RTTI (and <typeinfo>)? */
|
||||||
$[cdefine HAVE_RTTI]
|
$[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
|
#end dtool_config.h
|
||||||
|
|
||||||
#endif // BUILD_TYPE
|
#endif // BUILD_TYPE
|
||||||
|
@ -6,8 +6,12 @@
|
|||||||
|
|
||||||
#define SOURCES \
|
#define SOURCES \
|
||||||
dtoolbase.cxx dtoolbase.h dtoolbase_cc.h dtoolsymbols.h \
|
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 \
|
#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
|
#end lib_target
|
||||||
|
@ -17,3 +17,21 @@
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#include "dtoolbase.h"
|
#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
|
#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
|
#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.
|
// They will automatically be undefined at the end of the file.
|
||||||
|
|
||||||
#include <vector>
|
#include "pvector.h"
|
||||||
|
|
||||||
#if defined(WIN32_VC) && !defined(CPPPARSER)
|
#if defined(WIN32_VC) && !defined(CPPPARSER)
|
||||||
|
|
||||||
@ -65,7 +65,7 @@ EXPORT_TEMPLATE_CLASS(EXPCL, EXPTP, std::vector<TYPE>)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Now make a typedef for the vector.
|
// 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
|
// Finally, we must define a non-inline function that performs the
|
||||||
// insert operation given a range of pointers. We do this because
|
// insert operation given a range of pointers. We do this because
|
||||||
|
@ -143,6 +143,35 @@ clear_bins() {
|
|||||||
nassertv(_default_bin == (GeomBin *)NULL);
|
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
|
// Function: CullTraverser::output
|
||||||
// Access: Public
|
// Access: Public
|
||||||
|
@ -59,6 +59,8 @@ PUBLISHED:
|
|||||||
GeomBin *get_bin(const string &name) const;
|
GeomBin *get_bin(const string &name) const;
|
||||||
void clear_bins();
|
void clear_bins();
|
||||||
|
|
||||||
|
void clear_state();
|
||||||
|
|
||||||
void output(ostream &out) const;
|
void output(ostream &out) const;
|
||||||
void write(ostream &out, int indent_level = 0) const;
|
void write(ostream &out, int indent_level = 0) const;
|
||||||
|
|
||||||
|
@ -125,6 +125,27 @@ release_all_textures() {
|
|||||||
nassertv(_prepared_textures.empty());
|
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
|
// Function: GraphicsStateGuardian::reset
|
||||||
// Access: Public, Virtual
|
// Access: Public, Virtual
|
||||||
|
@ -78,10 +78,11 @@ PUBLISHED:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void enable_frame_clear(bool clear_color, bool clear_depth);
|
void enable_frame_clear(bool clear_color, bool clear_depth);
|
||||||
|
|
||||||
public:
|
|
||||||
void release_all_textures();
|
void release_all_textures();
|
||||||
|
|
||||||
|
void clear_attribute(TypeHandle type);
|
||||||
|
|
||||||
|
public:
|
||||||
virtual void clear(const RenderBuffer &buffer)=0;
|
virtual void clear(const RenderBuffer &buffer)=0;
|
||||||
virtual void clear(const RenderBuffer &buffer, const DisplayRegion* region)=0;
|
virtual void clear(const RenderBuffer &buffer, const DisplayRegion* region)=0;
|
||||||
|
|
||||||
|
@ -16,9 +16,11 @@
|
|||||||
//
|
//
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifdef WIN32_VC
|
||||||
#define WINDOWS_LEAN_AND_MEAN
|
#define WINDOWS_LEAN_AND_MEAN
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#undef WINDOWS_LEAN_AND_MEAN
|
#undef WINDOWS_LEAN_AND_MEAN
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <error_utils.h>
|
#include <error_utils.h>
|
||||||
|
@ -20,8 +20,11 @@
|
|||||||
datagramOutputFile.h datagramSink.I datagramSink.h \
|
datagramOutputFile.h datagramSink.I datagramSink.h \
|
||||||
get_config_path.h hashGeneratorBase.I hashGeneratorBase.h \
|
get_config_path.h hashGeneratorBase.I hashGeneratorBase.h \
|
||||||
hashVal.I hashVal.h indent.I indent.h littleEndian.h \
|
hashVal.I hashVal.h indent.I indent.h littleEndian.h \
|
||||||
memoryUsage.I memoryUsage.h memoryUsagePointers.I \
|
memoryInfo.I memoryInfo.h \
|
||||||
memoryUsagePointers.h multifile.I multifile.h namable.I \
|
memoryUsage.I memoryUsage.h \
|
||||||
|
memoryUsagePointerCounts.I memoryUsagePointerCounts.h \
|
||||||
|
memoryUsagePointers.I memoryUsagePointers.h \
|
||||||
|
multifile.I multifile.h namable.I \
|
||||||
namable.h nativeNumericData.I nativeNumericData.h \
|
namable.h nativeNumericData.I nativeNumericData.h \
|
||||||
numeric_types.h pointerTo.I pointerTo.h referenceCount.I \
|
numeric_types.h pointerTo.I pointerTo.h referenceCount.I \
|
||||||
profileTimer.I profileTimer.h referenceCount.h \
|
profileTimer.I profileTimer.h referenceCount.h \
|
||||||
@ -36,7 +39,8 @@
|
|||||||
config_express.cxx datagram.cxx datagramGenerator.cxx \
|
config_express.cxx datagram.cxx datagramGenerator.cxx \
|
||||||
datagramInputFile.cxx datagramIterator.cxx \
|
datagramInputFile.cxx datagramIterator.cxx \
|
||||||
datagramOutputFile.cxx datagramSink.cxx get_config_path.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 \
|
memoryUsagePointers.cxx multifile.cxx namable.cxx \
|
||||||
nativeNumericData.cxx profileTimer.cxx referenceCount.cxx \
|
nativeNumericData.cxx profileTimer.cxx referenceCount.cxx \
|
||||||
reversedNumericData.cxx trueClock.cxx typeHandle.cxx \
|
reversedNumericData.cxx trueClock.cxx typeHandle.cxx \
|
||||||
@ -58,9 +62,11 @@
|
|||||||
datagramGenerator.h get_config_path.h \
|
datagramGenerator.h get_config_path.h \
|
||||||
hashGeneratorBase.I hashGeneratorBase.h \
|
hashGeneratorBase.I hashGeneratorBase.h \
|
||||||
hashVal.I hashVal.h \
|
hashVal.I hashVal.h \
|
||||||
indent.I indent.h littleEndian.h \
|
indent.I indent.h littleEndian.h \
|
||||||
memoryUsage.I memoryUsage.h memoryUsagePointers.I \
|
memoryInfo.I memoryInfo.h \
|
||||||
memoryUsagePointers.h multifile.I multifile.h \
|
memoryUsage.I memoryUsage.h \
|
||||||
|
memoryUsagePointerCounts.I memoryUsagePointerCounts.h \
|
||||||
|
memoryUsagePointers.I memoryUsagePointers.h multifile.I multifile.h \
|
||||||
nativeNumericData.I nativeNumericData.h \
|
nativeNumericData.I nativeNumericData.h \
|
||||||
numeric_types.h \
|
numeric_types.h \
|
||||||
pointerTo.I pointerTo.h referenceCount.I referenceCount.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__
|
#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
|
// Function: MemoryUsage::get_num_pointers
|
||||||
// Access: Public, Static
|
// Access: Public, Static
|
||||||
|
@ -49,116 +49,6 @@ double MemoryUsage::AgeHistogram::_cutoff[MemoryUsage::AgeHistogram::num_buckets
|
|||||||
60.0,
|
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
|
// Function: MemoryUsage::TypeHistogram::add_info
|
||||||
@ -166,8 +56,8 @@ update_type_handle(TypeHandle &destination, TypeHandle refined) {
|
|||||||
// Description: Adds a single entry to the histogram.
|
// Description: Adds a single entry to the histogram.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void MemoryUsage::TypeHistogram::
|
void MemoryUsage::TypeHistogram::
|
||||||
add_info(TypeHandle type) {
|
add_info(TypeHandle type, MemoryInfo &info) {
|
||||||
_counts[type]++;
|
_counts[type].add_info(info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -175,14 +65,16 @@ add_info(TypeHandle type) {
|
|||||||
// below, to sort the types in descending order by counts.
|
// below, to sort the types in descending order by counts.
|
||||||
class TypeHistogramCountSorter {
|
class TypeHistogramCountSorter {
|
||||||
public:
|
public:
|
||||||
TypeHistogramCountSorter(int count, TypeHandle type) {
|
TypeHistogramCountSorter(const MemoryUsagePointerCounts &count,
|
||||||
_count = count;
|
TypeHandle type) :
|
||||||
_type = type;
|
_count(count),
|
||||||
|
_type(type)
|
||||||
|
{
|
||||||
}
|
}
|
||||||
bool operator < (const TypeHistogramCountSorter &other) const {
|
bool operator < (const TypeHistogramCountSorter &other) const {
|
||||||
return _count > other._count;
|
return _count > other._count;
|
||||||
}
|
}
|
||||||
int _count;
|
MemoryUsagePointerCounts _count;
|
||||||
TypeHandle _type;
|
TypeHandle _type;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -206,7 +98,13 @@ show() const {
|
|||||||
|
|
||||||
vector<TypeHistogramCountSorter>::const_iterator vi;
|
vector<TypeHistogramCountSorter>::const_iterator vi;
|
||||||
for (vi = count_sorter.begin(); vi != count_sorter.end(); ++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.
|
// Description: Adds a single entry to the histogram.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void MemoryUsage::AgeHistogram::
|
void MemoryUsage::AgeHistogram::
|
||||||
add_info(double age) {
|
add_info(double age, MemoryInfo &info) {
|
||||||
int bucket = choose_bucket(age);
|
int bucket = choose_bucket(age);
|
||||||
nassertv(bucket >= 0 && bucket < num_buckets);
|
nassertv(bucket >= 0 && bucket < num_buckets);
|
||||||
_counts[bucket]++;
|
_counts[bucket].add_info(info);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
@ -250,11 +148,13 @@ add_info(double age) {
|
|||||||
void MemoryUsage::AgeHistogram::
|
void MemoryUsage::AgeHistogram::
|
||||||
show() const {
|
show() const {
|
||||||
for (int i = 0; i < num_buckets - 1; i++) {
|
for (int i = 0; i < num_buckets - 1; i++) {
|
||||||
nout << _cutoff[i] << " to " << _cutoff[i + 1] << " seconds old : "
|
nout << _cutoff[i] << " to " << _cutoff[i + 1] << " seconds old : ";
|
||||||
<< _counts[i] << " pointers.\n";
|
_counts[i].output(nout);
|
||||||
|
nout << "\n";
|
||||||
}
|
}
|
||||||
nout << _cutoff[num_buckets - 1] << " seconds old and up : "
|
nout << _cutoff[num_buckets - 1] << " seconds old and up : ";
|
||||||
<< _counts[num_buckets - 1] << " pointers.\n";
|
_counts[num_buckets - 1].output(nout);
|
||||||
|
nout << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
@ -265,7 +165,7 @@ show() const {
|
|||||||
void MemoryUsage::AgeHistogram::
|
void MemoryUsage::AgeHistogram::
|
||||||
clear() {
|
clear() {
|
||||||
for (int i = 0; i < num_buckets; i++) {
|
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
|
#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
|
// Function: MemoryUsage::Constructor
|
||||||
// Access: Private
|
// Access: Private
|
||||||
@ -354,8 +285,18 @@ MemoryUsage() {
|
|||||||
_track_memory_usage =
|
_track_memory_usage =
|
||||||
config_express.GetBool("track-memory-usage", false);
|
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;
|
_freeze_index = 0;
|
||||||
_count = 0;
|
_count = 0;
|
||||||
|
_allocated_size = 0;
|
||||||
|
_total_size = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
@ -382,24 +323,31 @@ get_global_ptr() {
|
|||||||
void MemoryUsage::
|
void MemoryUsage::
|
||||||
ns_record_pointer(ReferenceCount *ptr) {
|
ns_record_pointer(ReferenceCount *ptr) {
|
||||||
if (_track_memory_usage) {
|
if (_track_memory_usage) {
|
||||||
MemoryInfo info;
|
pair<Table::iterator, bool> insert_result =
|
||||||
info._ptr = ptr;
|
_table.insert(Table::value_type((void *)ptr, MemoryInfo()));
|
||||||
info._typed_ptr = (TypedObject *)NULL;
|
|
||||||
|
// 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._static_type = ReferenceCount::get_class_type();
|
||||||
info._dynamic_type = ReferenceCount::get_class_type();
|
info._dynamic_type = ReferenceCount::get_class_type();
|
||||||
info._time = TrueClock::get_ptr()->get_real_time();
|
info._time = TrueClock::get_ptr()->get_real_time();
|
||||||
info._freeze_index = _freeze_index;
|
info._freeze_index = _freeze_index;
|
||||||
info._reconsider_dynamic_type = true;
|
info._flags |= (MemoryInfo::F_reconsider_dynamic_type | MemoryInfo::F_got_ref);
|
||||||
|
|
||||||
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++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -427,6 +375,8 @@ ns_update_type(ReferenceCount *ptr, TypeHandle type) {
|
|||||||
MemoryInfo &info = (*ti).second;
|
MemoryInfo &info = (*ti).second;
|
||||||
info.update_type_handle(info._static_type, type);
|
info.update_type_handle(info._static_type, type);
|
||||||
info.determine_dynamic_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;
|
MemoryInfo &info = (*ti).second;
|
||||||
info._typed_ptr = typed_ptr;
|
info._typed_ptr = typed_ptr;
|
||||||
info.determine_dynamic_type();
|
info.determine_dynamic_type();
|
||||||
|
|
||||||
|
consolidate_void_ptr(info);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -481,6 +433,14 @@ ns_remove_pointer(ReferenceCount *ptr) {
|
|||||||
|
|
||||||
MemoryInfo &info = (*ti).second;
|
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
|
// Since the pointer has been destructed, we can't safely call its
|
||||||
// TypedObject virtual methods any more. Better clear out the
|
// TypedObject virtual methods any more. Better clear out the
|
||||||
// typed_ptr for good measure.
|
// typed_ptr for good measure.
|
||||||
@ -488,15 +448,143 @@ ns_remove_pointer(ReferenceCount *ptr) {
|
|||||||
|
|
||||||
if (info._freeze_index == _freeze_index) {
|
if (info._freeze_index == _freeze_index) {
|
||||||
double now = TrueClock::get_ptr()->get_real_time();
|
double now = TrueClock::get_ptr()->get_real_time();
|
||||||
_count--;
|
_trend_types.add_info(info.get_type(), info);
|
||||||
_trend_types.add_info(info.get_type());
|
_trend_ages.add_info(now - info._time, info);
|
||||||
_trend_ages.add_info(now - info._time);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_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
|
// Function: MemoryUsage::ns_get_num_pointers
|
||||||
// Access: Private
|
// Access: Private
|
||||||
@ -523,8 +611,9 @@ ns_get_pointers(MemoryUsagePointers &result) {
|
|||||||
Table::iterator ti;
|
Table::iterator ti;
|
||||||
for (ti = _table.begin(); ti != _table.end(); ++ti) {
|
for (ti = _table.begin(); ti != _table.end(); ++ti) {
|
||||||
MemoryInfo &info = (*ti).second;
|
MemoryInfo &info = (*ti).second;
|
||||||
if (info._freeze_index == _freeze_index) {
|
if (info._freeze_index == _freeze_index &&
|
||||||
result.add_entry(info._ptr, info._typed_ptr, info.get_type(),
|
info._ref_ptr != (ReferenceCount *)NULL) {
|
||||||
|
result.add_entry(info._ref_ptr, info._typed_ptr, info.get_type(),
|
||||||
now - info._time);
|
now - info._time);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -546,11 +635,12 @@ ns_get_pointers_of_type(MemoryUsagePointers &result, TypeHandle type) {
|
|||||||
Table::iterator ti;
|
Table::iterator ti;
|
||||||
for (ti = _table.begin(); ti != _table.end(); ++ti) {
|
for (ti = _table.begin(); ti != _table.end(); ++ti) {
|
||||||
MemoryInfo &info = (*ti).second;
|
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();
|
TypeHandle info_type = info.get_type();
|
||||||
if (info_type != TypeHandle::none() &&
|
if (info_type != TypeHandle::none() &&
|
||||||
info_type.is_derived_from(type)) {
|
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);
|
now - info._time);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -574,11 +664,12 @@ ns_get_pointers_of_age(MemoryUsagePointers &result,
|
|||||||
Table::iterator ti;
|
Table::iterator ti;
|
||||||
for (ti = _table.begin(); ti != _table.end(); ++ti) {
|
for (ti = _table.begin(); ti != _table.end(); ++ti) {
|
||||||
MemoryInfo &info = (*ti).second;
|
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;
|
double age = now - info._time;
|
||||||
if ((age >= from && age <= to) ||
|
if ((age >= from && age <= to) ||
|
||||||
(age >= to && age <= from)) {
|
(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;
|
Table::iterator ti;
|
||||||
for (ti = _table.begin(); ti != _table.end(); ++ti) {
|
for (ti = _table.begin(); ti != _table.end(); ++ti) {
|
||||||
MemoryInfo &info = (*ti).second;
|
MemoryInfo &info = (*ti).second;
|
||||||
if (info._freeze_index == _freeze_index) {
|
if (info._freeze_index == _freeze_index &&
|
||||||
if ((*ti).first->get_ref_count() == 0) {
|
info._ref_ptr != (ReferenceCount *)NULL) {
|
||||||
(*ti).first->ref();
|
if (info._ref_ptr->get_ref_count() == 0) {
|
||||||
result.add_entry(info._ptr, info._typed_ptr, info.get_type(),
|
info._ref_ptr->ref();
|
||||||
|
result.add_entry(info._ref_ptr, info._typed_ptr, info.get_type(),
|
||||||
now - info._time);
|
now - info._time);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -639,6 +731,7 @@ ns_get_pointers_with_zero_count(MemoryUsagePointers &result) {
|
|||||||
void MemoryUsage::
|
void MemoryUsage::
|
||||||
ns_freeze() {
|
ns_freeze() {
|
||||||
_count = 0;
|
_count = 0;
|
||||||
|
_allocated_size = 0;
|
||||||
_trend_types.clear();
|
_trend_types.clear();
|
||||||
_trend_ages.clear();
|
_trend_ages.clear();
|
||||||
_freeze_index++;
|
_freeze_index++;
|
||||||
@ -658,7 +751,7 @@ ns_show_current_types() {
|
|||||||
for (ti = _table.begin(); ti != _table.end(); ++ti) {
|
for (ti = _table.begin(); ti != _table.end(); ++ti) {
|
||||||
MemoryInfo &info = (*ti).second;
|
MemoryInfo &info = (*ti).second;
|
||||||
if (info._freeze_index == _freeze_index) {
|
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) {
|
for (ti = _table.begin(); ti != _table.end(); ++ti) {
|
||||||
MemoryInfo &info = (*ti).second;
|
MemoryInfo &info = (*ti).second;
|
||||||
if (info._freeze_index == _freeze_index) {
|
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();
|
_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
|
#endif // NDEBUG
|
||||||
|
@ -22,6 +22,8 @@
|
|||||||
#include <pandabase.h>
|
#include <pandabase.h>
|
||||||
|
|
||||||
#include "typedObject.h"
|
#include "typedObject.h"
|
||||||
|
#include "memoryInfo.h"
|
||||||
|
#include "memoryUsagePointerCounts.h"
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
@ -42,7 +44,6 @@ class EXPCL_PANDAEXPRESS MemoryUsage {
|
|||||||
public:
|
public:
|
||||||
INLINE static bool get_track_memory_usage();
|
INLINE static bool get_track_memory_usage();
|
||||||
|
|
||||||
PUBLISHED:
|
|
||||||
#if defined(__GNUC__) && !defined(NDEBUG)
|
#if defined(__GNUC__) && !defined(NDEBUG)
|
||||||
// There seems to be a problem with egcs-2.91.66: it gets confused
|
// 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
|
// with too many nested inline functions, and sets the wrong pointer
|
||||||
@ -62,7 +63,20 @@ PUBLISHED:
|
|||||||
INLINE static void remove_pointer(ReferenceCount *ptr);
|
INLINE static void remove_pointer(ReferenceCount *ptr);
|
||||||
#endif // __GNUC__ && !NDEBUG
|
#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 int get_num_pointers();
|
||||||
INLINE static void get_pointers(MemoryUsagePointers &result);
|
INLINE static void get_pointers(MemoryUsagePointers &result);
|
||||||
INLINE static void get_pointers_of_type(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_update_type(ReferenceCount *ptr, TypedObject *typed_ptr);
|
||||||
void ns_remove_pointer(ReferenceCount *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();
|
int ns_get_num_pointers();
|
||||||
void ns_get_pointers(MemoryUsagePointers &result);
|
void ns_get_pointers(MemoryUsagePointers &result);
|
||||||
void ns_get_pointers_of_type(MemoryUsagePointers &result,
|
void ns_get_pointers_of_type(MemoryUsagePointers &result,
|
||||||
@ -101,38 +120,25 @@ private:
|
|||||||
void ns_show_current_ages();
|
void ns_show_current_ages();
|
||||||
void ns_show_trend_ages();
|
void ns_show_trend_ages();
|
||||||
|
|
||||||
|
void consolidate_void_ptr(MemoryInfo &info);
|
||||||
|
|
||||||
static MemoryUsage *_global_ptr;
|
static MemoryUsage *_global_ptr;
|
||||||
|
|
||||||
class MemoryInfo {
|
typedef map<void *, MemoryInfo> Table;
|
||||||
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;
|
|
||||||
Table _table;
|
Table _table;
|
||||||
int _freeze_index;
|
int _freeze_index;
|
||||||
int _count;
|
int _count;
|
||||||
|
size_t _allocated_size;
|
||||||
|
size_t _total_size;
|
||||||
|
|
||||||
class TypeHistogram {
|
class TypeHistogram {
|
||||||
public:
|
public:
|
||||||
void add_info(TypeHandle type);
|
void add_info(TypeHandle type, MemoryInfo &info);
|
||||||
void show() const;
|
void show() const;
|
||||||
void clear();
|
void clear();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
typedef map<TypeHandle, int> Counts;
|
typedef map<TypeHandle, MemoryUsagePointerCounts> Counts;
|
||||||
Counts _counts;
|
Counts _counts;
|
||||||
};
|
};
|
||||||
TypeHistogram _trend_types;
|
TypeHistogram _trend_types;
|
||||||
@ -140,7 +146,7 @@ private:
|
|||||||
class AgeHistogram {
|
class AgeHistogram {
|
||||||
public:
|
public:
|
||||||
AgeHistogram();
|
AgeHistogram();
|
||||||
void add_info(double age);
|
void add_info(double age, MemoryInfo &info);
|
||||||
void show() const;
|
void show() const;
|
||||||
void clear();
|
void clear();
|
||||||
|
|
||||||
@ -148,7 +154,7 @@ private:
|
|||||||
int choose_bucket(double age) const;
|
int choose_bucket(double age) const;
|
||||||
|
|
||||||
enum { num_buckets = 5 };
|
enum { num_buckets = 5 };
|
||||||
int _counts[num_buckets];
|
MemoryUsagePointerCounts _counts[num_buckets];
|
||||||
static double _cutoff[num_buckets];
|
static double _cutoff[num_buckets];
|
||||||
};
|
};
|
||||||
AgeHistogram _trend_ages;
|
AgeHistogram _trend_ages;
|
||||||
@ -156,7 +162,7 @@ private:
|
|||||||
|
|
||||||
bool _track_memory_usage;
|
bool _track_memory_usage;
|
||||||
|
|
||||||
#endif
|
#endif // NDEBUG
|
||||||
};
|
};
|
||||||
|
|
||||||
#include "memoryUsage.I"
|
#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:
|
// Description:
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
INLINE MemoryUsagePointers::Entry::
|
INLINE MemoryUsagePointers::Entry::
|
||||||
Entry(ReferenceCount *ptr, TypedObject *typed_ptr,
|
Entry(ReferenceCount *ref_ptr, TypedObject *typed_ptr,
|
||||||
TypeHandle type, double age) :
|
TypeHandle type, double age) :
|
||||||
_ptr(ptr),
|
_ref_ptr(ref_ptr),
|
||||||
_typed_ptr(typed_ptr),
|
_typed_ptr(typed_ptr),
|
||||||
_type(type),
|
_type(type),
|
||||||
_age(age)
|
_age(age)
|
||||||
{
|
{
|
||||||
_ptr->ref();
|
_ref_ptr->ref();
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
@ -39,12 +39,12 @@ Entry(ReferenceCount *ptr, TypedObject *typed_ptr,
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
INLINE MemoryUsagePointers::Entry::
|
INLINE MemoryUsagePointers::Entry::
|
||||||
Entry(const Entry ©) :
|
Entry(const Entry ©) :
|
||||||
_ptr(copy._ptr),
|
_ref_ptr(copy._ref_ptr),
|
||||||
_typed_ptr(copy._typed_ptr),
|
_typed_ptr(copy._typed_ptr),
|
||||||
_type(copy._type),
|
_type(copy._type),
|
||||||
_age(copy._age)
|
_age(copy._age)
|
||||||
{
|
{
|
||||||
_ptr->ref();
|
_ref_ptr->ref();
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
@ -54,12 +54,12 @@ Entry(const Entry ©) :
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
INLINE void MemoryUsagePointers::Entry::
|
INLINE void MemoryUsagePointers::Entry::
|
||||||
operator = (const Entry ©) {
|
operator = (const Entry ©) {
|
||||||
if (_ptr != copy._ptr) {
|
if (_ref_ptr != copy._ref_ptr) {
|
||||||
_ptr->unref();
|
_ref_ptr->unref();
|
||||||
_ptr = copy._ptr;
|
_ref_ptr = copy._ref_ptr;
|
||||||
// We can't call unref_delete(), because we don't know what kind
|
// We can't call unref_delete(), because we don't know what kind
|
||||||
// of pointer it is precisely. Potential leak.
|
// of pointer it is precisely. Potential leak.
|
||||||
_ptr->ref();
|
_ref_ptr->ref();
|
||||||
}
|
}
|
||||||
_typed_ptr = copy._typed_ptr;
|
_typed_ptr = copy._typed_ptr;
|
||||||
_type = copy._type;
|
_type = copy._type;
|
||||||
@ -75,6 +75,6 @@ INLINE MemoryUsagePointers::Entry::
|
|||||||
~Entry() {
|
~Entry() {
|
||||||
// We can't call unref_delete(), because we don't know what kind
|
// We can't call unref_delete(), because we don't know what kind
|
||||||
// of pointer it is precisely. Potential leak.
|
// of pointer it is precisely. Potential leak.
|
||||||
_ptr->unref();
|
_ref_ptr->unref();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,7 +78,7 @@ get_num_pointers() const {
|
|||||||
ReferenceCount *MemoryUsagePointers::
|
ReferenceCount *MemoryUsagePointers::
|
||||||
get_pointer(int n) const {
|
get_pointer(int n) const {
|
||||||
nassertr(n >= 0 && n < get_num_pointers(), NULL);
|
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;
|
return typed_ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReferenceCount *ptr = _entries[n]._ptr;
|
ReferenceCount *ref_ptr = _entries[n]._ref_ptr;
|
||||||
|
|
||||||
TypeHandle type = _entries[n]._type;
|
TypeHandle type = _entries[n]._type;
|
||||||
|
|
||||||
@ -116,7 +116,7 @@ get_typed_pointer(int n) const {
|
|||||||
|
|
||||||
if (type != TypeHandle::none() &&
|
if (type != TypeHandle::none() &&
|
||||||
type.is_derived_from(TypedReferenceCount::get_class_type())) {
|
type.is_derived_from(TypedReferenceCount::get_class_type())) {
|
||||||
return (TypedReferenceCount *)ptr;
|
return (TypedReferenceCount *)ref_ptr;
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -176,13 +176,13 @@ clear() {
|
|||||||
// only by MemoryUsage.
|
// only by MemoryUsage.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void MemoryUsagePointers::
|
void MemoryUsagePointers::
|
||||||
add_entry(ReferenceCount *ptr, TypedObject *typed_ptr,
|
add_entry(ReferenceCount *ref_ptr, TypedObject *typed_ptr,
|
||||||
TypeHandle type, double age) {
|
TypeHandle type, double age) {
|
||||||
// We can't safly add pointers with a zero reference count. They
|
// We can't safly add pointers with a zero reference count. They
|
||||||
// might be statically-allocated or something, and if we try to add
|
// might be statically-allocated or something, and if we try to add
|
||||||
// them they'll try to destruct when the PointerTo later goes away.
|
// them they'll try to destruct when the PointerTo later goes away.
|
||||||
if (ptr->get_ref_count() != 0) {
|
if (ref_ptr->get_ref_count() != 0) {
|
||||||
_entries.push_back(Entry(ptr, typed_ptr, type, age));
|
_entries.push_back(Entry(ref_ptr, typed_ptr, type, age));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,12 +64,12 @@ PUBLISHED:
|
|||||||
void clear();
|
void clear();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void add_entry(ReferenceCount *ptr, TypedObject *typed_ptr,
|
void add_entry(ReferenceCount *ref_ptr, TypedObject *typed_ptr,
|
||||||
TypeHandle type, double age);
|
TypeHandle type, double age);
|
||||||
|
|
||||||
class Entry {
|
class Entry {
|
||||||
public:
|
public:
|
||||||
INLINE Entry(ReferenceCount *ptr, TypedObject *typed_ptr,
|
INLINE Entry(ReferenceCount *ref_ptr, TypedObject *typed_ptr,
|
||||||
TypeHandle type, double age);
|
TypeHandle type, double age);
|
||||||
INLINE Entry(const Entry ©);
|
INLINE Entry(const Entry ©);
|
||||||
INLINE void operator = (const Entry ©);
|
INLINE void operator = (const Entry ©);
|
||||||
@ -80,7 +80,7 @@ private:
|
|||||||
// (since ReferenceCount has no public destructor). If we can't
|
// (since ReferenceCount has no public destructor). If we can't
|
||||||
// delete it, we can't make a PointerTo it, since PointerTo wants
|
// delete it, we can't make a PointerTo it, since PointerTo wants
|
||||||
// to be able to delete things.
|
// to be able to delete things.
|
||||||
ReferenceCount *_ptr;
|
ReferenceCount *_ref_ptr;
|
||||||
TypedObject *_typed_ptr;
|
TypedObject *_typed_ptr;
|
||||||
TypeHandle _type;
|
TypeHandle _type;
|
||||||
double _age;
|
double _age;
|
||||||
|
@ -118,7 +118,7 @@ private:
|
|||||||
// only works when the base type is, in fact, a class.
|
// only works when the base type is, in fact, a class.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
template<class Base>
|
template<class Base>
|
||||||
class EXPCL_PANDAEXPRESS RefCountObj : public Base, public ReferenceCount {
|
class EXPCL_PANDAEXPRESS RefCountObj : public ReferenceCount, public Base {
|
||||||
public:
|
public:
|
||||||
INLINE RefCountObj();
|
INLINE RefCountObj();
|
||||||
INLINE RefCountObj(const Base ©);
|
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
|
// texture state has changed, we have to be sure to clear the
|
||||||
// current texture state now. A bit unfortunate, but probably not
|
// current texture state now. A bit unfortunate, but probably not
|
||||||
// measurably expensive.
|
// measurably expensive.
|
||||||
NodeAttributes state;
|
clear_attribute(TextureTransition::get_class_type());
|
||||||
state.set_attribute(TextureTransition::get_class_type(), new TextureAttribute);
|
|
||||||
set_state(state, false);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (_clear_buffer_type != 0) {
|
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()
|
// Also force the lighting state to unlit, so that issue_light()
|
||||||
// will be guaranteed to be called next frame even if we have the
|
// will be guaranteed to be called next frame even if we have the
|
||||||
// same set of light pointers we had this frame.
|
// same set of light pointers we had this frame.
|
||||||
NodeAttributes state;
|
clear_attribute(LightTransition::get_class_type());
|
||||||
state.set_attribute(LightTransition::get_class_type(), new LightAttribute);
|
|
||||||
set_state(state, false);
|
|
||||||
|
|
||||||
// All this work to undo the lighting state each frame doesn't seem
|
// 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
|
// 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();
|
// activate();
|
||||||
set_pack_alignment(1);
|
set_pack_alignment(1);
|
||||||
|
|
||||||
NodeAttributes state;
|
|
||||||
|
|
||||||
// Bug fix for RE, RE2, and VTX - need to disable texturing in order
|
// Bug fix for RE, RE2, and VTX - need to disable texturing in order
|
||||||
// for glReadPixels() to work
|
// for glReadPixels() to work
|
||||||
// NOTE: reading the depth buffer is *much* slower than reading the
|
// NOTE: reading the depth buffer is *much* slower than reading the
|
||||||
// color buffer
|
// color buffer
|
||||||
state.set_attribute(TextureTransition::get_class_type(),
|
clear_attribute(TextureTransition::get_class_type());
|
||||||
new TextureAttribute);
|
|
||||||
set_state(state, false);
|
|
||||||
|
|
||||||
int xo, yo, w, h;
|
int xo, yo, w, h;
|
||||||
dr->get_region_pixels(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);
|
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
|
// Function: NodeAttributes::erase
|
||||||
// Access: Public
|
// Access: Public
|
||||||
|
@ -64,6 +64,7 @@ public:
|
|||||||
// of PANDA.DLL.
|
// of PANDA.DLL.
|
||||||
typedef Attributes::iterator iterator;
|
typedef Attributes::iterator iterator;
|
||||||
typedef Attributes::const_iterator const_iterator;
|
typedef Attributes::const_iterator const_iterator;
|
||||||
|
typedef Attributes::key_type key_type;
|
||||||
typedef Attributes::value_type value_type;
|
typedef Attributes::value_type value_type;
|
||||||
typedef Attributes::size_type size_type;
|
typedef Attributes::size_type size_type;
|
||||||
|
|
||||||
@ -73,6 +74,7 @@ public:
|
|||||||
INLINE_GRAPH const_iterator begin() const;
|
INLINE_GRAPH const_iterator begin() const;
|
||||||
INLINE_GRAPH const_iterator end() const;
|
INLINE_GRAPH const_iterator end() const;
|
||||||
INLINE_GRAPH iterator insert(iterator position, const value_type &x);
|
INLINE_GRAPH iterator insert(iterator position, const value_type &x);
|
||||||
|
INLINE_GRAPH iterator find(const key_type &k);
|
||||||
INLINE_GRAPH void erase(iterator position);
|
INLINE_GRAPH void erase(iterator position);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -289,6 +289,21 @@ get_last_update() const {
|
|||||||
return _last_update;
|
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
|
// Function: NodeRelation::create_typed_arc
|
||||||
// Access: Public, Static
|
// Access: Public, Static
|
||||||
|
@ -122,6 +122,7 @@ PUBLISHED:
|
|||||||
INLINE_GRAPH int compare_transitions_to(const NodeRelation *arc) const;
|
INLINE_GRAPH int compare_transitions_to(const NodeRelation *arc) const;
|
||||||
|
|
||||||
INLINE_GRAPH UpdateSeq get_last_update() const;
|
INLINE_GRAPH UpdateSeq get_last_update() const;
|
||||||
|
INLINE_GRAPH void clear_wrt_cache();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool sub_render_trans(const AllAttributesWrapper &attrib,
|
bool sub_render_trans(const AllAttributesWrapper &attrib,
|
||||||
|
@ -39,6 +39,10 @@
|
|||||||
|
|
||||||
PStatClient *PStatClient::_global_pstats = NULL;
|
PStatClient *PStatClient::_global_pstats = NULL;
|
||||||
|
|
||||||
|
#ifndef CPPPARSER
|
||||||
|
PStatCollector _memory_usage_pcollector("Panda memory usage");
|
||||||
|
#endif
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: PStatClient::PerThreadData::Constructor
|
// Function: PStatClient::PerThreadData::Constructor
|
||||||
// Access: Public
|
// Access: Public
|
||||||
@ -363,6 +367,14 @@ make_thread(const string &name) {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void PStatClient::
|
void PStatClient::
|
||||||
main_tick() {
|
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();
|
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", { 1.0, 0.5, 0.2 }, "", 500.0 },
|
||||||
{ 1, "State changes:Transforms", { 0.2, 0.2, 0.8 }, },
|
{ 1, "State changes:Transforms", { 0.2, 0.2, 0.8 }, },
|
||||||
{ 1, "State changes:Textures", { 0.8, 0.2, 0.2 }, },
|
{ 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 }
|
{ 0, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -17,10 +17,10 @@
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
template<class Element>
|
template<class Element>
|
||||||
vector<Element> PointerToArray<Element>::_empty_array;
|
pvector<Element> PointerToArray<Element>::_empty_array;
|
||||||
|
|
||||||
template<class Element>
|
template<class Element>
|
||||||
vector<Element> ConstPointerToArray<Element>::_empty_array;
|
pvector<Element> ConstPointerToArray<Element>::_empty_array;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: PointerToArray::Constructor
|
// Function: PointerToArray::Constructor
|
||||||
@ -30,7 +30,7 @@ vector<Element> ConstPointerToArray<Element>::_empty_array;
|
|||||||
template<class Element>
|
template<class Element>
|
||||||
INLINE PointerToArray<Element>::
|
INLINE PointerToArray<Element>::
|
||||||
PointerToArray() :
|
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>
|
template<class Element>
|
||||||
INLINE PointerToArray<Element>::
|
INLINE PointerToArray<Element>::
|
||||||
PointerToArray(size_type n) :
|
PointerToArray(size_type n) :
|
||||||
PointerToBase<RefCountObj<vector<Element> > >(new RefCountObj<vector<Element> >) {
|
PointerToBase<RefCountObj<pvector<Element> > >(new RefCountObj<pvector<Element> >) {
|
||||||
_ptr->reserve(n);
|
_ptr->reserve(n);
|
||||||
insert(begin(), n, Element());
|
insert(begin(), n, Element());
|
||||||
}
|
}
|
||||||
@ -55,7 +55,7 @@ PointerToArray(size_type n) :
|
|||||||
template<class Element>
|
template<class Element>
|
||||||
INLINE PointerToArray<Element>::
|
INLINE PointerToArray<Element>::
|
||||||
PointerToArray(size_type n, const Element &value) :
|
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);
|
_ptr->reserve(n);
|
||||||
insert(begin(), n, value);
|
insert(begin(), n, value);
|
||||||
}
|
}
|
||||||
@ -68,7 +68,7 @@ PointerToArray(size_type n, const Element &value) :
|
|||||||
template<class Element>
|
template<class Element>
|
||||||
INLINE PointerToArray<Element>::
|
INLINE PointerToArray<Element>::
|
||||||
PointerToArray(const 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>::
|
INLINE PointerToArray<Element>::size_type PointerToArray<Element>::
|
||||||
max_size() const {
|
max_size() const {
|
||||||
nassertd(_ptr != NULL) {
|
nassertd(_ptr != NULL) {
|
||||||
((PointerToArray<Element> *)this)->reassign(new RefCountObj<vector<Element> >);
|
((PointerToArray<Element> *)this)->reassign(new RefCountObj<pvector<Element> >);
|
||||||
}
|
}
|
||||||
return _ptr->max_size();
|
return _ptr->max_size();
|
||||||
}
|
}
|
||||||
@ -173,7 +173,7 @@ template<class Element>
|
|||||||
INLINE void PointerToArray<Element>::
|
INLINE void PointerToArray<Element>::
|
||||||
reserve(PointerToArray<Element>::size_type n) {
|
reserve(PointerToArray<Element>::size_type n) {
|
||||||
if (_ptr == NULL) {
|
if (_ptr == NULL) {
|
||||||
reassign(new RefCountObj<vector<Element> >);
|
reassign(new RefCountObj<pvector<Element> >);
|
||||||
}
|
}
|
||||||
_ptr->reserve(n);
|
_ptr->reserve(n);
|
||||||
}
|
}
|
||||||
@ -199,7 +199,7 @@ template<class Element>
|
|||||||
INLINE PointerToArray<Element>::reference PointerToArray<Element>::
|
INLINE PointerToArray<Element>::reference PointerToArray<Element>::
|
||||||
front() const {
|
front() const {
|
||||||
nassertd(_ptr != NULL) {
|
nassertd(_ptr != NULL) {
|
||||||
((PointerToArray<Element> *)this)->reassign(new RefCountObj<vector<Element> >);
|
((PointerToArray<Element> *)this)->reassign(new RefCountObj<pvector<Element> >);
|
||||||
}
|
}
|
||||||
nassertd(!_ptr->empty()) {
|
nassertd(!_ptr->empty()) {
|
||||||
_ptr->push_back(Element());
|
_ptr->push_back(Element());
|
||||||
@ -216,7 +216,7 @@ template<class Element>
|
|||||||
INLINE PointerToArray<Element>::reference PointerToArray<Element>::
|
INLINE PointerToArray<Element>::reference PointerToArray<Element>::
|
||||||
back() const {
|
back() const {
|
||||||
nassertd(_ptr != NULL) {
|
nassertd(_ptr != NULL) {
|
||||||
((PointerToArray<Element> *)this)->reassign(new RefCountObj<vector<Element> >);
|
((PointerToArray<Element> *)this)->reassign(new RefCountObj<pvector<Element> >);
|
||||||
}
|
}
|
||||||
nassertd(!_ptr->empty()) {
|
nassertd(!_ptr->empty()) {
|
||||||
_ptr->push_back(Element());
|
_ptr->push_back(Element());
|
||||||
@ -261,7 +261,7 @@ template<class Element>
|
|||||||
INLINE void PointerToArray<Element>::
|
INLINE void PointerToArray<Element>::
|
||||||
erase(iterator position) const {
|
erase(iterator position) const {
|
||||||
nassertd(_ptr != NULL) {
|
nassertd(_ptr != NULL) {
|
||||||
((PointerToArray<Element> *)this)->reassign(new RefCountObj<vector<Element> >);
|
((PointerToArray<Element> *)this)->reassign(new RefCountObj<pvector<Element> >);
|
||||||
}
|
}
|
||||||
nassertv(position >= _ptr->begin() &&
|
nassertv(position >= _ptr->begin() &&
|
||||||
position <= _ptr->end());
|
position <= _ptr->end());
|
||||||
@ -277,7 +277,7 @@ template<class Element>
|
|||||||
INLINE void PointerToArray<Element>::
|
INLINE void PointerToArray<Element>::
|
||||||
erase(iterator first, iterator last) const {
|
erase(iterator first, iterator last) const {
|
||||||
nassertd(_ptr != NULL) {
|
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(first >= _ptr->begin() && first <= _ptr->end());
|
||||||
nassertv(last >= _ptr->begin() && last <= _ptr->end());
|
nassertv(last >= _ptr->begin() && last <= _ptr->end());
|
||||||
@ -294,7 +294,7 @@ template<class Element>
|
|||||||
INLINE PointerToArray<Element>::reference PointerToArray<Element>::
|
INLINE PointerToArray<Element>::reference PointerToArray<Element>::
|
||||||
operator [](size_type n) const {
|
operator [](size_type n) const {
|
||||||
nassertd(_ptr != NULL) {
|
nassertd(_ptr != NULL) {
|
||||||
((PointerToArray<Element> *)this)->reassign(new RefCountObj<vector<Element> >);
|
((PointerToArray<Element> *)this)->reassign(new RefCountObj<pvector<Element> >);
|
||||||
}
|
}
|
||||||
nassertd(!_ptr->empty()) {
|
nassertd(!_ptr->empty()) {
|
||||||
_ptr->push_back(Element());
|
_ptr->push_back(Element());
|
||||||
@ -313,7 +313,7 @@ template<class Element>
|
|||||||
INLINE void PointerToArray<Element>::
|
INLINE void PointerToArray<Element>::
|
||||||
push_back(const Element &x) {
|
push_back(const Element &x) {
|
||||||
if (_ptr == NULL) {
|
if (_ptr == NULL) {
|
||||||
reassign(new RefCountObj<vector<Element> >);
|
reassign(new RefCountObj<pvector<Element> >);
|
||||||
}
|
}
|
||||||
_ptr->push_back(x);
|
_ptr->push_back(x);
|
||||||
}
|
}
|
||||||
@ -327,7 +327,7 @@ template<class Element>
|
|||||||
INLINE void PointerToArray<Element>::
|
INLINE void PointerToArray<Element>::
|
||||||
pop_back() {
|
pop_back() {
|
||||||
nassertd(_ptr != NULL) {
|
nassertd(_ptr != NULL) {
|
||||||
((PointerToArray<Element> *)this)->reassign(new RefCountObj<vector<Element> >);
|
((PointerToArray<Element> *)this)->reassign(new RefCountObj<pvector<Element> >);
|
||||||
}
|
}
|
||||||
nassertv(!_ptr->empty());
|
nassertv(!_ptr->empty());
|
||||||
_ptr->pop_back();
|
_ptr->pop_back();
|
||||||
@ -344,7 +344,7 @@ template<class Element>
|
|||||||
INLINE void PointerToArray<Element>::
|
INLINE void PointerToArray<Element>::
|
||||||
make_empty() {
|
make_empty() {
|
||||||
nassertd(_ptr != NULL) {
|
nassertd(_ptr != NULL) {
|
||||||
((PointerToArray<Element> *)this)->reassign(new RefCountObj<vector<Element> >);
|
((PointerToArray<Element> *)this)->reassign(new RefCountObj<pvector<Element> >);
|
||||||
}
|
}
|
||||||
nassertv(!_ptr->empty());
|
nassertv(!_ptr->empty());
|
||||||
_ptr->clear();
|
_ptr->clear();
|
||||||
@ -385,10 +385,10 @@ p() const {
|
|||||||
// with some of the vector's esoteric functionality.
|
// with some of the vector's esoteric functionality.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
template<class Element>
|
template<class Element>
|
||||||
INLINE vector<Element> &PointerToArray<Element>::
|
INLINE pvector<Element> &PointerToArray<Element>::
|
||||||
v() const {
|
v() const {
|
||||||
nassertd(_ptr != NULL) {
|
nassertd(_ptr != NULL) {
|
||||||
((PointerToArray<Element> *)this)->reassign(new RefCountObj<vector<Element> >);
|
((PointerToArray<Element> *)this)->reassign(new RefCountObj<pvector<Element> >);
|
||||||
}
|
}
|
||||||
return *_ptr;
|
return *_ptr;
|
||||||
}
|
}
|
||||||
@ -403,7 +403,7 @@ template<class Element>
|
|||||||
INLINE void* PointerToArray<Element>::
|
INLINE void* PointerToArray<Element>::
|
||||||
get_void_ptr() const
|
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>::
|
INLINE void PointerToArray<Element>::
|
||||||
set_void_ptr(void* p)
|
set_void_ptr(void* p)
|
||||||
{
|
{
|
||||||
reassign((RefCountObj<vector<Element> > *)p);
|
reassign((RefCountObj<pvector<Element> > *)p);
|
||||||
}
|
}
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: PointerToArray::get_ref_count
|
// Function: PointerToArray::get_ref_count
|
||||||
@ -435,7 +435,7 @@ get_ref_count() const {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
template<class Element>
|
template<class Element>
|
||||||
INLINE PointerToArray<Element> &PointerToArray<Element>::
|
INLINE PointerToArray<Element> &PointerToArray<Element>::
|
||||||
operator = (RefCountObj<vector<Element> > *ptr) {
|
operator = (RefCountObj<pvector<Element> > *ptr) {
|
||||||
reassign(ptr);
|
reassign(ptr);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@ -462,7 +462,7 @@ operator = (const PointerToArray<Element> ©) {
|
|||||||
template<class Element>
|
template<class Element>
|
||||||
INLINE void PointerToArray<Element>::
|
INLINE void PointerToArray<Element>::
|
||||||
clear() {
|
clear() {
|
||||||
reassign((RefCountObj<vector<Element> > *)NULL);
|
reassign((RefCountObj<pvector<Element> > *)NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -475,7 +475,7 @@ clear() {
|
|||||||
template<class Element>
|
template<class Element>
|
||||||
INLINE ConstPointerToArray<Element>::
|
INLINE ConstPointerToArray<Element>::
|
||||||
ConstPointerToArray() :
|
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>
|
template<class Element>
|
||||||
INLINE ConstPointerToArray<Element>::
|
INLINE ConstPointerToArray<Element>::
|
||||||
ConstPointerToArray(const PointerToArray<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>
|
template<class Element>
|
||||||
INLINE ConstPointerToArray<Element>::
|
INLINE ConstPointerToArray<Element>::
|
||||||
ConstPointerToArray(const 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>::
|
INLINE ConstPointerToArray<Element>::size_type ConstPointerToArray<Element>::
|
||||||
max_size() const {
|
max_size() const {
|
||||||
nassertd(_ptr != NULL) {
|
nassertd(_ptr != NULL) {
|
||||||
((ConstPointerToArray<Element> *)this)->reassign(new RefCountObj<vector<Element> >);
|
((ConstPointerToArray<Element> *)this)->reassign(new RefCountObj<pvector<Element> >);
|
||||||
}
|
}
|
||||||
return _ptr->max_size();
|
return _ptr->max_size();
|
||||||
}
|
}
|
||||||
@ -604,7 +604,7 @@ template<class Element>
|
|||||||
INLINE ConstPointerToArray<Element>::size_type ConstPointerToArray<Element>::
|
INLINE ConstPointerToArray<Element>::size_type ConstPointerToArray<Element>::
|
||||||
capacity() const {
|
capacity() const {
|
||||||
nassertd(_ptr != NULL) {
|
nassertd(_ptr != NULL) {
|
||||||
((ConstPointerToArray<Element> *)this)->reassign(new RefCountObj<vector<Element> >);
|
((ConstPointerToArray<Element> *)this)->reassign(new RefCountObj<pvector<Element> >);
|
||||||
}
|
}
|
||||||
return _ptr->capacity();
|
return _ptr->capacity();
|
||||||
}
|
}
|
||||||
@ -619,7 +619,7 @@ template<class Element>
|
|||||||
INLINE ConstPointerToArray<Element>::reference ConstPointerToArray<Element>::
|
INLINE ConstPointerToArray<Element>::reference ConstPointerToArray<Element>::
|
||||||
operator[](size_type n) const {
|
operator[](size_type n) const {
|
||||||
nassertd(_ptr != NULL) {
|
nassertd(_ptr != NULL) {
|
||||||
((ConstPointerToArray<Element> *)this)->reassign(new RefCountObj<vector<Element> >);
|
((ConstPointerToArray<Element> *)this)->reassign(new RefCountObj<pvector<Element> >);
|
||||||
}
|
}
|
||||||
nassertd(!_ptr->empty()) {
|
nassertd(!_ptr->empty()) {
|
||||||
_ptr->push_back(Element());
|
_ptr->push_back(Element());
|
||||||
@ -638,7 +638,7 @@ template<class Element>
|
|||||||
INLINE ConstPointerToArray<Element>::reference ConstPointerToArray<Element>::
|
INLINE ConstPointerToArray<Element>::reference ConstPointerToArray<Element>::
|
||||||
front() const {
|
front() const {
|
||||||
nassertd(_ptr != NULL) {
|
nassertd(_ptr != NULL) {
|
||||||
((ConstPointerToArray<Element> *)this)->reassign(new RefCountObj<vector<Element> >);
|
((ConstPointerToArray<Element> *)this)->reassign(new RefCountObj<pvector<Element> >);
|
||||||
}
|
}
|
||||||
nassertd(!_ptr->empty()) {
|
nassertd(!_ptr->empty()) {
|
||||||
_ptr->push_back(Element());
|
_ptr->push_back(Element());
|
||||||
@ -655,7 +655,7 @@ template<class Element>
|
|||||||
INLINE ConstPointerToArray<Element>::reference ConstPointerToArray<Element>::
|
INLINE ConstPointerToArray<Element>::reference ConstPointerToArray<Element>::
|
||||||
back() const {
|
back() const {
|
||||||
nassertd(_ptr != NULL) {
|
nassertd(_ptr != NULL) {
|
||||||
((ConstPointerToArray<Element> *)this)->reassign(new RefCountObj<vector<Element> >);
|
((ConstPointerToArray<Element> *)this)->reassign(new RefCountObj<pvector<Element> >);
|
||||||
}
|
}
|
||||||
nassertd(!_ptr->empty()) {
|
nassertd(!_ptr->empty()) {
|
||||||
_ptr->push_back(Element());
|
_ptr->push_back(Element());
|
||||||
@ -698,10 +698,10 @@ p() const {
|
|||||||
// with some of the vector's esoteric functionality.
|
// with some of the vector's esoteric functionality.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
template<class Element>
|
template<class Element>
|
||||||
INLINE const vector<Element> &ConstPointerToArray<Element>::
|
INLINE const pvector<Element> &ConstPointerToArray<Element>::
|
||||||
v() const {
|
v() const {
|
||||||
nassertd(_ptr != NULL) {
|
nassertd(_ptr != NULL) {
|
||||||
((ConstPointerToArray<Element> *)this)->reassign(new RefCountObj<vector<Element> >);
|
((ConstPointerToArray<Element> *)this)->reassign(new RefCountObj<pvector<Element> >);
|
||||||
}
|
}
|
||||||
return *_ptr;
|
return *_ptr;
|
||||||
}
|
}
|
||||||
@ -724,7 +724,7 @@ get_ref_count() const {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
template<class Element>
|
template<class Element>
|
||||||
INLINE ConstPointerToArray<Element> &ConstPointerToArray<Element>::
|
INLINE ConstPointerToArray<Element> &ConstPointerToArray<Element>::
|
||||||
operator = (RefCountObj<vector<Element> > *ptr) {
|
operator = (RefCountObj<pvector<Element> > *ptr) {
|
||||||
reassign(ptr);
|
reassign(ptr);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@ -763,6 +763,6 @@ operator = (const ConstPointerToArray<Element> ©) {
|
|||||||
template<class Element>
|
template<class Element>
|
||||||
INLINE void ConstPointerToArray<Element>::
|
INLINE void ConstPointerToArray<Element>::
|
||||||
clear() {
|
clear() {
|
||||||
reassign((RefCountObj<vector<Element> > *)NULL);
|
reassign((RefCountObj<pvector<Element> > *)NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,8 +72,7 @@
|
|||||||
|
|
||||||
#include "referenceCount.h"
|
#include "referenceCount.h"
|
||||||
#include "pointerTo.h"
|
#include "pointerTo.h"
|
||||||
|
#include "pvector.h"
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Class : PointerToArray
|
// Class : PointerToArray
|
||||||
@ -84,17 +83,17 @@
|
|||||||
// with a reference count.
|
// with a reference count.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
template <class Element>
|
template <class Element>
|
||||||
class PointerToArray : public PointerToBase<RefCountObj<vector<Element> > > {
|
class PointerToArray : public PointerToBase<RefCountObj<pvector<Element> > > {
|
||||||
public:
|
public:
|
||||||
typedef vector<Element>::value_type value_type;
|
typedef pvector<Element>::value_type value_type;
|
||||||
typedef vector<Element>::reference reference;
|
typedef pvector<Element>::reference reference;
|
||||||
typedef vector<Element>::const_reference const_reference;
|
typedef pvector<Element>::const_reference const_reference;
|
||||||
typedef vector<Element>::iterator iterator;
|
typedef pvector<Element>::iterator iterator;
|
||||||
typedef vector<Element>::const_iterator const_iterator;
|
typedef pvector<Element>::const_iterator const_iterator;
|
||||||
typedef vector<Element>::reverse_iterator reverse_iterator;
|
typedef pvector<Element>::reverse_iterator reverse_iterator;
|
||||||
typedef vector<Element>::const_reverse_iterator const_reverse_iterator;
|
typedef pvector<Element>::const_reverse_iterator const_reverse_iterator;
|
||||||
typedef vector<Element>::difference_type difference_type;
|
typedef pvector<Element>::difference_type difference_type;
|
||||||
typedef vector<Element>::size_type size_type;
|
typedef pvector<Element>::size_type size_type;
|
||||||
|
|
||||||
PUBLISHED:
|
PUBLISHED:
|
||||||
INLINE PointerToArray();
|
INLINE PointerToArray();
|
||||||
@ -153,7 +152,7 @@ public:
|
|||||||
|
|
||||||
INLINE operator Element *() const;
|
INLINE operator Element *() const;
|
||||||
INLINE Element *p() 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.
|
//These functions are only to be used in Reading through BamReader.
|
||||||
//They are designed to work in pairs, so that you register what is
|
//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.
|
// Reassignment is by pointer, not memberwise as with a vector.
|
||||||
INLINE PointerToArray<Element> &
|
INLINE PointerToArray<Element> &
|
||||||
operator = (RefCountObj<vector<Element> > *ptr);
|
operator = (RefCountObj<pvector<Element> > *ptr);
|
||||||
INLINE PointerToArray<Element> &
|
INLINE PointerToArray<Element> &
|
||||||
operator = (const PointerToArray<Element> ©);
|
operator = (const PointerToArray<Element> ©);
|
||||||
INLINE void clear();
|
INLINE void clear();
|
||||||
@ -179,7 +178,7 @@ private:
|
|||||||
// NULL pointer. It might not be shared properly between different
|
// NULL pointer. It might not be shared properly between different
|
||||||
// .so's, since it's a static member of a template class, but we
|
// .so's, since it's a static member of a template class, but we
|
||||||
// don't really care.
|
// don't really care.
|
||||||
static vector<Element> _empty_array;
|
static pvector<Element> _empty_array;
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
@ -188,22 +187,22 @@ private:
|
|||||||
// may not be modified.
|
// may not be modified.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
template <class Element>
|
template <class Element>
|
||||||
class ConstPointerToArray : public PointerToBase<RefCountObj<vector<Element> > > {
|
class ConstPointerToArray : public PointerToBase<RefCountObj<pvector<Element> > > {
|
||||||
public:
|
public:
|
||||||
typedef vector<Element>::value_type value_type;
|
typedef pvector<Element>::value_type value_type;
|
||||||
typedef vector<Element>::const_reference reference;
|
typedef pvector<Element>::const_reference reference;
|
||||||
typedef vector<Element>::const_reference const_reference;
|
typedef pvector<Element>::const_reference const_reference;
|
||||||
typedef vector<Element>::const_iterator iterator;
|
typedef pvector<Element>::const_iterator iterator;
|
||||||
typedef vector<Element>::const_iterator const_iterator;
|
typedef pvector<Element>::const_iterator const_iterator;
|
||||||
#ifdef WIN32_VC
|
#ifdef WIN32_VC
|
||||||
// VC++ seems to break the const_reverse_iterator definition somehow.
|
// 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
|
#else
|
||||||
typedef vector<Element>::const_reverse_iterator reverse_iterator;
|
typedef pvector<Element>::const_reverse_iterator reverse_iterator;
|
||||||
#endif
|
#endif
|
||||||
typedef vector<Element>::const_reverse_iterator const_reverse_iterator;
|
typedef pvector<Element>::const_reverse_iterator const_reverse_iterator;
|
||||||
typedef vector<Element>::difference_type difference_type;
|
typedef pvector<Element>::difference_type difference_type;
|
||||||
typedef vector<Element>::size_type size_type;
|
typedef pvector<Element>::size_type size_type;
|
||||||
|
|
||||||
INLINE ConstPointerToArray();
|
INLINE ConstPointerToArray();
|
||||||
INLINE ConstPointerToArray(const PointerToArray<Element> ©);
|
INLINE ConstPointerToArray(const PointerToArray<Element> ©);
|
||||||
@ -233,13 +232,13 @@ public:
|
|||||||
|
|
||||||
INLINE operator const Element *() const;
|
INLINE operator const Element *() const;
|
||||||
INLINE const Element *p() const;
|
INLINE const Element *p() const;
|
||||||
INLINE const vector<Element> &v() const;
|
INLINE const pvector<Element> &v() const;
|
||||||
|
|
||||||
INLINE int get_ref_count() const;
|
INLINE int get_ref_count() const;
|
||||||
|
|
||||||
// Reassignment is by pointer, not memberwise as with a vector.
|
// Reassignment is by pointer, not memberwise as with a vector.
|
||||||
INLINE ConstPointerToArray<Element> &
|
INLINE ConstPointerToArray<Element> &
|
||||||
operator = (RefCountObj<vector<Element> > *ptr);
|
operator = (RefCountObj<pvector<Element> > *ptr);
|
||||||
INLINE ConstPointerToArray<Element> &
|
INLINE ConstPointerToArray<Element> &
|
||||||
operator = (const PointerToArray<Element> ©);
|
operator = (const PointerToArray<Element> ©);
|
||||||
INLINE ConstPointerToArray<Element> &
|
INLINE ConstPointerToArray<Element> &
|
||||||
@ -252,7 +251,7 @@ private:
|
|||||||
// NULL pointer. It might not be shared properly between different
|
// NULL pointer. It might not be shared properly between different
|
||||||
// .so's, since it's a static member of a template class, but we
|
// .so's, since it's a static member of a template class, but we
|
||||||
// don't really care.
|
// 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
|
// Function: NodePath::is_hidden
|
||||||
// Access: Public
|
// Access: Public
|
||||||
// Description: Returns true if some arc above this bottom node has
|
// Description: Returns true if the bottom arc has been hidden,
|
||||||
// been set to 'hide', false if it should be visible.
|
// 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::
|
INLINE bool NodePath::
|
||||||
is_hidden() const {
|
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
|
// Function: NodePath::is_stashed
|
||||||
// Access: Public
|
// Access: Public
|
||||||
// Description: Returns true if some arc above this bottom node has
|
// Description: Returns true if the bottom arc has been 'stashed',
|
||||||
// been set to 'stash', false if it should be visible.
|
// false otherwise.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
INLINE bool NodePath::
|
INLINE bool NodePath::
|
||||||
is_stashed() const {
|
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);
|
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;
|
NodePath get_stashed_ancestor() const;
|
||||||
|
|
||||||
void prepare_scene(GraphicsStateGuardianBase *gsg);
|
void prepare_scene(GraphicsStateGuardianBase *gsg);
|
||||||
|
INLINE void clear_wrt_cache();
|
||||||
|
|
||||||
void show_bounds();
|
void show_bounds();
|
||||||
void hide_bounds();
|
void hide_bounds();
|
||||||
@ -542,6 +543,7 @@ private:
|
|||||||
void r_list_transitions(ostream &out, int indent_level) const;
|
void r_list_transitions(ostream &out, int indent_level) const;
|
||||||
|
|
||||||
void r_adjust_all_priorities(NodeRelation *arc, int adjustment);
|
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
|
// It's important that there are no data members in this class. Put
|
||||||
// them in NodePathBase instead.
|
// them in NodePathBase instead.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user