1 #ifdef COMPILATION// -*-indent-tabs-mode:t;c-basic-offset:4;tab-width:4;-*-
2 $CXXX $CXXFLAGS $0 -o $0x -lboost_unit_test_framework&&$0x&&rm $0x;exit
3 #endif
4 // © Alfredo A. Correa 2019-2020
5
6 #ifndef BOOST_MULTI_MEMORY_STACK_HPP
7 #define BOOST_MULTI_MEMORY_STACK_HPP
8
9 #include "../memory/monotonic.hpp"
10 #include "../memory/allocator.hpp"
11
12 #include<cstddef> // max_align_t
13 #include<stack>
14 #include<cassert>
15
16 namespace boost{
17 namespace multi{
18 namespace memory{
19
20 template<typename Ptr = byte*, std::size_t Align = alignof(std::max_align_t)>
21 class stack : protected monotonic<Ptr, Align>{
22 private:
23 std::stack<typename stack::void_pointer> positions_ = {};
24 typename stack::size_type total_requested_ = 0;
25 typename stack::size_type total_discarded_ = 0;
26 typename stack::size_type max_needed_ = 0;
27 long hits_ = 0;
28 public:
hits() const29 long hits() const{return hits_;}
reset()30 void reset(){monotonic<Ptr, Align>::reset(); positions_.clear();}
max_needed() const31 typename stack::size_type max_needed() const{return max_needed_;}
32 using monotonic<Ptr, Align>::monotonic;
33 template<std::size_t AA = Align>
allocate(typename stack::size_type required_bytes,typename stack::size_type align=AA)34 typename stack::void_pointer allocate(
35 typename stack::size_type required_bytes,
36 typename stack::size_type align = AA
37 ){
38 total_requested_ += required_bytes;
39 max_needed_ = std::max(max_needed_, total_requested_ - total_discarded_);
40 positions_.push(monotonic<Ptr, Align>::template allocate<AA>(required_bytes, align));
41 ++hits_;
42 return positions_.top();
43 }
deallocate(typename stack::void_pointer p,typename stack::size_type discarded_bytes)44 void deallocate(
45 typename stack::void_pointer p,
46 typename stack::size_type discarded_bytes
47 ){
48 total_discarded_ += discarded_bytes;
49 monotonic<Ptr, Align>::deallocate(p, discarded_bytes);//positions_.top(), discarded_bytes);
50 assert( p == positions_.top() && "stack violation" );
51 this->position_ -= discarded_bytes;
52 positions_.pop();
53 }
54 };
55
56 template<class T>
57 using stack_allocator = multi::memory::allocator<T, stack<char*>>;//, alignof(T)>>;
58
59 }}}
60
61 #if not __INCLUDE_LEVEL__
62 #define BOOST_TEST_MODULE "C++ Unit Tests for Multi stack memory resource"
63 #define BOOST_TEST_DYN_LINK
64 #include<boost/test/unit_test.hpp>
65
66 #include "../../multi/array.hpp"
67 #include<vector>
68
69 namespace multi = boost::multi;
70 namespace memory = multi::memory;
71
BOOST_AUTO_TEST_CASE(multi_memory_allocator)72 BOOST_AUTO_TEST_CASE(multi_memory_allocator){
73 {
74 alignas(double) char buffer[256*sizeof(double)];
75 memory::stack<char*> stck(buffer);
76 auto p1 = stck.allocate(1*sizeof(double), alignof(double));
77 BOOST_REQUIRE( stck.max_needed() == 1*sizeof(double) );
78
79 auto p2 = stck.allocate(255*sizeof(double), alignof(double));
80 BOOST_REQUIRE( stck.max_needed() == 256*sizeof(double) );
81
82 stck.deallocate(p2, 255*sizeof(double));
83 BOOST_REQUIRE( stck.max_needed() == 256*sizeof(double) );
84
85 stck.deallocate(p1, 1*sizeof(double));
86 BOOST_REQUIRE( stck.max_needed() == 256*sizeof(double) );
87
88 auto p3 = stck.allocate(100*sizeof(double)); (void)p3;
89 }
90 {
91 alignas(double) char buffer[256*sizeof(double)];
92 multi::memory::stack<char*> sm(buffer);
93 {
94 std::vector<double, multi::memory::stack_allocator<double>> v(10, &sm);
95 std::vector<double, multi::memory::stack_allocator<double>> w(10, &sm);
96 }
97 std::vector<double, multi::memory::stack_allocator<double>> w(5, &sm);
98 BOOST_REQUIRE( sm.max_needed()/sizeof(double) == 20 );
99 }
100 }
101 #endif
102 #endif
103
104