]> oss.titaniummirror.com Git - msp430-gcc.git/blobdiff - libstdc++-v3/include/ext/pool_allocator.h
Imported gcc-4.4.3
[msp430-gcc.git] / libstdc++-v3 / include / ext / pool_allocator.h
diff --git a/libstdc++-v3/include/ext/pool_allocator.h b/libstdc++-v3/include/ext/pool_allocator.h
new file mode 100644 (file)
index 0000000..87d145d
--- /dev/null
@@ -0,0 +1,263 @@
+// Allocators -*- C++ -*-
+
+// Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
+// Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+/*
+ * Copyright (c) 1996-1997
+ * Silicon Graphics Computer Systems, Inc.
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Silicon Graphics makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ */
+
+/** @file ext/pool_allocator.h
+ *  This file is a GNU extension to the Standard C++ Library.
+ */
+
+#ifndef _POOL_ALLOCATOR_H
+#define _POOL_ALLOCATOR_H 1
+
+#include <bits/c++config.h>
+#include <cstdlib>
+#include <new>
+#include <bits/functexcept.h>
+#include <ext/atomicity.h>
+#include <ext/concurrence.h>
+#include <bits/move.h>
+
+_GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)
+
+  using std::size_t;
+  using std::ptrdiff_t;
+
+  /**
+   *  @brief  Base class for __pool_alloc.
+   *
+   *  Uses various allocators to fulfill underlying requests (and makes as
+   *  few requests as possible when in default high-speed pool mode).
+   *
+   *  Important implementation properties:
+   *  0. If globally mandated, then allocate objects from new
+   *  1. If the clients request an object of size > _S_max_bytes, the resulting
+   *     object will be obtained directly from new
+   *  2. In all other cases, we allocate an object of size exactly
+   *     _S_round_up(requested_size).  Thus the client has enough size
+   *     information that we can return the object to the proper free list
+   *     without permanently losing part of the object.
+   */
+    class __pool_alloc_base
+    {
+    protected:
+
+      enum { _S_align = 8 };
+      enum { _S_max_bytes = 128 };
+      enum { _S_free_list_size = (size_t)_S_max_bytes / (size_t)_S_align };
+      
+      union _Obj
+      {
+       union _Obj* _M_free_list_link;
+       char        _M_client_data[1];    // The client sees this.
+      };
+      
+      static _Obj* volatile         _S_free_list[_S_free_list_size];
+
+      // Chunk allocation state.
+      static char*                  _S_start_free;
+      static char*                  _S_end_free;
+      static size_t                 _S_heap_size;     
+      
+      size_t
+      _M_round_up(size_t __bytes)
+      { return ((__bytes + (size_t)_S_align - 1) & ~((size_t)_S_align - 1)); }
+      
+      _Obj* volatile*
+      _M_get_free_list(size_t __bytes);
+    
+      __mutex&
+      _M_get_mutex();
+
+      // Returns an object of size __n, and optionally adds to size __n
+      // free list.
+      void*
+      _M_refill(size_t __n);
+      
+      // Allocates a chunk for nobjs of size size.  nobjs may be reduced
+      // if it is inconvenient to allocate the requested number.
+      char*
+      _M_allocate_chunk(size_t __n, int& __nobjs);
+    };
+
+
+  /**
+   * @brief  Allocator using a memory pool with a single lock.
+   * @ingroup allocators
+   */
+  template<typename _Tp>
+    class __pool_alloc : private __pool_alloc_base
+    {
+    private:
+      static _Atomic_word          _S_force_new;
+
+    public:
+      typedef size_t     size_type;
+      typedef ptrdiff_t  difference_type;
+      typedef _Tp*       pointer;
+      typedef const _Tp* const_pointer;
+      typedef _Tp&       reference;
+      typedef const _Tp& const_reference;
+      typedef _Tp        value_type;
+
+      template<typename _Tp1>
+        struct rebind
+        { typedef __pool_alloc<_Tp1> other; };
+
+      __pool_alloc() throw() { }
+
+      __pool_alloc(const __pool_alloc&) throw() { }
+
+      template<typename _Tp1>
+        __pool_alloc(const __pool_alloc<_Tp1>&) throw() { }
+
+      ~__pool_alloc() throw() { }
+
+      pointer
+      address(reference __x) const { return &__x; }
+
+      const_pointer
+      address(const_reference __x) const { return &__x; }
+
+      size_type
+      max_size() const throw() 
+      { return size_t(-1) / sizeof(_Tp); }
+
+      // _GLIBCXX_RESOLVE_LIB_DEFECTS
+      // 402. wrong new expression in [some_] allocator::construct
+      void 
+      construct(pointer __p, const _Tp& __val) 
+      { ::new((void *)__p) _Tp(__val); }
+
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+      template<typename... _Args>
+        void
+        construct(pointer __p, _Args&&... __args)
+       { ::new((void *)__p) _Tp(std::forward<_Args>(__args)...); }
+#endif
+
+      void 
+      destroy(pointer __p) { __p->~_Tp(); }
+
+      pointer
+      allocate(size_type __n, const void* = 0);
+
+      void
+      deallocate(pointer __p, size_type __n);      
+    };
+
+  template<typename _Tp>
+    inline bool
+    operator==(const __pool_alloc<_Tp>&, const __pool_alloc<_Tp>&)
+    { return true; }
+
+  template<typename _Tp>
+    inline bool
+    operator!=(const __pool_alloc<_Tp>&, const __pool_alloc<_Tp>&)
+    { return false; }
+
+  template<typename _Tp>
+    _Atomic_word
+    __pool_alloc<_Tp>::_S_force_new;
+
+  template<typename _Tp>
+    _Tp*
+    __pool_alloc<_Tp>::allocate(size_type __n, const void*)
+    {
+      pointer __ret = 0;
+      if (__builtin_expect(__n != 0, true))
+       {
+         if (__builtin_expect(__n > this->max_size(), false))
+           std::__throw_bad_alloc();
+
+         // If there is a race through here, assume answer from getenv
+         // will resolve in same direction.  Inspired by techniques
+         // to efficiently support threading found in basic_string.h.
+         if (_S_force_new == 0)
+           {
+             if (std::getenv("GLIBCXX_FORCE_NEW"))
+               __atomic_add_dispatch(&_S_force_new, 1);
+             else
+               __atomic_add_dispatch(&_S_force_new, -1);
+           }
+
+         const size_t __bytes = __n * sizeof(_Tp);           
+         if (__bytes > size_t(_S_max_bytes) || _S_force_new > 0)
+           __ret = static_cast<_Tp*>(::operator new(__bytes));
+         else
+           {
+             _Obj* volatile* __free_list = _M_get_free_list(__bytes);
+             
+             __scoped_lock sentry(_M_get_mutex());
+             _Obj* __restrict__ __result = *__free_list;
+             if (__builtin_expect(__result == 0, 0))
+               __ret = static_cast<_Tp*>(_M_refill(_M_round_up(__bytes)));
+             else
+               {
+                 *__free_list = __result->_M_free_list_link;
+                 __ret = reinterpret_cast<_Tp*>(__result);
+               }
+             if (__builtin_expect(__ret == 0, 0))
+               std::__throw_bad_alloc();
+           }
+       }
+      return __ret;
+    }
+
+  template<typename _Tp>
+    void
+    __pool_alloc<_Tp>::deallocate(pointer __p, size_type __n)
+    {
+      if (__builtin_expect(__n != 0 && __p != 0, true))
+       {
+         const size_t __bytes = __n * sizeof(_Tp);
+         if (__bytes > static_cast<size_t>(_S_max_bytes) || _S_force_new > 0)
+           ::operator delete(__p);
+         else
+           {
+             _Obj* volatile* __free_list = _M_get_free_list(__bytes);
+             _Obj* __q = reinterpret_cast<_Obj*>(__p);
+
+             __scoped_lock sentry(_M_get_mutex());
+             __q ->_M_free_list_link = *__free_list;
+             *__free_list = __q;
+           }
+       }
+    }
+
+_GLIBCXX_END_NAMESPACE
+
+#endif