epoc32/include/stdapis/boost/detail/quick_allocator.hpp
branchSymbian2
changeset 2 2fe1408b6811
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/epoc32/include/stdapis/boost/detail/quick_allocator.hpp	Tue Mar 16 16:12:26 2010 +0000
     1.3 @@ -0,0 +1,198 @@
     1.4 +#ifndef BOOST_DETAIL_QUICK_ALLOCATOR_HPP_INCLUDED
     1.5 +#define BOOST_DETAIL_QUICK_ALLOCATOR_HPP_INCLUDED
     1.6 +
     1.7 +// MS compatible compilers support #pragma once
     1.8 +
     1.9 +#if defined(_MSC_VER) && (_MSC_VER >= 1020)
    1.10 +# pragma once
    1.11 +#endif
    1.12 +
    1.13 +//
    1.14 +//  detail/quick_allocator.hpp
    1.15 +//
    1.16 +//  Copyright (c) 2003 David Abrahams
    1.17 +//  Copyright (c) 2003 Peter Dimov
    1.18 +//
    1.19 +// Distributed under the Boost Software License, Version 1.0. (See
    1.20 +// accompanying file LICENSE_1_0.txt or copy at
    1.21 +// http://www.boost.org/LICENSE_1_0.txt)
    1.22 +//
    1.23 +
    1.24 +#include <boost/config.hpp>
    1.25 +
    1.26 +#include <boost/detail/lightweight_mutex.hpp>
    1.27 +#include <boost/type_traits/type_with_alignment.hpp>
    1.28 +#include <boost/type_traits/alignment_of.hpp>
    1.29 +
    1.30 +#include <new>              // ::operator new, ::operator delete
    1.31 +#include <cstddef>          // std::size_t
    1.32 +
    1.33 +namespace boost
    1.34 +{
    1.35 +
    1.36 +namespace detail
    1.37 +{
    1.38 +
    1.39 +template<unsigned size, unsigned align_> union freeblock
    1.40 +{
    1.41 +    typedef typename boost::type_with_alignment<align_>::type aligner_type;
    1.42 +    aligner_type aligner;
    1.43 +    char bytes[size];
    1.44 +    freeblock * next;
    1.45 +};
    1.46 +
    1.47 +template<unsigned size, unsigned align_> struct allocator_impl
    1.48 +{
    1.49 +    typedef freeblock<size, align_> block;
    1.50 +
    1.51 +    // It may seem odd to use such small pages.
    1.52 +    //
    1.53 +    // However, on a typical Windows implementation that uses
    1.54 +    // the OS allocator, "normal size" pages interact with the
    1.55 +    // "ordinary" operator new, slowing it down dramatically.
    1.56 +    //
    1.57 +    // 512 byte pages are handled by the small object allocator,
    1.58 +    // and don't interfere with ::new.
    1.59 +    //
    1.60 +    // The other alternative is to use much bigger pages (1M.)
    1.61 +    //
    1.62 +    // It is surprisingly easy to hit pathological behavior by
    1.63 +    // varying the page size. g++ 2.96 on Red Hat Linux 7.2,
    1.64 +    // for example, passionately dislikes 496. 512 seems OK.
    1.65 +
    1.66 +#if defined(BOOST_QA_PAGE_SIZE)
    1.67 +
    1.68 +    enum { items_per_page = BOOST_QA_PAGE_SIZE / size };
    1.69 +
    1.70 +#else
    1.71 +
    1.72 +    enum { items_per_page = 512 / size }; // 1048560 / size
    1.73 +
    1.74 +#endif
    1.75 +
    1.76 +#ifdef BOOST_HAS_THREADS
    1.77 +
    1.78 +    static lightweight_mutex & mutex()
    1.79 +    {
    1.80 +        static lightweight_mutex m;
    1.81 +        return m;
    1.82 +    }
    1.83 +
    1.84 +    static lightweight_mutex * mutex_init;
    1.85 +
    1.86 +#endif
    1.87 +
    1.88 +    static block * free;
    1.89 +    static block * page;
    1.90 +    static unsigned last;
    1.91 +
    1.92 +    static inline void * alloc()
    1.93 +    {
    1.94 +#ifdef BOOST_HAS_THREADS
    1.95 +        lightweight_mutex::scoped_lock lock( mutex() );
    1.96 +#endif
    1.97 +        if(block * x = free)
    1.98 +        {
    1.99 +            free = x->next;
   1.100 +            return x;
   1.101 +        }
   1.102 +        else
   1.103 +        {
   1.104 +            if(last == items_per_page)
   1.105 +            {
   1.106 +                // "Listen to me carefully: there is no memory leak"
   1.107 +                // -- Scott Meyers, Eff C++ 2nd Ed Item 10
   1.108 +                page = ::new block[items_per_page];
   1.109 +                last = 0;
   1.110 +            }
   1.111 +
   1.112 +            return &page[last++];
   1.113 +        }
   1.114 +    }
   1.115 +
   1.116 +    static inline void * alloc(std::size_t n)
   1.117 +    {
   1.118 +        if(n != size) // class-specific new called for a derived object
   1.119 +        {
   1.120 +            return ::operator new(n);
   1.121 +        }
   1.122 +        else
   1.123 +        {
   1.124 +#ifdef BOOST_HAS_THREADS
   1.125 +            lightweight_mutex::scoped_lock lock( mutex() );
   1.126 +#endif
   1.127 +            if(block * x = free)
   1.128 +            {
   1.129 +                free = x->next;
   1.130 +                return x;
   1.131 +            }
   1.132 +            else
   1.133 +            {
   1.134 +                if(last == items_per_page)
   1.135 +                {
   1.136 +                    page = ::new block[items_per_page];
   1.137 +                    last = 0;
   1.138 +                }
   1.139 +
   1.140 +                return &page[last++];
   1.141 +            }
   1.142 +        }
   1.143 +    }
   1.144 +
   1.145 +    static inline void dealloc(void * pv)
   1.146 +    {
   1.147 +        if(pv != 0) // 18.4.1.1/13
   1.148 +        {
   1.149 +#ifdef BOOST_HAS_THREADS
   1.150 +            lightweight_mutex::scoped_lock lock( mutex() );
   1.151 +#endif
   1.152 +            block * pb = static_cast<block *>(pv);
   1.153 +            pb->next = free;
   1.154 +            free = pb;
   1.155 +        }
   1.156 +    }
   1.157 +
   1.158 +    static inline void dealloc(void * pv, std::size_t n)
   1.159 +    {
   1.160 +        if(n != size) // class-specific delete called for a derived object
   1.161 +        {
   1.162 +            ::operator delete(pv);
   1.163 +        }
   1.164 +        else if(pv != 0) // 18.4.1.1/13
   1.165 +        {
   1.166 +#ifdef BOOST_HAS_THREADS
   1.167 +            lightweight_mutex::scoped_lock lock( mutex() );
   1.168 +#endif
   1.169 +            block * pb = static_cast<block *>(pv);
   1.170 +            pb->next = free;
   1.171 +            free = pb;
   1.172 +        }
   1.173 +    }
   1.174 +};
   1.175 +
   1.176 +#ifdef BOOST_HAS_THREADS
   1.177 +
   1.178 +template<unsigned size, unsigned align_>
   1.179 +  lightweight_mutex * allocator_impl<size, align_>::mutex_init = &allocator_impl<size, align_>::mutex();
   1.180 +
   1.181 +#endif
   1.182 +
   1.183 +template<unsigned size, unsigned align_>
   1.184 +  freeblock<size, align_> * allocator_impl<size, align_>::free = 0;
   1.185 +
   1.186 +template<unsigned size, unsigned align_>
   1.187 +  freeblock<size, align_> * allocator_impl<size, align_>::page = 0;
   1.188 +
   1.189 +template<unsigned size, unsigned align_>
   1.190 +  unsigned allocator_impl<size, align_>::last = allocator_impl<size, align_>::items_per_page;
   1.191 +
   1.192 +template<class T>
   1.193 +struct quick_allocator: public allocator_impl< sizeof(T), boost::alignment_of<T>::value >
   1.194 +{
   1.195 +};
   1.196 +
   1.197 +} // namespace detail
   1.198 +
   1.199 +} // namespace boost
   1.200 +
   1.201 +#endif  // #ifndef BOOST_DETAIL_QUICK_ALLOCATOR_HPP_INCLUDED