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/15 01:23:20 UTC
svn commit: r406469 - in /incubator/stdcxx/trunk/tests:
include/rw_allocator.h src/allocator.cpp
Author: sebor
Date: Sun May 14 16:23:18 2006
New Revision: 406469
URL: http://svn.apache.org/viewcvs?rev=406469&view=rev
Log:
2006-05-14 Martin Sebor <se...@roguewave.com>
* rw_allocator.h: New header with the definition of a user-defined
allocator class template.
* allocator.cpp: New source containing definitions of helper classes
and functions used by the user-defined allocator template.
Added:
incubator/stdcxx/trunk/tests/include/rw_allocator.h (with props)
incubator/stdcxx/trunk/tests/src/allocator.cpp (with props)
Added: incubator/stdcxx/trunk/tests/include/rw_allocator.h
URL: http://svn.apache.org/viewcvs/incubator/stdcxx/trunk/tests/include/rw_allocator.h?rev=406469&view=auto
==============================================================================
--- incubator/stdcxx/trunk/tests/include/rw_allocator.h (added)
+++ incubator/stdcxx/trunk/tests/include/rw_allocator.h Sun May 14 16:23:18 2006
@@ -0,0 +1,208 @@
+/**************************************************************************
+ *
+ * rw_allocator.h - user-defined allocator type
+ *
+ * $Id$
+ *
+ ***************************************************************************
+ *
+ * Copyright 2006 The Apache Software Foundation or its licensors,
+ * as applicable.
+ *
+ * Copyright 2006 Rogue Wave Software.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ **************************************************************************/
+
+#ifndef RW_ALLOCATOR_INCLUDED
+#define RW_ALLOCATOR_INCLUDED
+
+
+#include <testdefs.h>
+
+
+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_allocate, m_deallocate,
+ m_construct, m_destroy,
+ m_address, m_max_size,
+ n_funs
+ };
+
+ // constructs an allocator object managing a memory pool
+ // of the specified size (bytes and blocks)
+ SharedAlloc (_RWSTD_SIZE_T /* max_bytes */ = _RWSTD_SIZE_MAX,
+ _RWSTD_SIZE_T /* max_blocks */ = _RWSTD_SIZE_MAX);
+
+ virtual ~SharedAlloc ();
+
+ // attempts to allocate storage for nelems objects of elemsize
+ // bytes each and returns a pointer to the allocated storage
+ // on success; throws std::bad_alloc on failure
+ virtual void*
+ allocate (_RWSTD_SIZE_T /* nelems */,
+ _RWSTD_SIZE_T /* elemsize */,
+ const void* /* hint */);
+
+ // deallocates storage at ptr allocated by a call to allocate
+ // for nelems objects of elemsize bytes each
+ virtual void
+ deallocate (void* /* ptr */,
+ _RWSTD_SIZE_T /* nelems */,
+ _RWSTD_SIZE_T /* elemsize */);
+
+ // 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 */);
+
+ // 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 */);
+
+ // gets or sets a pointer to the global allocator object
+ static SharedAlloc*
+ instance (SharedAlloc* = 0);
+
+ // 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 n_bytes_; // number of allocated bytes
+ _RWSTD_SIZE_T n_blocks_; // number of allocated blocks
+
+ _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];
+
+ // member function counter value that, when reached, will cause
+ // an exception derived from std::bad_alloc to be thrown
+ _RWSTD_SIZE_T throw_at_calls_ [n_funs];
+
+private:
+ int id_;
+};
+
+
+// allocator types for easy specialization
+template <class T>
+struct AllocTypes
+{
+ typedef _RWSTD_SIZE_T size_type;
+ typedef _RWSTD_PTRDIFF_T difference_type;
+ typedef T* pointer;
+ typedef const T* const_pointer;
+ typedef T& reference;
+ typedef const T& const_reference;
+};
+
+
+template <class T, class Types = AllocTypes<T> >
+struct UserAlloc
+{
+// private:
+ SharedAlloc* const pal_;
+
+public:
+ typedef T value_type;
+ typedef typename Types::size_type size_type;
+ typedef typename Types::difference_type difference_type;
+ typedef typename Types::pointer pointer;
+ typedef typename Types::const_pointer const_pointer;
+ typedef typename Types::reference reference;
+ typedef typename Types::const_reference const_reference;
+
+ UserAlloc (SharedAlloc *pal = 0) _THROWS (())
+ : pal_ (pal ? pal : SharedAlloc::instance ()) {
+ RW_ASSERT (0 != pal_);
+ pal_->funcall (pal_->m_ctor);
+ }
+
+ UserAlloc (const UserAlloc &rhs) _THROWS (())
+ : pal_ (rhs.pal_) {
+ RW_ASSERT (0 != pal_);
+ pal_->funcall (pal_->m_cpy_ctor);
+ }
+
+#ifndef _RWSTD_NO_INLINE_MEMBER_TEMPLATES
+
+ template <class U>
+ UserAlloc (const UserAlloc<U> &rhs) _THROWS (())
+ : pal_ (rhs.pal_) {
+ RW_ASSERT (0 != pal_);
+ pal_->funcall (pal_->m_cvt_ctor);
+ }
+
+ template <class U>
+ struct rebind { typedef UserAlloc<U> other; };
+
+#endif // _RWSTD_NO_INLINE_MEMBER_TEMPLATES
+
+ ~UserAlloc () {
+ pal_->funcall (pal_->m_dtor);
+ }
+
+ pointer allocate (size_type nelems, const void *hint = 0) {
+ void* const ptr = pal_->allocate (nelems, sizeof (value_type), hint);
+ return _RWSTD_STATIC_CAST (pointer, ptr);
+ }
+
+ void deallocate (pointer ptr, size_type nelems) {
+ pal_->deallocate (ptr, nelems, sizeof (value_type));
+ }
+
+ void construct (pointer ptr, const_reference val) {
+ pal_->funcall (pal_->m_construct);
+ new (ptr) value_type (val);
+ }
+
+ void destroy (pointer ptr) {
+ pal_->funcall (pal_->m_destroy);
+ ptr->~T ();
+ }
+
+ pointer address (reference ref) const {
+ pal_->funcall (pal_->m_address);
+ return &ref;
+ }
+
+ const_pointer address (const_reference ref) const {
+ pal_->funcall (pal_->m_address);
+ return &ref;
+ }
+
+ size_type max_size () const _THROWS (()) {
+ return pal_->max_size (sizeof (value_type));
+ }
+
+ bool operator== (const UserAlloc &rhs) const {
+ return pal_->id () == rhs.pal_->id ();
+ }
+
+ bool operator!= (const UserAlloc &rhs) const {
+ return !operator== (rhs);
+ }
+};
+
+
+#endif // RW_ALLOCATOR_INCLUDED
Propchange: incubator/stdcxx/trunk/tests/include/rw_allocator.h
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: incubator/stdcxx/trunk/tests/include/rw_allocator.h
------------------------------------------------------------------------------
svn:keywords = Id
Added: incubator/stdcxx/trunk/tests/src/allocator.cpp
URL: http://svn.apache.org/viewcvs/incubator/stdcxx/trunk/tests/src/allocator.cpp?rev=406469&view=auto
==============================================================================
--- incubator/stdcxx/trunk/tests/src/allocator.cpp (added)
+++ incubator/stdcxx/trunk/tests/src/allocator.cpp Sun May 14 16:23:18 2006
@@ -0,0 +1,212 @@
+/************************************************************************
+ *
+ * allocator.cpp - definitions of allocator testsuite helpers
+ *
+ * $Id$
+ *
+ ************************************************************************
+ *
+ * Copyright 2006 The Apache Software Foundation or its licensors,
+ * as applicable.
+ *
+ * Copyright 2006 Rogue Wave Software.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ **************************************************************************/
+
+// expand _TEST_EXPORT macros
+#define _RWSTD_TEST_SRC
+
+#include <rw_allocator.h>
+#include <new> // for bad_alloc
+#include <stdarg.h> // for va_arg(), va_list
+#include <string.h> // for memset()
+
+/**************************************************************************/
+
+static const char* const
+_rw_funnames[] = {
+ "UserAlloc::UserAlloc ()",
+ "UserAlloc::UserAlloc (const UserAlloc<U>&)",
+ "UserAlloc::UserAlloc (const UserAlloc&)",
+ "UserAlloc::~UserAlloc ()",
+ "UserAlloc::allocate (size_type, void*)",
+ "UserAlloc::deallocate (pointer, size_type)",
+ "UserAlloc::construct (pointer, const_reference)",
+ "UserAlloc::destroy (pointer)",
+ "UserAlloc::address (reference)",
+ "UserAlloc::max_size ()"
+};
+
+static int _rw_id_gen; // generates unique ids
+
+/**************************************************************************/
+
+_TEST_EXPORT int
+rw_vasnprintf (char**, size_t*, const char*, va_list);
+
+
+static void
+_rw_throw_exception (const char *file, int line, const char *fmt, ...)
+{
+ struct BadSharedAlloc: _RWSTD_BAD_ALLOC {
+ char what_ [4096];
+
+ /* virtual */ const char* what () const _THROWS (()) {
+ return what_;
+ }
+ };
+
+ BadSharedAlloc ex;
+
+ va_list va;
+ va_start (va, fmt);
+
+ char *buf = ex.what_;
+ size_t bufsize = sizeof ex.what_;
+ rw_vasnprintf (&buf, &bufsize, fmt, va);
+
+ va_end (va);
+
+ throw ex;
+}
+
+/**************************************************************************/
+
+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)
+{
+ memset (n_calls_, 0, sizeof n_calls_);
+ memset (throw_at_calls_, -1, sizeof throw_at_calls_);
+}
+
+
+/* virtual */ SharedAlloc::
+~SharedAlloc ()
+{
+ // no-op
+}
+
+
+/* virtual */ void* SharedAlloc::
+allocate (size_t nelems, size_t size, const void* /* = 0 */)
+{
+ funcall (m_allocate);
+
+ const size_t nbytes = nelems * size;
+
+ if (max_blocks_ < n_blocks_ + nelems)
+ _rw_throw_exception (__FILE__, __LINE__,
+ "allocate (%zu): reached block limit of %zu",
+ nbytes, max_blocks_);
+
+ if (max_bytes_ < n_bytes_ + nbytes)
+ _rw_throw_exception (__FILE__, __LINE__,
+ "allocate (%zu): reached size limit of %zu",
+ nbytes, max_bytes_);
+
+ return operator new (nbytes);
+}
+
+
+/* virtual */ void SharedAlloc::
+deallocate (void *ptr, size_t nelems, size_t size)
+{
+ funcall (m_deallocate);
+
+ return operator delete (ptr);
+}
+
+
+/* virtual */ size_t SharedAlloc::
+max_size (size_t size)
+{
+ funcall (m_max_size);
+
+ return max_blocks_ / size;
+}
+
+
+/* virtual */ void SharedAlloc::
+funcall (MemFun mf)
+{
+ if (m_ctor == mf) {
+ // ordinary (not a copy or converting) ctor
+ if (id_ <= 0) {
+ RW_ASSERT (0 == n_refs_);
+ id_ = ++_rw_id_gen;
+ }
+
+ // increment the number of references to this allocator
+ ++n_refs_;
+ }
+ else if (m_cpy_ctor == mf || m_cvt_ctor == mf) {
+ // copy or converting ctor
+ RW_ASSERT (0 < id_);
+ RW_ASSERT (0 < n_refs_);
+
+ // increment the number of references to this allocator
+ ++n_refs_;
+ }
+ else if (m_dtor == mf) {
+ // dtor
+ RW_ASSERT (0 <= id_ && id_ <= _rw_id_gen);
+ RW_ASSERT (0 < n_refs_);
+
+ // decrement the number of references and invalidate
+ // id if no object refers to *this
+ if (0 == --n_refs_)
+ id_ = -1;
+ }
+
+ // check the number of calls and throw an exception
+ // if the specified limit has been reached
+ if (n_calls_ [mf] == throw_at_calls_ [mf])
+ _rw_throw_exception (__FILE__, __LINE__,
+ "%s: reached call limit of %zu",
+ _rw_funnames [mf], throw_at_calls_);
+
+ // increment the number of calls
+ ++n_calls_ [mf];
+}
+
+
+/* static */ SharedAlloc* SharedAlloc::
+instance (SharedAlloc *pinst /* = 0 */)
+{
+ // get or a set a pointer to the global allocator object
+ static size_t instbuf [sizeof (SharedAlloc) / sizeof (size_t) + 1];
+ static SharedAlloc* pglobal = 0;
+
+ if (pinst) {
+ // set the global allocator object and return
+ // a pointer to the old one (may be 0)
+ SharedAlloc* const tmp = pglobal;
+ pglobal = pinst;
+ pinst = tmp;
+ }
+ else if (0 == pglobal) {
+ // construct the global allocator object
+ pglobal = new (instbuf) SharedAlloc ();
+ pinst = pglobal;
+ }
+ else
+ pinst = pglobal;
+
+ RW_ASSERT (0 != pinst);
+
+ return pinst;
+}
Propchange: incubator/stdcxx/trunk/tests/src/allocator.cpp
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: incubator/stdcxx/trunk/tests/src/allocator.cpp
------------------------------------------------------------------------------
svn:keywords = Id