+2019-05-22 Jonathan Wakely <jwakely@redhat.com>
+
+ PR libstdc++/77691
+ * include/experimental/memory_resource: Add system header pragma and
+ do not define anything unless compiled as C++14 or later.
+ (__resource_adaptor_common::__guaranteed_alignment): Remove.
+ (__resource_adaptor_imp::do_allocate): If the requested alignment
+ is a fundamental alignment then either allocate directly from _M_alloc
+ or call the new _M_allocate function.
+ (__resource_adaptor_imp::do_deallocate): Likewise for deallocation.
+ (__resource_adaptor_imp::_M_allocate): New function that uses a copy
+ of the allocator rebound to a POD type with the specified alignment.
+ (__resource_adaptor_imp::_M_deallocate): Likewise for deallocation.
+ * testsuite/experimental/memory_resource/new_delete_resource.cc:
+ Adjust expected allocation sizes.
+ * testsuite/experimental/memory_resource/resource_adaptor.cc: Remove
+ xfail for Solaris x86.
+
2019-05-21 Thomas Rodgers <trodgers@redhat.com>
LWG 3062 - Unnecessary decay_t in is_execution_policy_v
#ifndef _GLIBCXX_EXPERIMENTAL_MEMORY_RESOURCE
#define _GLIBCXX_EXPERIMENTAL_MEMORY_RESOURCE 1
+#pragma GCC system_header
+
+#if __cplusplus >= 201402L
+
#include <memory> // align, uses_allocator, __uses_alloc
#include <experimental/utility> // pair, experimental::erased_type
#include <atomic> // atomic
return __val;
}
};
-
- template<typename _Alloc>
- struct __guaranteed_alignment : std::integral_constant<size_t, 1> { };
-
- template<typename _Tp>
- struct __guaranteed_alignment<__gnu_cxx::new_allocator<_Tp>>
- : std::alignment_of<std::max_align_t>::type { };
-
- template<typename _Tp>
- struct __guaranteed_alignment<__gnu_cxx::malloc_allocator<_Tp>>
- : std::alignment_of<std::max_align_t>::type { };
-
-#if _GLIBCXX_USE_ALLOCATOR_NEW
- template<typename _Tp>
- struct __guaranteed_alignment<std::allocator<_Tp>>
- : std::alignment_of<std::max_align_t>::type { };
-#endif
};
/// @endcond
virtual void*
do_allocate(size_t __bytes, size_t __alignment) override
{
- if (__alignment <= __guaranteed_alignment<_Alloc>::value)
+ // Cannot use max_align_t on 32-bit Solaris x86, see PR libstdc++/77691
+#if ! (defined __sun__ && defined __i386__)
+ if (__alignment == alignof(max_align_t))
+ return _M_allocate<alignof(max_align_t)>(__bytes);
+#endif
+ switch (__alignment)
{
- if (__bytes < __alignment)
- __bytes = __alignment;
+ case 1:
return _M_alloc.allocate(__bytes);
+ case 2:
+ return _M_allocate<2>(__bytes);
+ case 4:
+ return _M_allocate<4>(__bytes);
+ case 8:
+ return _M_allocate<8>(__bytes);
}
-
-
const _AlignMgr __mgr(__bytes, __alignment);
// Assume _M_alloc returns 1-byte aligned memory, so allocate enough
// space to fit a block of the right size and alignment, plus some
}
virtual void
- do_deallocate(void* __p, size_t __bytes, size_t __alignment) noexcept
+ do_deallocate(void* __ptr, size_t __bytes, size_t __alignment) noexcept
override
{
- auto __ptr = static_cast<char*>(__p);
- if (__alignment <= __guaranteed_alignment<_Alloc>::value)
+#if ! (defined __sun__ && defined __i386__)
+ if (__alignment == alignof(max_align_t))
+ return (void) _M_deallocate<alignof(max_align_t)>(__ptr, __bytes);
+#endif
+ switch (__alignment)
{
- if (__bytes < __alignment)
- __bytes = __alignment;
- _M_alloc.deallocate(__ptr, __bytes);
- return;
+ case 1:
+ return (void) _M_alloc.deallocate((char*)__ptr, __bytes);
+ case 2:
+ return (void) _M_deallocate<2>(__ptr, __bytes);
+ case 4:
+ return (void) _M_deallocate<4>(__ptr, __bytes);
+ case 8:
+ return (void) _M_deallocate<8>(__ptr, __bytes);
}
-
const _AlignMgr __mgr(__bytes, __alignment);
- // Use the stored token to retrieve the original pointer to deallocate.
- _M_alloc.deallocate(__mgr._M_unadjust(__ptr), __mgr._M_alloc_size());
+ // Use the stored token to retrieve the original pointer.
+ _M_alloc.deallocate(__mgr._M_unadjust((char*)__ptr),
+ __mgr._M_alloc_size());
}
virtual bool
}
private:
+ template<size_t _Num>
+ struct _Aligned_type { alignas(_Num) char __c[_Num]; };
+
+ // Rebind the allocator to the specified type and use it to allocate.
+ template<size_t _Num, typename _Tp = _Aligned_type<_Num>>
+ void*
+ _M_allocate(size_t __bytes)
+ {
+ typename allocator_traits<_Alloc>::template
+ rebind_alloc<_Tp> __a2(_M_alloc);
+ const size_t __n = (__bytes + _Num - 1) / _Num;
+ return __a2.allocate(__n);
+ }
+
+ // Rebind the allocator to the specified type and use it to deallocate.
+ template<size_t _Num, typename _Tp = _Aligned_type<_Num>>
+ void
+ _M_deallocate(void* __ptr, size_t __bytes) noexcept
+ {
+ typename allocator_traits<_Alloc>::template
+ rebind_alloc<_Tp> __a2(_M_alloc);
+ const size_t __n = (__bytes + _Num - 1) / _Num;
+ __a2.deallocate((_Tp*)__ptr, __n);
+ }
+
_Alloc _M_alloc{};
};
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
+#endif // C++14
#endif // _GLIBCXX_EXPERIMENTAL_MEMORY_RESOURCE
#include <cstdlib>
#include <testsuite_hooks.h>
+#if defined __sun__ && defined __i386__
+// See PR libstdc++/77691
+# define BAD_MAX_ALIGN_T 1
+#endif
+
bool new_called = false;
bool delete_called = false;
std::size_t bytes_allocated = 0;
throw std::bad_alloc();
}
-void operator delete(void* p)
+void operator delete(void* p) noexcept
{
delete_called = true;
std::free(p);
bytes_allocated = 0; // assume everything getting deleted
}
-void operator delete(void* p, std::size_t n)
+void operator delete(void* p, std::size_t n) noexcept
{
delete_called = true;
std::free(p);
template<std::size_t A>
bool aligned(void* p)
- {
- return (reinterpret_cast<std::uintptr_t>(p) % A) == 0;
- }
+ { return (reinterpret_cast<std::uintptr_t>(p) % A) == 0; }
template<typename T>
bool aligned(void* p)
using std::size_t;
void* p = nullptr;
- auto max = [](int n, int a) { return n > a ? n : a; };
+ auto round = [](size_t n, size_t a) { return n % a ? n + a - (n % a) : n; };
bytes_allocated = 0;
memory_resource* r1 = new_delete_resource();
p = r1->allocate(1); // uses alignment = alignof(max_align_t)
- VERIFY( bytes_allocated <= alignof(max_align_t) );
+#ifdef BAD_MAX_ALIGN_T
+ VERIFY( bytes_allocated != 0 );
+#else
+ VERIFY( bytes_allocated == alignof(max_align_t) );
+#endif
VERIFY( aligned<max_align_t>(p) );
r1->deallocate(p, 1);
VERIFY( bytes_allocated == 0 );
VERIFY( bytes_allocated == 2 );
VERIFY( aligned<max_align_t>(p) );
r1->deallocate(p, 2, alignof(char));
- __builtin_printf("%d\n", (int)bytes_allocated);
VERIFY( bytes_allocated == 0 );
p = r1->allocate(3, alignof(short));
- VERIFY( bytes_allocated == max(3, alignof(short)) );
+ VERIFY( bytes_allocated == round(3, alignof(short)) );
VERIFY( aligned<short>(p) );
r1->deallocate(p, 3, alignof(short));
VERIFY( bytes_allocated == 0 );
p = r1->allocate(4, alignof(long));
- VERIFY( bytes_allocated == max(4, alignof(long)) );
+ VERIFY( bytes_allocated == round(4, alignof(long)) );
VERIFY( aligned<long>(p) );
r1->deallocate(p, 4, alignof(long));
VERIFY( bytes_allocated == 0 );