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 typedef std::ptrdiff_t difference_type;
66
67 typedef boost::interprocess::version_type<expand_bwd_test_allocator, 2> version;
68
69 //Dummy multiallocation chain
70 struct multiallocation_chain{};
71
72 template<class T2>
73 struct rebind
74 { typedef expand_bwd_test_allocator<T2> other; };
75
76 //!Constructor from the segment manager. Never throws
expand_bwd_test_allocator(T * buf,size_type sz,difference_type offset)77 expand_bwd_test_allocator(T *buf, size_type sz, difference_type offset)
78 : mp_buffer(buf), m_size(sz)
79 , m_offset(offset), m_allocations(0){ }
80
81 //!Constructor from other expand_bwd_test_allocator. Never throws
expand_bwd_test_allocator(const expand_bwd_test_allocator & other)82 expand_bwd_test_allocator(const expand_bwd_test_allocator &other)
83 : mp_buffer(other.mp_buffer), m_size(other.m_size)
84 , m_offset(other.m_offset), m_allocations(0){ }
85
86 //!Constructor from related expand_bwd_test_allocator. Never throws
87 template<class T2>
expand_bwd_test_allocator(const expand_bwd_test_allocator<T2> & other)88 expand_bwd_test_allocator(const expand_bwd_test_allocator<T2> &other)
89 : mp_buffer(other.mp_buffer), m_size(other.m_size)
90 , m_offset(other.m_offset), m_allocations(0){ }
91
address(reference value)92 pointer address(reference value)
93 { return pointer(addressof(value)); }
94
address(const_reference value) const95 const_pointer address(const_reference value) const
96 { return const_pointer(addressof(value)); }
97
allocate(size_type,cvoid_ptr hint=0)98 pointer allocate(size_type , cvoid_ptr hint = 0)
99 { (void)hint; return 0; }
100
deallocate(const pointer &,size_type)101 void deallocate(const pointer &, size_type)
102 {}
103
104 template<class Convertible>
construct(pointer ptr,const Convertible & value)105 void construct(pointer ptr, const Convertible &value)
106 { new((void*)ptr) value_type(value); }
107
destroy(pointer ptr)108 void destroy(pointer ptr)
109 { (*ptr).~value_type(); }
110
max_size() const111 size_type max_size() const
112 { return m_size; }
113
swap(self_t & alloc1,self_t & alloc2)114 friend void swap(self_t &alloc1, self_t &alloc2)
115 {
116 ::boost::adl_move_swap(alloc1.mp_buffer, alloc2.mp_buffer);
117 ::boost::adl_move_swap(alloc1.m_size, alloc2.m_size);
118 ::boost::adl_move_swap(alloc1.m_offset, alloc2.m_offset);
119 }
120
121 //Experimental version 2 expand_bwd_test_allocator functions
122
allocation_command(boost::interprocess::allocation_type command,size_type limit_size,size_type & prefer_in_recvd_out_size,pointer & reuse)123 pointer allocation_command(boost::interprocess::allocation_type command,
124 size_type limit_size, size_type &prefer_in_recvd_out_size, pointer &reuse)
125 {
126 (void)reuse; (void)command;
127 //This allocator only expands backwards!
128 assert(m_allocations == 0 || (command & boost::interprocess::expand_bwd));
129 prefer_in_recvd_out_size = limit_size;
130
131 if(m_allocations == 0){
132 if((m_offset + limit_size) > m_size){
133 assert(0);
134 }
135 ++m_allocations;
136 return mp_buffer + m_offset;
137 }
138 else if(m_allocations == 1){
139 if(limit_size > m_size){
140 assert(0);
141 }
142 ++m_allocations;
143 return mp_buffer;
144 }
145 else{
146 assert(0);
147 throw std::bad_alloc();
148 }
149 }
150
151 //!Returns maximum the number of objects the previously allocated memory
152 //!pointed by p can hold.
size(const pointer & p) const153 size_type size(const pointer &p) const
154 { (void)p; return m_size; }
155
156 //!Allocates just one object. Memory allocated with this function
157 //!must be deallocated only with deallocate_one().
158 //!Throws boost::interprocess::bad_alloc if there is no enough memory
allocate_one()159 pointer allocate_one()
160 { return this->allocate(1); }
161
162 //!Deallocates memory previously allocated with allocate_one().
163 //!You should never use deallocate_one to deallocate memory allocated
164 //!with other functions different from allocate_one(). Never throws
deallocate_one(const pointer & p)165 void deallocate_one(const pointer &p)
166 { return this->deallocate(p, 1); }
167
168 pointer mp_buffer;
169 size_type m_size;
170 difference_type m_offset;
171 char m_allocations;
172 };
173
174 //!Equality test for same type of expand_bwd_test_allocator
175 template<class T> inline
operator ==(const expand_bwd_test_allocator<T> &,const expand_bwd_test_allocator<T> &)176 bool operator==(const expand_bwd_test_allocator<T> &,
177 const expand_bwd_test_allocator<T> &)
178 { return false; }
179
180 //!Inequality test for same type of expand_bwd_test_allocator
181 template<class T> inline
operator !=(const expand_bwd_test_allocator<T> &,const expand_bwd_test_allocator<T> &)182 bool operator!=(const expand_bwd_test_allocator<T> &,
183 const expand_bwd_test_allocator<T> &)
184 { return true; }
185
186 } //namespace test {
187 } //namespace interprocess {
188 } //namespace boost {
189
190 #include <boost/interprocess/detail/config_end.hpp>
191
192 #endif //BOOST_INTERPROCESS_EXPAND_BWD_TEST_ALLOCATOR_HPP
193
194