]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | ////////////////////////////////////////////////////////////////////////////// |
2 | // | |
3 | // (C) Copyright Ion Gaztanaga 2015-2015. Distributed under the Boost | |
4 | // Software License, Version 1.0. (See accompanying file | |
5 | // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |
6 | // | |
7 | // See http://www.boost.org/libs/container for documentation. | |
8 | // | |
9 | ////////////////////////////////////////////////////////////////////////////// | |
10 | ||
11 | #ifndef BOOST_CONTAINER_DETAIL_BLOCK_LIST_HEADER | |
12 | #define BOOST_CONTAINER_DETAIL_BLOCK_LIST_HEADER | |
13 | ||
14 | #ifndef BOOST_CONFIG_HPP | |
15 | # include <boost/config.hpp> | |
16 | #endif | |
17 | ||
18 | #if defined(BOOST_HAS_PRAGMA_ONCE) | |
19 | # pragma once | |
20 | #endif | |
21 | ||
22 | #include <boost/container/detail/config_begin.hpp> | |
23 | #include <boost/container/detail/workaround.hpp> | |
24 | #include <boost/container/container_fwd.hpp> | |
25 | #include <boost/container/pmr/memory_resource.hpp> | |
26 | #include <boost/container/throw_exception.hpp> | |
27 | #include <boost/intrusive/circular_list_algorithms.hpp> | |
28 | #include <boost/move/detail/type_traits.hpp> | |
29 | #include <boost/assert.hpp> | |
92f5a8d4 | 30 | #include <boost/container/detail/placement_new.hpp> |
7c673cae FG |
31 | |
32 | #include <cstddef> | |
33 | ||
34 | namespace boost { | |
35 | namespace container { | |
36 | namespace pmr { | |
37 | ||
38 | struct list_node | |
39 | { | |
40 | list_node *next; | |
41 | list_node *previous; | |
42 | }; | |
43 | ||
44 | struct list_node_traits | |
45 | { | |
46 | typedef list_node node; | |
47 | typedef list_node* node_ptr; | |
48 | typedef const list_node* const_node_ptr; | |
49 | ||
50 | static node_ptr get_next(const_node_ptr n) | |
51 | { return n->next; } | |
52 | ||
53 | static node_ptr get_previous(const_node_ptr n) | |
54 | { return n->previous; } | |
55 | ||
56 | static void set_next(const node_ptr & n, const node_ptr & next) | |
57 | { n->next = next; } | |
58 | ||
59 | static void set_previous(const node_ptr & n, const node_ptr & previous) | |
60 | { n->previous = previous; } | |
61 | }; | |
62 | ||
63 | struct block_list_header | |
64 | : public list_node | |
65 | { | |
66 | std::size_t size; | |
67 | }; | |
68 | ||
69 | typedef bi::circular_list_algorithms<list_node_traits> list_algo; | |
70 | ||
71 | ||
72 | template<class DerivedFromBlockListHeader = block_list_header> | |
73 | class block_list_base | |
74 | { | |
75 | list_node m_list; | |
76 | ||
77 | static const std::size_t MaxAlignMinus1 = memory_resource::max_align-1u; | |
78 | ||
79 | public: | |
80 | ||
81 | static const std::size_t header_size = std::size_t(sizeof(DerivedFromBlockListHeader) + MaxAlignMinus1) & std::size_t(~MaxAlignMinus1); | |
82 | ||
83 | explicit block_list_base() | |
84 | { list_algo::init_header(&m_list); } | |
85 | ||
86 | #if !defined(BOOST_NO_CXX11_DELETED_FUNCTIONS) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED) | |
87 | block_list_base(const block_list_base&) = delete; | |
88 | block_list_base operator=(const block_list_base&) = delete; | |
89 | #else | |
90 | private: | |
91 | block_list_base (const block_list_base&); | |
92 | block_list_base operator=(const block_list_base&); | |
93 | public: | |
94 | #endif | |
95 | ||
96 | ~block_list_base() | |
97 | {} | |
98 | ||
99 | void *allocate(std::size_t size, memory_resource &mr) | |
100 | { | |
101 | if((size_t(-1) - header_size) < size) | |
102 | throw_bad_alloc(); | |
103 | void *p = mr.allocate(size+header_size); | |
92f5a8d4 | 104 | block_list_header &mb = *::new((void*)p, boost_container_new_t()) DerivedFromBlockListHeader; |
7c673cae FG |
105 | mb.size = size+header_size; |
106 | list_algo::link_after(&m_list, &mb); | |
107 | return (char *)p + header_size; | |
108 | } | |
109 | ||
110 | void deallocate(void *p, memory_resource &mr) BOOST_NOEXCEPT | |
111 | { | |
112 | DerivedFromBlockListHeader *pheader = static_cast<DerivedFromBlockListHeader*> | |
113 | (static_cast<void*>((char*)p - header_size)); | |
114 | list_algo::unlink(pheader); | |
115 | const std::size_t size = pheader->size; | |
116 | static_cast<DerivedFromBlockListHeader*>(pheader)->~DerivedFromBlockListHeader(); | |
117 | mr.deallocate(pheader, size, memory_resource::max_align); | |
118 | } | |
119 | ||
120 | void release(memory_resource &mr) BOOST_NOEXCEPT | |
121 | { | |
122 | list_node *n = list_algo::node_traits::get_next(&m_list); | |
123 | while(n != &m_list){ | |
124 | DerivedFromBlockListHeader &d = static_cast<DerivedFromBlockListHeader&>(*n); | |
125 | n = list_algo::node_traits::get_next(n); | |
126 | std::size_t size = d.size; | |
127 | d.~DerivedFromBlockListHeader(); | |
128 | mr.deallocate(reinterpret_cast<char*>(&d), size, memory_resource::max_align); | |
129 | } | |
130 | list_algo::init_header(&m_list); | |
131 | } | |
132 | }; | |
133 | ||
134 | } //namespace pmr { | |
135 | } //namespace container { | |
136 | } //namespace boost { | |
137 | ||
138 | #include <boost/container/detail/config_end.hpp> | |
139 | ||
140 | #endif //BOOST_CONTAINER_DETAIL_BLOCK_LIST_HEADER |