1 | /////////////////////////////////////////////////////////////////////////////// |
2 | // |
3 | // (C) Copyright Ion Gaztanaga 2005-2012. 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/interprocess for documentation. |
8 | // |
9 | /////////////////////////////////////////////////////////////////////////////// |
10 | |
11 | #ifndef BOOST_INTERPROCESS_EXPAND_BWD_TEST_ALLOCATOR_HPP |
12 | #define BOOST_INTERPROCESS_EXPAND_BWD_TEST_ALLOCATOR_HPP |
13 | |
14 | #if defined (_MSC_VER) |
15 | # pragma once |
16 | #endif |
17 | |
18 | #include <boost/interprocess/detail/config_begin.hpp> |
19 | #include <boost/interprocess/detail/workaround.hpp> |
20 | |
21 | #include <boost/interprocess/interprocess_fwd.hpp> |
22 | #include <boost/interprocess/containers/allocation_type.hpp> |
23 | #include <boost/assert.hpp> |
24 | #include <boost/interprocess/detail/utilities.hpp> |
25 | #include <boost/interprocess/containers/version_type.hpp> |
26 | #include <boost/interprocess/exceptions.hpp> |
27 | #include <boost/move/adl_move_swap.hpp> |
28 | #include <memory> |
29 | #include <cstddef> |
30 | #include <cassert> |
31 | #include <new> |
32 | |
33 | //!\file |
34 | //!Describes an allocator to test expand capabilities |
35 | |
36 | namespace boost { |
37 | namespace interprocess { |
38 | namespace test { |
39 | |
40 | //This allocator just allows two allocations. The first one will return |
41 | //mp_buffer + m_offset configured in the constructor. The second one |
42 | //will return mp_buffer. |
43 | template<class T> |
44 | class expand_bwd_test_allocator |
45 | { |
46 | private: |
47 | typedef expand_bwd_test_allocator<T> self_t; |
48 | typedef void * aux_pointer_t; |
49 | typedef const void * cvoid_ptr; |
50 | |
51 | template<class T2> |
52 | expand_bwd_test_allocator& operator=(const expand_bwd_test_allocator<T2>&); |
53 | |
54 | expand_bwd_test_allocator& operator=(const expand_bwd_test_allocator&); |
55 | |
56 | public: |
57 | typedef T value_type; |
58 | typedef T * pointer; |
59 | typedef const T * const_pointer; |
60 | typedef typename ipcdetail::add_reference |
61 | <value_type>::type reference; |
62 | typedef typename ipcdetail::add_reference |
63 | <const value_type>::type const_reference; |
64 | typedef std::size_t size_type; |
65 | |
66 | typedef boost::interprocess::version_type<expand_bwd_test_allocator, 2> version; |
67 | |
68 | //Dummy multiallocation chain |
69 | struct multiallocation_chain{}; |
70 | |
71 | template<class T2> |
72 | struct rebind |
73 | { typedef expand_bwd_test_allocator<T2> other; }; |
74 | |
75 | //!Constructor from the segment manager. Never throws |
76 | expand_bwd_test_allocator(T *buf, size_type sz, size_type offset) |
77 | : mp_buffer(buf), m_size(sz) |
78 | , m_offset(offset), m_allocations(0){ } |
79 | |
80 | //!Constructor from other expand_bwd_test_allocator. Never throws |
81 | expand_bwd_test_allocator(const expand_bwd_test_allocator &other) |
82 | : mp_buffer(other.mp_buffer), m_size(other.m_size) |
83 | , m_offset(other.m_offset), m_allocations(0){ } |
84 | |
85 | //!Constructor from related expand_bwd_test_allocator. Never throws |
86 | template<class T2> |
87 | expand_bwd_test_allocator(const expand_bwd_test_allocator<T2> &other) |
88 | : mp_buffer(other.mp_buffer), m_size(other.m_size) |
89 | , m_offset(other.m_offset), m_allocations(0){ } |
90 | |
91 | pointer address(reference value) |
92 | { return pointer(addressof(value)); } |
93 | |
94 | const_pointer address(const_reference value) const |
95 | { return const_pointer(addressof(value)); } |
96 | |
97 | pointer allocate(size_type , cvoid_ptr hint = 0) |
98 | { (void)hint; return 0; } |
99 | |
100 | void deallocate(const pointer &, size_type) |
101 | {} |
102 | |
103 | template<class Convertible> |
104 | void construct(pointer ptr, const Convertible &value) |
105 | { new((void*)ptr) value_type(value); } |
106 | |
107 | void destroy(pointer ptr) |
108 | { (*ptr).~value_type(); } |
109 | |
110 | size_type max_size() const |
111 | { return m_size; } |
112 | |
113 | friend void swap(self_t &alloc1, self_t &alloc2) |
114 | { |
115 | ::boost::adl_move_swap(alloc1.mp_buffer, alloc2.mp_buffer); |
116 | ::boost::adl_move_swap(alloc1.m_size, alloc2.m_size); |
117 | ::boost::adl_move_swap(alloc1.m_offset, alloc2.m_offset); |
118 | } |
119 | |
120 | //Experimental version 2 expand_bwd_test_allocator functions |
121 | |
122 | pointer allocation_command(boost::interprocess::allocation_type command, |
123 | size_type limit_size, size_type &prefer_in_recvd_out_size, pointer &reuse) |
124 | { |
125 | (void)reuse; (void)command; |
126 | //This allocator only expands backwards! |
127 | assert(m_allocations == 0 || (command & boost::interprocess::expand_bwd)); |
128 | prefer_in_recvd_out_size = limit_size; |
129 | |
130 | if(m_allocations == 0){ |
131 | if((m_offset + limit_size) > m_size){ |
132 | assert(0); |
133 | } |
134 | ++m_allocations; |
135 | return mp_buffer + std::ptrdiff_t(m_offset); |
136 | } |
137 | else if(m_allocations == 1){ |
138 | if(limit_size > m_size){ |
139 | assert(0); |
140 | } |
141 | ++m_allocations; |
142 | return mp_buffer; |
143 | } |
144 | else{ |
145 | assert(0); |
146 | throw std::bad_alloc(); |
147 | } |
148 | } |
149 | |
150 | //!Returns maximum the number of objects the previously allocated memory |
151 | //!pointed by p can hold. |
152 | size_type size(const pointer &p) const |
153 | { (void)p; return m_size; } |
154 | |
155 | //!Allocates just one object. Memory allocated with this function |
156 | //!must be deallocated only with deallocate_one(). |
157 | //!Throws boost::interprocess::bad_alloc if there is no enough memory |
158 | pointer allocate_one() |
159 | { return this->allocate(1); } |
160 | |
161 | //!Deallocates memory previously allocated with allocate_one(). |
162 | //!You should never use deallocate_one to deallocate memory allocated |
163 | //!with other functions different from allocate_one(). Never throws |
164 | void deallocate_one(const pointer &p) |
165 | { return this->deallocate(p, 1); } |
166 | |
167 | pointer mp_buffer; |
168 | size_type m_size; |
169 | size_type m_offset; |
170 | char m_allocations; |
171 | }; |
172 | |
173 | //!Equality test for same type of expand_bwd_test_allocator |
174 | template<class T> inline |
175 | bool operator==(const expand_bwd_test_allocator<T> &, |
176 | const expand_bwd_test_allocator<T> &) |
177 | { return false; } |
178 | |
179 | //!Inequality test for same type of expand_bwd_test_allocator |
180 | template<class T> inline |
181 | bool operator!=(const expand_bwd_test_allocator<T> &, |
182 | const expand_bwd_test_allocator<T> &) |
183 | { return true; } |
184 | |
185 | } //namespace test { |
186 | } //namespace interprocess { |
187 | } //namespace boost { |
188 | |
189 | #include <boost/interprocess/detail/config_end.hpp> |
190 | |
191 | #endif //BOOST_INTERPROCESS_EXPAND_BWD_TEST_ALLOCATOR_HPP |
192 | |
193 | |