]>
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_SLIST_HEADER | |
12 | #define BOOST_CONTAINER_DETAIL_BLOCK_SLIST_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 | ||
23 | #include <boost/container/detail/config_begin.hpp> | |
24 | #include <boost/container/detail/workaround.hpp> | |
25 | #include <boost/container/container_fwd.hpp> | |
26 | #include <boost/container/pmr/memory_resource.hpp> | |
27 | #include <boost/container/throw_exception.hpp> | |
28 | ||
29 | #include <boost/move/detail/type_traits.hpp> | |
30 | #include <boost/intrusive/linear_slist_algorithms.hpp> | |
31 | #include <boost/assert.hpp> | |
32 | ||
33 | #include <cstddef> | |
34 | ||
35 | namespace boost { | |
36 | namespace container { | |
37 | namespace pmr { | |
38 | ||
39 | struct slist_node | |
40 | { | |
41 | slist_node *next; | |
42 | }; | |
43 | ||
44 | struct slist_node_traits | |
45 | { | |
46 | typedef slist_node node; | |
47 | typedef slist_node* node_ptr; | |
48 | typedef const slist_node* const_node_ptr; | |
49 | ||
50 | static node_ptr get_next(const_node_ptr n) | |
51 | { return n->next; } | |
52 | ||
53 | static void set_next(const node_ptr & n, const node_ptr & next) | |
54 | { n->next = next; } | |
55 | }; | |
56 | ||
57 | struct block_slist_header | |
58 | : public slist_node | |
59 | { | |
60 | std::size_t size; | |
61 | }; | |
62 | ||
63 | typedef bi::linear_slist_algorithms<slist_node_traits> slist_algo; | |
64 | ||
65 | template<class DerivedFromBlockSlistHeader = block_slist_header> | |
66 | class block_slist_base | |
67 | { | |
68 | slist_node m_slist; | |
69 | ||
70 | static const std::size_t MaxAlignMinus1 = memory_resource::max_align-1u; | |
71 | ||
72 | public: | |
73 | ||
74 | static const std::size_t header_size = std::size_t(sizeof(DerivedFromBlockSlistHeader) + MaxAlignMinus1) & std::size_t(~MaxAlignMinus1); | |
75 | ||
76 | explicit block_slist_base() | |
77 | { slist_algo::init_header(&m_slist); } | |
78 | ||
79 | #if !defined(BOOST_NO_CXX11_DELETED_FUNCTIONS) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED) | |
80 | block_slist_base(const block_slist_base&) = delete; | |
81 | block_slist_base operator=(const block_slist_base&) = delete; | |
82 | #else | |
83 | private: | |
84 | block_slist_base (const block_slist_base&); | |
85 | block_slist_base operator=(const block_slist_base&); | |
86 | public: | |
87 | #endif | |
88 | ||
89 | ~block_slist_base() | |
90 | {} | |
91 | ||
92 | void *allocate(std::size_t size, memory_resource &mr) | |
93 | { | |
94 | if((size_t(-1) - header_size) < size) | |
95 | throw_bad_alloc(); | |
96 | void *p = mr.allocate(size+header_size); | |
97 | block_slist_header &mb = *::new((void*)p) DerivedFromBlockSlistHeader; | |
98 | mb.size = size+header_size; | |
99 | slist_algo::link_after(&m_slist, &mb); | |
100 | return (char *)p + header_size; | |
101 | } | |
102 | ||
103 | void release(memory_resource &mr) BOOST_NOEXCEPT | |
104 | { | |
105 | slist_node *n = slist_algo::node_traits::get_next(&m_slist); | |
106 | while(n){ | |
107 | DerivedFromBlockSlistHeader &d = static_cast<DerivedFromBlockSlistHeader&>(*n); | |
108 | n = slist_algo::node_traits::get_next(n); | |
109 | std::size_t size = d.block_slist_header::size; | |
110 | d.~DerivedFromBlockSlistHeader(); | |
111 | mr.deallocate(reinterpret_cast<char*>(&d), size, memory_resource::max_align); | |
112 | } | |
113 | slist_algo::init_header(&m_slist); | |
114 | } | |
115 | }; | |
116 | ||
117 | class block_slist | |
118 | : public block_slist_base<> | |
119 | { | |
120 | memory_resource &m_upstream_rsrc; | |
121 | ||
122 | public: | |
123 | ||
124 | explicit block_slist(memory_resource &upstream_rsrc) | |
125 | : block_slist_base<>(), m_upstream_rsrc(upstream_rsrc) | |
126 | {} | |
127 | ||
128 | #if !defined(BOOST_NO_CXX11_DELETED_FUNCTIONS) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED) | |
129 | block_slist(const block_slist&) = delete; | |
130 | block_slist operator=(const block_slist&) = delete; | |
131 | #else | |
132 | private: | |
133 | block_slist (const block_slist&); | |
134 | block_slist operator=(const block_slist&); | |
135 | public: | |
136 | #endif | |
137 | ||
138 | ~block_slist() | |
139 | { this->release(); } | |
140 | ||
141 | void *allocate(std::size_t size) | |
142 | { return this->block_slist_base<>::allocate(size, m_upstream_rsrc); } | |
143 | ||
144 | void release() BOOST_NOEXCEPT | |
145 | { return this->block_slist_base<>::release(m_upstream_rsrc); } | |
146 | ||
147 | memory_resource& upstream_resource() const BOOST_NOEXCEPT | |
148 | { return m_upstream_rsrc; } | |
149 | }; | |
150 | ||
151 | } //namespace pmr { | |
152 | } //namespace container { | |
153 | } //namespace boost { | |
154 | ||
155 | #include <boost/container/detail/config_end.hpp> | |
156 | ||
157 | #endif //BOOST_CONTAINER_DETAIL_BLOCK_SLIST_HEADER |