Files
libcxx/include/__sso_allocator
Eric Fiselier e09f85bbe5 Implement sized deallocation for std::allocator and friends.
Summary:
C++14 sized deallocation is disabled by default due to ABI concerns. However, when a user manually enables it then libc++ should take advantage of it since sized deallocation can provide a significant performance win depending on the underlying malloc implementation. (Note that libc++'s definitions of sized delete don't do anything special yet, but users are free to provide their own).

This patch updates __libcpp_deallocate to selectively call sized operator delete when it's available. `__libcpp_deallocate_unsized` should be used when the size of the allocation is unknown.

On Apple this patch makes no attempt to determine if the sized operator delete is unavailable, only that the language feature is enabled. This could cause a compile error when using `std::allocator`, but the same compile error would occur whenever the user calls `new`, so I don't think it's a problem.

Reviewers: ldionne, mclow.lists

Reviewed By: ldionne

Subscribers: rsmith, ckennelly, libcxx-commits, christof

Differential Revision: https://reviews.llvm.org/D53120

git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@345281 91177308-0d34-0410-b5e6-96231b3b80d8
2018-10-25 17:21:30 +00:00

78 lines
2.5 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 __n)
{
if (__p == (pointer)&buf_)
__allocated_ = false;
else
_VSTD::__libcpp_deallocate(__p, __n * sizeof(_Tp), __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