2 * Copyright (c) 2018 Samsung Electronics Co., Ltd. All rights reserved.
4 * Licensed under the LGPL License, Version 2.1 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * https://www.gnu.org/licenses/
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 #ifndef VSTACK_ALLOCATOR_H
18 #define VSTACK_ALLOCATOR_H
23 template <std::size_t N, std::size_t alignment = alignof(std::max_align_t)>
26 alignas(alignment) char buf_[N];
30 ~arena() {ptr_ = nullptr;}
31 arena() noexcept : ptr_(buf_) {}
32 arena(const arena&) = delete;
33 arena& operator=(const arena&) = delete;
35 template <std::size_t ReqAlign> char* allocate(std::size_t n);
36 void deallocate(char* p, std::size_t n) noexcept;
38 static constexpr std::size_t size() noexcept {return N;}
39 std::size_t used() const noexcept {return static_cast<std::size_t>(ptr_ - buf_);}
40 void reset() noexcept {ptr_ = buf_;}
45 align_up(std::size_t n) noexcept
46 {return (n + (alignment-1)) & ~(alignment-1);}
49 pointer_in_buffer(char* p) noexcept
50 {return buf_ <= p && p <= buf_ + N;}
53 template <std::size_t N, std::size_t alignment>
54 template <std::size_t ReqAlign>
56 arena<N, alignment>::allocate(std::size_t n)
58 static_assert(ReqAlign <= alignment, "alignment is too small for this arena");
59 assert(pointer_in_buffer(ptr_) && "stack_alloc has outlived arena");
60 auto const aligned_n = align_up(n);
61 if (static_cast<decltype(aligned_n)>(buf_ + N - ptr_) >= aligned_n)
68 static_assert(alignment <= alignof(std::max_align_t), "you've chosen an "
69 "alignment that is larger than alignof(std::max_align_t), and "
70 "cannot be guaranteed by normal operator new");
71 return static_cast<char*>(::operator new(n));
74 template <std::size_t N, std::size_t alignment>
76 arena<N, alignment>::deallocate(char* p, std::size_t n) noexcept
78 assert(pointer_in_buffer(ptr_) && "stack_alloc has outlived arena");
79 if (pointer_in_buffer(p))
89 template <class T, std::size_t N, std::size_t Align = alignof(std::max_align_t)>
94 static auto constexpr alignment = Align;
95 static auto constexpr size = N;
96 using arena_type = arena<size, alignment>;
102 stack_alloc(const stack_alloc&) = default;
103 stack_alloc& operator=(const stack_alloc&) = delete;
105 stack_alloc(arena_type& a) noexcept : a_(a)
107 static_assert(size % alignment == 0,
108 "size N needs to be a multiple of alignment Align");
111 stack_alloc(const stack_alloc<U, N, alignment>& a) noexcept
114 template <class _Up> struct rebind {using other = stack_alloc<_Up, N, alignment>;};
116 T* allocate(std::size_t n)
118 return reinterpret_cast<T*>(a_.template allocate<alignof(T)>(n*sizeof(T)));
120 void deallocate(T* p, std::size_t n) noexcept
122 a_.deallocate(reinterpret_cast<char*>(p), n*sizeof(T));
125 template <class T1, std::size_t N1, std::size_t A1,
126 class U, std::size_t M, std::size_t A2>
129 operator==(const stack_alloc<T1, N1, A1>& x, const stack_alloc<U, M, A2>& y) noexcept;
131 template <class U, std::size_t M, std::size_t A> friend class stack_alloc;
134 template <class T, std::size_t N, std::size_t A1, class U, std::size_t M, std::size_t A2>
137 operator==(const stack_alloc<T, N, A1>& x, const stack_alloc<U, M, A2>& y) noexcept
139 return N == M && A1 == A2 && &x.a_ == &y.a_;
142 template <class T, std::size_t N, std::size_t A1, class U, std::size_t M, std::size_t A2>
145 operator!=(const stack_alloc<T, N, A1>& x, const stack_alloc<U, M, A2>& y) noexcept
150 #endif // VSTACK_ALLOCATOR_H