Implement polymorphic_allocator<byte> for C++20 (P0339R6)
* include/std/memory_resource (polymorphic_allocator): Add default template argument for C++20. (polymorphic_allocator::allocate_bytes) (polymorphic_allocator::deallocate_bytes) (polymorphic_allocator::allocate_object) (polymorphic_allocator::deallocate_object) (polymorphic_allocator::new_object) (polymorphic_allocator::delete_object): New member functions for C++20. * testsuite/20_util/polymorphic_allocator/allocate_object.cc: New test. From-SVN: r269362
This commit is contained in:
parent
c445049114
commit
0e31827300
|
@ -1,3 +1,17 @@
|
|||
2019-03-04 Jonathan Wakely <jwakely@redhat.com>
|
||||
|
||||
* include/std/memory_resource (polymorphic_allocator): Add default
|
||||
template argument for C++20.
|
||||
(polymorphic_allocator::allocate_bytes)
|
||||
(polymorphic_allocator::deallocate_bytes)
|
||||
(polymorphic_allocator::allocate_object)
|
||||
(polymorphic_allocator::deallocate_object)
|
||||
(polymorphic_allocator::new_object)
|
||||
(polymorphic_allocator::delete_object): New member functions for
|
||||
C++20.
|
||||
* testsuite/20_util/polymorphic_allocator/allocate_object.cc: New
|
||||
test.
|
||||
|
||||
2019-03-03 Jonathan Wakely <jwakely@redhat.com>
|
||||
|
||||
PR libstdc++/89562
|
||||
|
|
|
@ -33,11 +33,13 @@
|
|||
|
||||
#if __cplusplus >= 201703L
|
||||
|
||||
#include <limits> // numeric_limits
|
||||
#include <memory> // align, allocator_arg_t, __uses_alloc
|
||||
#include <utility> // pair, index_sequence
|
||||
#include <vector> // vector
|
||||
#include <cstddef> // size_t, max_align_t
|
||||
#include <cstddef> // size_t, max_align_t, byte
|
||||
#include <shared_mutex> // shared_mutex
|
||||
#include <bits/functexcept.h>
|
||||
#include <debug/assertions.h>
|
||||
|
||||
namespace std _GLIBCXX_VISIBILITY(default)
|
||||
|
@ -55,8 +57,13 @@ namespace pmr
|
|||
|
||||
class memory_resource;
|
||||
|
||||
#if __cplusplus == 201703L
|
||||
template<typename _Tp>
|
||||
class polymorphic_allocator;
|
||||
#else // C++20
|
||||
template<typename _Tp = std::byte>
|
||||
class polymorphic_allocator;
|
||||
#endif
|
||||
|
||||
// Global memory resources
|
||||
memory_resource* new_delete_resource() noexcept;
|
||||
|
@ -170,7 +177,59 @@ namespace pmr
|
|||
__attribute__((__nonnull__))
|
||||
{ _M_resource->deallocate(__p, __n * sizeof(_Tp), alignof(_Tp)); }
|
||||
|
||||
#if __cplusplus <= 201703L
|
||||
#if __cplusplus > 201703L
|
||||
void*
|
||||
allocate_bytes(size_t __nbytes,
|
||||
size_t __alignment = alignof(max_align_t))
|
||||
{ return _M_resource->allocate(__nbytes, __alignment); }
|
||||
|
||||
void
|
||||
deallocate_bytes(void* __p, size_t __nbytes,
|
||||
size_t __alignment = alignof(max_align_t))
|
||||
{ _M_resource->deallocate(__p, __nbytes, __alignment); }
|
||||
|
||||
template<typename _Up>
|
||||
_Up*
|
||||
allocate_object(size_t __n = 1)
|
||||
{
|
||||
if ((std::numeric_limits<size_t>::max() / sizeof(_Up)) < __n)
|
||||
__throw_length_error("polymorphic_allocator::allocate_object");
|
||||
return static_cast<_Up*>(allocate_bytes(__n * sizeof(_Up),
|
||||
alignof(_Up)));
|
||||
}
|
||||
|
||||
template<typename _Up>
|
||||
void
|
||||
deallocate_object(_Up* __p, size_t __n = 1)
|
||||
{ deallocate_bytes(__p, __n * sizeof(_Up), alignof(_Up)); }
|
||||
|
||||
template<typename _Up, typename... _CtorArgs>
|
||||
_Up*
|
||||
new_object(_CtorArgs&&... __ctor_args)
|
||||
{
|
||||
_Up* __p = allocate_object<_Up>();
|
||||
__try
|
||||
{
|
||||
construct(__p, std::forward<_CtorArgs>(__ctor_args)...);
|
||||
}
|
||||
__catch (...)
|
||||
{
|
||||
deallocate_object(__p);
|
||||
__throw_exception_again;
|
||||
}
|
||||
return __p;
|
||||
}
|
||||
|
||||
template<typename _Up>
|
||||
void
|
||||
delete_object(_Up* __p)
|
||||
{
|
||||
destroy(__p);
|
||||
deallocate_object(__p);
|
||||
}
|
||||
#endif // C++2a
|
||||
|
||||
#if __cplusplus == 201703L
|
||||
template<typename _Tp1, typename... _Args>
|
||||
__attribute__((__nonnull__))
|
||||
typename __not_pair<_Tp1>::type
|
||||
|
|
|
@ -0,0 +1,80 @@
|
|||
// Copyright (C) 2019 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.
|
||||
|
||||
// You should have received a copy of the GNU General Public License along
|
||||
// with this library; see the file COPYING3. If not see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
// { dg-options "-std=gnu++2a" }
|
||||
// { dg-do run { target c++2a } }
|
||||
|
||||
#include <memory_resource>
|
||||
#include <cstring>
|
||||
#include <testsuite_hooks.h>
|
||||
#include <testsuite_allocator.h>
|
||||
|
||||
void
|
||||
test01()
|
||||
{
|
||||
__gnu_test::memory_resource res;
|
||||
std::pmr::polymorphic_allocator<> alloc(&res);
|
||||
static_assert( std::is_same_v<decltype(alloc)::value_type, std::byte> );
|
||||
|
||||
void* p = alloc.allocate_bytes(100);
|
||||
VERIFY( res.number_of_active_allocations() == 1 );
|
||||
alloc.deallocate_bytes(p, 100);
|
||||
VERIFY( res.number_of_active_allocations() == 0 );
|
||||
p = alloc.allocate_bytes(100, 64);
|
||||
VERIFY( res.number_of_active_allocations() == 1 );
|
||||
alloc.deallocate_bytes(p, 100, 64);
|
||||
VERIFY( res.number_of_active_allocations() == 0 );
|
||||
|
||||
int* p1 = alloc.allocate_object<int>();
|
||||
int* p2 = alloc.allocate_object<int>(2);
|
||||
struct X { double d[10]; };
|
||||
X* px = alloc.allocate_object<X>(20);
|
||||
VERIFY( res.number_of_active_allocations() == 3 );
|
||||
|
||||
alloc.deallocate_object(p1);
|
||||
alloc.deallocate_object(p2, 2);
|
||||
alloc.deallocate_object(px, 20);
|
||||
VERIFY( res.number_of_active_allocations() == 0 );
|
||||
|
||||
struct Y {
|
||||
Y(int i, const char* s, bool* alive)
|
||||
: i(i), s(s), alive(alive)
|
||||
{ *alive = true; }
|
||||
|
||||
~Y() { *alive = false; }
|
||||
|
||||
int i;
|
||||
const char* s;
|
||||
bool* alive;
|
||||
};
|
||||
|
||||
bool alive = false;
|
||||
Y* py = alloc.new_object<Y>(1, "two", &alive);
|
||||
VERIFY( alive );
|
||||
VERIFY( py->i == 1 );
|
||||
VERIFY( std::strcmp(py->s, "two") == 0 );
|
||||
VERIFY( res.number_of_active_allocations() == 1 );
|
||||
|
||||
alloc.delete_object(py);
|
||||
VERIFY( alive == false );
|
||||
}
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
test01();
|
||||
}
|
Loading…
Reference in New Issue