// MT-optimized allocator -*- C++ -*-
-// Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+// Copyright (C) 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 2, or (at your option)
+// 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,
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
-// You should have received a copy of the GNU General Public License along
-// with this library; see the file COPYING. If not, write to the Free
-// Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
-// USA.
+// 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.
-// As a special exception, you may use this file as part of a free software
-// library without restriction. Specifically, if other files instantiate
-// templates or use macros or inline functions from this file, or you compile
-// this file and link it with other files to produce an executable, this
-// file does not by itself cause the resulting executable to be covered by
-// the GNU General Public License. This exception does not however
-// invalidate any other reasons why the executable file might be covered by
-// the GNU General Public License.
+// 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/>.
/** @file ext/mt_allocator.h
* This file is a GNU extension to the Standard C++ Library.
#include <new>
#include <cstdlib>
#include <bits/functexcept.h>
-#include <bits/gthr.h>
-#include <bits/atomicity.h>
+#include <ext/atomicity.h>
+#include <bits/move.h>
_GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)
typedef void (*__destroy_handler)(void*);
- /// @brief Base class for pool object.
+ /// Base class for pool object.
struct __pool_base
{
// Using short int as type for the binmap implies we are never
- // caching blocks larger than 65535 with this allocator.
+ // caching blocks larger than 32768 with this allocator.
typedef unsigned short int _Binmap_type;
// Variables used to configure the behavior of the allocator,
// Allocation requests (after round-up to power of 2) below
// this value will be handled by the allocator. A raw new/
// call will be used for requests larger than this value.
+ // NB: Must be much smaller than _M_chunk_size and in any
+ // case <= 32768.
size_t _M_max_bytes;
-
+
// Size in bytes of the smallest bin.
- // NB: Must be a power of 2 and >= _M_align.
+ // NB: Must be a power of 2 and >= _M_align (and of course
+ // much smaller than _M_max_bytes).
size_t _M_min_bin;
-
+
// In order to avoid fragmenting and minimize the number of
// new() calls we always request new memory using this
// value. Based on previous discussions on the libstdc++
- // mailing list we have choosen the value below.
+ // mailing list we have chosen the value below.
// See http://gcc.gnu.org/ml/libstdc++/2001-07/msg00077.html
+ // NB: At least one order of magnitude > _M_max_bytes.
size_t _M_chunk_size;
-
+
// The maximum number of supported threads. For
// single-threaded operation, use one. Maximum values will
// vary depending on details of the underlying system. (For
// /proc/sys/kernel/threads-max, while Linux 2.6.6 reports
// 65534)
size_t _M_max_threads;
-
+
// Each time a deallocation occurs in a threaded application
// we make sure that there are no more than
// _M_freelist_headroom % of used memory on the freelist. If
_M_get_binmap(size_t __bytes)
{ return _M_binmap[__bytes]; }
- const size_t
+ size_t
_M_get_align()
{ return _M_options._M_align; }
union _Block_record
{
// Points to the block_record of the next free block.
- _Block_record* volatile _M_next;
+ _Block_record* _M_next;
};
struct _Bin_record
{
// An "array" of pointers to the first free block.
- _Block_record** volatile _M_first;
+ _Block_record** _M_first;
// A list of the initial addresses of all allocated blocks.
_Block_address* _M_address;
// An "array" of bin_records each of which represents a specific
// power of 2 size. Memory to this "array" is allocated in
// _M_initialize().
- _Bin_record* volatile _M_bin;
+ _Bin_record* _M_bin;
// Actual value calculated in _M_initialize().
size_t _M_bin_size;
struct _Thread_record
{
// Points to next free thread id record. NULL if last record in list.
- _Thread_record* volatile _M_next;
+ _Thread_record* _M_next;
// Thread id ranging from 1 to _S_max_threads.
size_t _M_id;
union _Block_record
{
// Points to the block_record of the next free block.
- _Block_record* volatile _M_next;
+ _Block_record* _M_next;
// The thread id of the thread which has requested this block.
size_t _M_thread_id;
// An "array" of pointers to the first free block for each
// thread id. Memory to this "array" is allocated in
// _S_initialize() for _S_max_threads + global pool 0.
- _Block_record** volatile _M_first;
+ _Block_record** _M_first;
// A list of the initial addresses of all allocated blocks.
_Block_address* _M_address;
// An "array" of counters used to keep track of the amount of
// blocks that are on the freelist/used for each thread id.
- // Memory to these "arrays" is allocated in _S_initialize() for
- // _S_max_threads + global pool 0.
- size_t* volatile _M_free;
- size_t* volatile _M_used;
+ // - Note that the second part of the allocated _M_used "array"
+ // actually hosts (atomic) counters of reclaimed blocks: in
+ // _M_reserve_block and in _M_reclaim_block those numbers are
+ // subtracted from the first ones to obtain the actual size
+ // of the "working set" of the given thread.
+ // - Memory to these "arrays" is allocated in _S_initialize()
+ // for _S_max_threads + global pool 0.
+ size_t* _M_free;
+ size_t* _M_used;
// Each bin has its own mutex which is used to ensure data
// integrity while changing "ownership" on a block. The mutex
// An "array" of bin_records each of which represents a specific
// power of 2 size. Memory to this "array" is allocated in
// _M_initialize().
- _Bin_record* volatile _M_bin;
+ _Bin_record* _M_bin;
// Actual value calculated in _M_initialize().
size_t _M_bin_size;
};
#endif
- /// @brief Policy for shared __pool objects.
+ /// Policy for shared __pool objects.
template<template <bool> class _PoolTp, bool _Thread>
struct __common_pool_policy : public __common_pool_base<_PoolTp, _Thread>
{
};
#endif
- /// @brief Policy for individual __pool objects.
+ /// Policy for individual __pool objects.
template<typename _Tp, template <bool> class _PoolTp, bool _Thread>
struct __per_type_pool_policy
: public __per_type_pool_base<_Tp, _PoolTp, _Thread>
};
- /// @brief Base class for _Tp dependent member functions.
+ /// Base class for _Tp dependent member functions.
template<typename _Tp>
class __mt_alloc_base
{
// 402. wrong new expression in [some_] allocator::construct
void
construct(pointer __p, const _Tp& __val)
- { ::new(__p) _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(); }
* size per thread plus a "global" one. Steps are taken to limit
* the per thread freelist sizes (by returning excess back to
* the "global" list).
+ * @ingroup allocators
*
* Further details:
- * http://gcc.gnu.org/onlinedocs/libstdc++/ext/mt_allocator.html
+ * http://gcc.gnu.org/onlinedocs/libstdc++/manual/bk01pt12ch32.html
*/
template<typename _Tp,
typename _Poolp = __common_pool_policy<__pool, __thread_default> >