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