mirror of
https://github.com/llvm-mirror/libcxx.git
synced 2025-10-23 01:18:52 +08:00

This patch fixes std::allocator, and more specifically, all users of __libcpp_allocate and __libcpp_deallocate, to support over-aligned types. __libcpp_allocate/deallocate now take an alignment parameter, and when the specified alignment is greater than that supported by malloc/new, the aligned version of operator new is called (assuming it's available). When aligned new isn't available, the old behavior has been kept, and the alignment parameter is ignored. This patch depends on recent changes to __builtin_operator_new/delete which allow them to be used to call any regular new/delete operator. By using __builtin_operator_new/delete when possible, the new/delete erasure optimization is maintained. git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@328180 91177308-0d34-0410-b5e6-96231b3b80d8
78 lines
2.4 KiB
C++
78 lines
2.4 KiB
C++
// -*- C++ -*-
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is dual licensed under the MIT and the University of Illinois Open
|
|
// Source Licenses. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef _LIBCPP___SSO_ALLOCATOR
|
|
#define _LIBCPP___SSO_ALLOCATOR
|
|
|
|
#include <__config>
|
|
#include <type_traits>
|
|
#include <new>
|
|
|
|
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
|
#pragma GCC system_header
|
|
#endif
|
|
|
|
_LIBCPP_BEGIN_NAMESPACE_STD
|
|
|
|
template <class _Tp, size_t _Np> class _LIBCPP_HIDDEN __sso_allocator;
|
|
|
|
template <size_t _Np>
|
|
class _LIBCPP_HIDDEN __sso_allocator<void, _Np>
|
|
{
|
|
public:
|
|
typedef const void* const_pointer;
|
|
typedef void value_type;
|
|
};
|
|
|
|
template <class _Tp, size_t _Np>
|
|
class _LIBCPP_HIDDEN __sso_allocator
|
|
{
|
|
typename aligned_storage<sizeof(_Tp) * _Np>::type buf_;
|
|
bool __allocated_;
|
|
public:
|
|
typedef size_t size_type;
|
|
typedef _Tp* pointer;
|
|
typedef _Tp value_type;
|
|
|
|
_LIBCPP_INLINE_VISIBILITY __sso_allocator() throw() : __allocated_(false) {}
|
|
_LIBCPP_INLINE_VISIBILITY __sso_allocator(const __sso_allocator&) throw() : __allocated_(false) {}
|
|
template <class _Up> _LIBCPP_INLINE_VISIBILITY __sso_allocator(const __sso_allocator<_Up, _Np>&) throw()
|
|
: __allocated_(false) {}
|
|
private:
|
|
__sso_allocator& operator=(const __sso_allocator&);
|
|
public:
|
|
_LIBCPP_INLINE_VISIBILITY pointer allocate(size_type __n, typename __sso_allocator<void, _Np>::const_pointer = 0)
|
|
{
|
|
if (!__allocated_ && __n <= _Np)
|
|
{
|
|
__allocated_ = true;
|
|
return (pointer)&buf_;
|
|
}
|
|
return static_cast<pointer>(_VSTD::__libcpp_allocate(__n * sizeof(_Tp), __alignof(_Tp)));
|
|
}
|
|
_LIBCPP_INLINE_VISIBILITY void deallocate(pointer __p, size_type)
|
|
{
|
|
if (__p == (pointer)&buf_)
|
|
__allocated_ = false;
|
|
else
|
|
_VSTD::__libcpp_deallocate(__p, __alignof(_Tp));
|
|
}
|
|
_LIBCPP_INLINE_VISIBILITY size_type max_size() const throw() {return size_type(~0) / sizeof(_Tp);}
|
|
|
|
_LIBCPP_INLINE_VISIBILITY
|
|
bool operator==(__sso_allocator& __a) const {return &buf_ == &__a.buf_;}
|
|
_LIBCPP_INLINE_VISIBILITY
|
|
bool operator!=(__sso_allocator& __a) const {return &buf_ != &__a.buf_;}
|
|
};
|
|
|
|
_LIBCPP_END_NAMESPACE_STD
|
|
|
|
#endif // _LIBCPP___SSO_ALLOCATOR
|