You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@stdcxx.apache.org by se...@apache.org on 2006/05/18 01:25:59 UTC
svn commit: r407397 - in /incubator/stdcxx/trunk/tests:
include/rw_allocator.h src/allocator.cpp
Author: sebor
Date: Wed May 17 16:25:58 2006
New Revision: 407397
URL: http://svn.apache.org/viewvc?rev=407397&view=rev
Log:
2006-05-17 Martin Sebor <se...@roguewave.com>
* rw_allocator.h (m_cpy_assign, m_cvt_assign): New constants.
(UserAlloc::operator=): Defined.
(rw_check_leaks): Declared and defined new helpers.
* allocator.cpp (<driver.h>): Included for rw_assert().
(UserAlloc ctor): Initialized n_refs_.
(UserAlloc dtor): Invalidated member arrays.
(_rw_check_leaks): New helper.
(rw_check_leaks): Defined.
Modified:
incubator/stdcxx/trunk/tests/include/rw_allocator.h
incubator/stdcxx/trunk/tests/src/allocator.cpp
Modified: incubator/stdcxx/trunk/tests/include/rw_allocator.h
URL: http://svn.apache.org/viewvc/incubator/stdcxx/trunk/tests/include/rw_allocator.h?rev=407397&r1=407396&r2=407397&view=diff
==============================================================================
--- incubator/stdcxx/trunk/tests/include/rw_allocator.h (original)
+++ incubator/stdcxx/trunk/tests/include/rw_allocator.h Wed May 17 16:25:58 2006
@@ -32,12 +32,26 @@
#include <testdefs.h>
+_RWSTD_NAMESPACE (std) {
+
+// declare to avoid dragging in all of <memory>
+// (yes, it is undefined for programs to do that)
+template <class T>
+struct allocator;
+
+} // namespace std
+
+
struct _TEST_EXPORT SharedAlloc
{
// identifies each member function of a standard allocator class
enum MemFun {
- m_ctor, m_cvt_ctor, m_cpy_ctor,
- m_dtor,
+ m_ctor, // ordinary constructor
+ m_cpy_ctor, // copy constructor
+ m_cvt_ctor, // converting (template) constructor
+ m_cpy_assign, // ordinary assignment operator
+ m_cvt_assign, // converting (template) assignment operator
+ m_dtor, // destructor
m_allocate, m_deallocate,
m_construct, m_destroy,
m_address, m_max_size,
@@ -69,13 +83,14 @@
// returns the maximum number of objects of elemsize each
// that can be allocated from the pool managed by *this
virtual _RWSTD_SIZE_T
- max_size (_RWSTD_SIZE_T /* elemsize */);
+ max_size (_RWSTD_SIZE_T /* elemsize */ = 1);
// records a call to the allocator member function fun and
// throws an exception derived from std::bad_alloc if the
// number of calls to the member function reaches the limit
// specified by throw_at_calls_
- virtual void funcall (MemFun /* fun */);
+ virtual void
+ funcall (MemFun /* fun */, const SharedAlloc* = 0);
// gets or sets a pointer to the global allocator object
static SharedAlloc*
@@ -84,13 +99,13 @@
// returns a unique id of this allocator object
int id () const { return id_; }
- _RWSTD_SIZE_T max_bytes_; // memory pool size
- _RWSTD_SIZE_T max_blocks_; // memory pool size
+ _RWSTD_SIZE_T max_bytes_; // memory pool size in bytes
+ _RWSTD_SIZE_T max_blocks_; // memory pool size in blocks
- _RWSTD_SIZE_T n_bytes_; // number of allocated bytes
- _RWSTD_SIZE_T n_blocks_; // number of allocated blocks
+ _RWSTD_SIZE_T n_bytes_; // number of allocated bytes
+ _RWSTD_SIZE_T n_blocks_; // number of allocated blocks
- _RWSTD_SIZE_T n_refs_; // number of references
+ _RWSTD_SIZE_T n_refs_; // number of references
// counter of the number of calls to each allocator member function
_RWSTD_SIZE_T n_calls_ [n_funs];
@@ -121,7 +136,7 @@
struct UserAlloc
{
// private:
- SharedAlloc* const pal_;
+ SharedAlloc* pal_;
public:
typedef T value_type;
@@ -154,10 +169,21 @@
}
template <class U>
+ void operator= (const UserAlloc<U> &rhs) {
+ pal_->funcall (pal_->m_cvt_assign, rhs.pal_);
+ pal_ = rhs.pal_;
+ }
+
+ template <class U>
struct rebind { typedef UserAlloc<U> other; };
#endif // _RWSTD_NO_INLINE_MEMBER_TEMPLATES
+ void operator= (const UserAlloc &rhs) {
+ pal_->funcall (pal_->m_cpy_assign, rhs.pal_);
+ pal_ = rhs.pal_;
+ }
+
~UserAlloc () {
pal_->funcall (pal_->m_dtor);
}
@@ -204,5 +230,55 @@
}
};
+
+// when (line <= 0) establishes a new check point for memory leaks
+// by storing the number and size of blocks of storage currently
+// allocated by operator new and by the SharedAlloc object pointed
+// to by palloc (when non-zero)
+// when (line > 0) reports the difference between the the number
+// and size of blocks of storage allocated at the last checkpoint
+// and the values specified by expect_blocks and expect_bytes
+_TEST_EXPORT void
+rw_check_leaks (const SharedAlloc* /* palloc */ = 0,
+ int /* line */ = 0,
+ _RWSTD_SIZE_T /* expect_blocks */ = 0,
+ _RWSTD_SIZE_T /* expect_bytes */ = _RWSTD_SIZE_MAX);
+
+
+// when (line <= 0) establishes a new check point for memory leaks
+// by storing the number and size of blocks of storage currently
+// allocated by operator new
+// when (line > 0) reports the difference between the the number
+// and size of blocks of storage allocated at the last checkpoint
+// and the values specified by expect_blocks and expect_bytes
+template <class charT>
+inline void
+rw_check_leaks (const std::allocator<charT>& /* unused */,
+ int line = 0,
+ _RWSTD_SIZE_T expect_blocks = 0,
+ _RWSTD_SIZE_T expect_bytes = _RWSTD_SIZE_MAX)
+{
+ // can't track memory leaks here
+ rw_check_leaks ((SharedAlloc*)0, line, expect_blocks, expect_bytes);
+}
+
+
+// when (line <= 0) establishes a new check point for memory leaks
+// by storing the number and size of blocks of storage currently
+// allocated by operator new and by the user-defined allocator
+// specified by the first argument
+// when (line > 0) reports the difference between the the number
+// and size of blocks of storage allocated at the last checkpoint
+// and the values specified by expect_blocks and expect_bytes
+template <class charT, class Types>
+inline void
+rw_check_leaks (const UserAlloc<charT, Types> &alloc,
+ int line = 0,
+ _RWSTD_SIZE_T expect_blocks = 0,
+ _RWSTD_SIZE_T expect_bytes = _RWSTD_SIZE_MAX)
+{
+ // track memory leaks via SharedAlloc
+ rw_check_leaks (alloc.pal_, line, expect_blocks, expect_bytes);
+}
#endif // RW_ALLOCATOR_INCLUDED
Modified: incubator/stdcxx/trunk/tests/src/allocator.cpp
URL: http://svn.apache.org/viewvc/incubator/stdcxx/trunk/tests/src/allocator.cpp?rev=407397&r1=407396&r2=407397&view=diff
==============================================================================
--- incubator/stdcxx/trunk/tests/src/allocator.cpp (original)
+++ incubator/stdcxx/trunk/tests/src/allocator.cpp Wed May 17 16:25:58 2006
@@ -30,6 +30,7 @@
#include <rw_allocator.h>
#include <rw_new.h> // for operator_new()
+#include <driver.h> // for rw_assert()
#include <new> // for bad_alloc, placement new
#include <stdarg.h> // for va_arg(), va_list
#include <string.h> // for memset()
@@ -39,15 +40,17 @@
static const char* const
_rw_funnames[] = {
"UserAlloc::UserAlloc ()",
- "UserAlloc::UserAlloc (const UserAlloc<U>&)",
"UserAlloc::UserAlloc (const UserAlloc&)",
+ "UserAlloc::UserAlloc (const UserAlloc<U>&)",
"UserAlloc::~UserAlloc ()",
+ "UserAlloc::operator= (const UserAlloc&)",
+ "UserAlloc::operator=<U>(const UserAlloc<U>&)",
"UserAlloc::allocate (size_type, void*)",
"UserAlloc::deallocate (pointer, size_type)",
"UserAlloc::construct (pointer, const_reference)",
"UserAlloc::destroy (pointer)",
- "UserAlloc::address (reference)",
- "UserAlloc::max_size ()"
+ "UserAlloc::address (reference) const",
+ "UserAlloc::max_size () const"
};
static int _rw_id_gen; // generates unique ids
@@ -88,7 +91,7 @@
SharedAlloc::
SharedAlloc (size_t nbytes /* = MAX_SIZE */, size_t nblocks /* = MAX_SIZE */)
: max_bytes_ (nbytes), max_blocks_ (nblocks),
- n_bytes_ (0), n_blocks_ (0), id_ (0)
+ n_bytes_ (0), n_blocks_ (0), n_refs_ (0), id_ (0)
{
memset (n_calls_, 0, sizeof n_calls_);
memset (throw_at_calls_, -1, sizeof throw_at_calls_);
@@ -98,7 +101,25 @@
/* virtual */ SharedAlloc::
~SharedAlloc ()
{
- // no-op
+ static size_t deadbeef = 0;
+ if (0 == deadbeef) {
+ deadbeef = size_t (0xdeadbeefU);
+ if (deadbeef < deadbeef << 1) {
+ // assume 64-bit size_t
+ deadbeef <<= 31;
+ deadbeef <<= 1;
+ deadbeef |= size_t (0xdeadbeefU);
+ }
+ }
+
+ // invalidate
+ size_t n = sizeof n_calls_ / sizeof *n_calls_;
+ for (size_t i = 0; i != n; ++i)
+ n_calls_ [i] = deadbeef;
+
+ n = sizeof throw_at_calls_ / sizeof *throw_at_calls_;
+ for (size_t i = 0; i != n; ++i)
+ throw_at_calls_ [i] = deadbeef;
}
@@ -133,7 +154,7 @@
/* virtual */ size_t SharedAlloc::
-max_size (size_t size)
+max_size (size_t size /* = 1 */)
{
funcall (m_max_size);
@@ -142,7 +163,7 @@
/* virtual */ void SharedAlloc::
-funcall (MemFun mf)
+funcall (MemFun mf, const SharedAlloc *other /* = 0 */)
{
if (m_ctor == mf) {
// ordinary (not a copy or converting) ctor
@@ -162,6 +183,27 @@
// increment the number of references to this allocator
++n_refs_;
}
+ else if (m_cpy_assign == mf || m_cvt_assign == mf) {
+ // assignment operator
+ RW_ASSERT (0 <= id_ && id_ <= _rw_id_gen);
+ RW_ASSERT (0 < n_refs_);
+
+ RW_ASSERT (0 != other);
+
+ if (this != other) {
+ // decrement the number of references and invalidate
+ // id if no object refers to *this
+ if (0 == --n_refs_)
+ id_ = -1;
+
+ SharedAlloc* const po = _RWSTD_CONST_CAST (SharedAlloc*, other);
+
+ if (other->id_ <= 0)
+ po->id_ = ++_rw_id_gen;
+
+ ++po->n_refs_;
+ }
+ }
else if (m_dtor == mf) {
// dtor
RW_ASSERT (0 <= id_ && id_ <= _rw_id_gen);
@@ -210,4 +252,76 @@
RW_ASSERT (0 != pinst);
return pinst;
+}
+
+/**************************************************************************/
+
+static void
+_rw_check_leaks (int line, size_t expect_blocks, size_t expect_bytes)
+{
+ if (0 < line) {
+ // determine and report memory leaks since last checkpoint
+
+ /* const */ size_t nbytes;
+ const size_t nblocks = rwt_check_leaks (&nbytes, 0);
+
+ if (_RWSTD_SIZE_MAX == expect_blocks)
+ expect_blocks = nblocks;
+
+ if (_RWSTD_SIZE_MAX == expect_bytes)
+ expect_bytes = nbytes;
+
+ rw_assert (nblocks == expect_blocks && nbytes == expect_bytes,
+ 0, line,
+ "line %d. %{$FUNCALL} operator new allocated "
+ "%zu bytes in %zu blocks, expected %zu bytes "
+ "in %zu blocks",
+ __LINE__, nbytes, nblocks,
+ expect_bytes, expect_blocks);
+ }
+ else {
+ // establish a checkpoint for memory leaks
+ rwt_check_leaks (0, 0);
+ }
+}
+
+
+_TEST_EXPORT void
+rw_check_leaks (const SharedAlloc *palloc /* = 0 */,
+ int line /* = 0 */,
+ size_t expect_blocks /* = 0 */,
+ size_t expect_bytes /* = -1 */)
+{
+ _rw_check_leaks (line, expect_blocks, expect_bytes);
+
+ if (0 == palloc)
+ return;
+
+ static size_t nbytes;
+ static size_t nblocks;
+
+ if (0 < line) {
+ // determine and report memory leaks since last checkpoint
+ const size_t leaked_bytes = palloc->n_bytes_ - nbytes;
+ const size_t leaked_blocks = palloc->n_blocks_ - nblocks;
+
+ if (_RWSTD_SIZE_MAX == expect_blocks) // don't care
+ expect_blocks = leaked_blocks;
+
+ if (_RWSTD_SIZE_MAX == expect_bytes) // don't care
+ expect_bytes = nbytes;
+
+ rw_assert ( leaked_blocks == expect_blocks
+ && leaked_bytes == expect_bytes, 0, line,
+ "line %d. %{$FUNCALL} UserAlloc allocated "
+ "%zu bytes in %zu blocks, expected %zu bytes "
+ "in %zu blocks",
+ __LINE__, leaked_bytes, leaked_blocks,
+ expect_bytes, expect_blocks);
+ }
+ else {
+ // establish a checkpoint for memory leaks
+ nbytes = palloc->n_bytes_;
+ nblocks = palloc->n_blocks_;
+ }
}