138fd1498Szrj // Aligned memory buffer -*- C++ -*- 238fd1498Szrj 338fd1498Szrj // Copyright (C) 2013-2018 Free Software Foundation, Inc. 438fd1498Szrj // 538fd1498Szrj // This file is part of the GNU ISO C++ Library. This library is free 638fd1498Szrj // software; you can redistribute it and/or modify it under the 738fd1498Szrj // terms of the GNU General Public License as published by the 838fd1498Szrj // Free Software Foundation; either version 3, or (at your option) 938fd1498Szrj // any later version. 1038fd1498Szrj 1138fd1498Szrj // This library is distributed in the hope that it will be useful, 1238fd1498Szrj // but WITHOUT ANY WARRANTY; without even the implied warranty of 1338fd1498Szrj // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1438fd1498Szrj // GNU General Public License for more details. 1538fd1498Szrj 1638fd1498Szrj // Under Section 7 of GPL version 3, you are granted additional 1738fd1498Szrj // permissions described in the GCC Runtime Library Exception, version 1838fd1498Szrj // 3.1, as published by the Free Software Foundation. 1938fd1498Szrj 2038fd1498Szrj // You should have received a copy of the GNU General Public License and 2138fd1498Szrj // a copy of the GCC Runtime Library Exception along with this program; 2238fd1498Szrj // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 2338fd1498Szrj // <http://www.gnu.org/licenses/>. 2438fd1498Szrj 2538fd1498Szrj /** @file ext/aligned_buffer.h 2638fd1498Szrj * This file is a GNU extension to the Standard C++ Library. 2738fd1498Szrj */ 2838fd1498Szrj 2938fd1498Szrj #ifndef _ALIGNED_BUFFER_H 3038fd1498Szrj #define _ALIGNED_BUFFER_H 1 3138fd1498Szrj 3238fd1498Szrj #pragma GCC system_header 3338fd1498Szrj 3438fd1498Szrj #if __cplusplus >= 201103L 3538fd1498Szrj # include <type_traits> 3638fd1498Szrj #else 3738fd1498Szrj # include <bits/c++0x_warning.h> 3838fd1498Szrj #endif 3938fd1498Szrj 4038fd1498Szrj namespace __gnu_cxx 4138fd1498Szrj { 4238fd1498Szrj // A utility type containing a POD object that can hold an object of type 4338fd1498Szrj // _Tp initialized via placement new or allocator_traits::construct. 4438fd1498Szrj // Intended for use as a data member subobject, use __aligned_buffer for 4538fd1498Szrj // complete objects. 4638fd1498Szrj template<typename _Tp> 4738fd1498Szrj struct __aligned_membuf 4838fd1498Szrj { 4938fd1498Szrj // Target macro ADJUST_FIELD_ALIGN can produce different alignment for 5038fd1498Szrj // types when used as class members. __aligned_membuf is intended 5138fd1498Szrj // for use as a class member, so align the buffer as for a class member. 52*58e805e6Szrj // Since GCC 8 we could just use alignof(_Tp) instead, but older 53*58e805e6Szrj // versions of non-GNU compilers might still need this trick. 5438fd1498Szrj struct _Tp2 { _Tp _M_t; }; 5538fd1498Szrj 5638fd1498Szrj alignas(__alignof__(_Tp2::_M_t)) unsigned char _M_storage[sizeof(_Tp)]; 5738fd1498Szrj 5838fd1498Szrj __aligned_membuf() = default; 5938fd1498Szrj 6038fd1498Szrj // Can be used to avoid value-initialization zeroing _M_storage. __aligned_membuf__aligned_membuf6138fd1498Szrj __aligned_membuf(std::nullptr_t) { } 6238fd1498Szrj 6338fd1498Szrj void* _M_addr__aligned_membuf6438fd1498Szrj _M_addr() noexcept 6538fd1498Szrj { return static_cast<void*>(&_M_storage); } 6638fd1498Szrj 6738fd1498Szrj const void* _M_addr__aligned_membuf6838fd1498Szrj _M_addr() const noexcept 6938fd1498Szrj { return static_cast<const void*>(&_M_storage); } 7038fd1498Szrj 7138fd1498Szrj _Tp* _M_ptr__aligned_membuf7238fd1498Szrj _M_ptr() noexcept 7338fd1498Szrj { return static_cast<_Tp*>(_M_addr()); } 7438fd1498Szrj 7538fd1498Szrj const _Tp* _M_ptr__aligned_membuf7638fd1498Szrj _M_ptr() const noexcept 7738fd1498Szrj { return static_cast<const _Tp*>(_M_addr()); } 7838fd1498Szrj }; 7938fd1498Szrj 8038fd1498Szrj #if _GLIBCXX_INLINE_VERSION 8138fd1498Szrj template<typename _Tp> 8238fd1498Szrj using __aligned_buffer = __aligned_membuf<_Tp>; 8338fd1498Szrj #else 8438fd1498Szrj // Similar to __aligned_membuf but aligned for complete objects, not members. 8538fd1498Szrj // This type is used in <forward_list>, <future>, <bits/shared_ptr_base.h> 8638fd1498Szrj // and <bits/hashtable_policy.h>, but ideally they would use __aligned_membuf 8738fd1498Szrj // instead, as it has smaller size for some types on some targets. 8838fd1498Szrj // This type is still used to avoid an ABI change. 8938fd1498Szrj template<typename _Tp> 9038fd1498Szrj struct __aligned_buffer 91*58e805e6Szrj : std::aligned_storage<sizeof(_Tp), __alignof__(_Tp)> 9238fd1498Szrj { 9338fd1498Szrj typename 94*58e805e6Szrj std::aligned_storage<sizeof(_Tp), __alignof__(_Tp)>::type _M_storage; 9538fd1498Szrj 9638fd1498Szrj __aligned_buffer() = default; 9738fd1498Szrj 9838fd1498Szrj // Can be used to avoid value-initialization __aligned_buffer__aligned_buffer9938fd1498Szrj __aligned_buffer(std::nullptr_t) { } 10038fd1498Szrj 10138fd1498Szrj void* _M_addr__aligned_buffer10238fd1498Szrj _M_addr() noexcept 10338fd1498Szrj { 10438fd1498Szrj return static_cast<void*>(&_M_storage); 10538fd1498Szrj } 10638fd1498Szrj 10738fd1498Szrj const void* _M_addr__aligned_buffer10838fd1498Szrj _M_addr() const noexcept 10938fd1498Szrj { 11038fd1498Szrj return static_cast<const void*>(&_M_storage); 11138fd1498Szrj } 11238fd1498Szrj 11338fd1498Szrj _Tp* _M_ptr__aligned_buffer11438fd1498Szrj _M_ptr() noexcept 11538fd1498Szrj { return static_cast<_Tp*>(_M_addr()); } 11638fd1498Szrj 11738fd1498Szrj const _Tp* _M_ptr__aligned_buffer11838fd1498Szrj _M_ptr() const noexcept 11938fd1498Szrj { return static_cast<const _Tp*>(_M_addr()); } 12038fd1498Szrj }; 12138fd1498Szrj #endif 12238fd1498Szrj 12338fd1498Szrj } // namespace 12438fd1498Szrj 12538fd1498Szrj #endif /* _ALIGNED_BUFFER_H */ 126