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