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_CACHED_NODE_ALLOCATOR_HPP
12 #define BOOST_INTERPROCESS_CACHED_NODE_ALLOCATOR_HPP
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/interprocess/detail/config_begin.hpp>
23 #include <boost/interprocess/detail/workaround.hpp>
24 
25 #include <boost/interprocess/interprocess_fwd.hpp>
26 #include <boost/interprocess/allocators/detail/node_pool.hpp>
27 #include <boost/interprocess/allocators/detail/allocator_common.hpp>
28 #include <boost/interprocess/detail/workaround.hpp>
29 #include <boost/interprocess/detail/utilities.hpp>
30 #include <boost/interprocess/containers/version_type.hpp>
31 #include <boost/interprocess/allocators/detail/node_tools.hpp>
32 #include <cstddef>
33 
34 //!\file
35 //!Describes cached_cached_node_allocator pooled shared memory STL compatible allocator
36 
37 namespace boost {
38 namespace interprocess {
39 
40 
41 #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
42 
43 namespace ipcdetail {
44 
45 template < class T
46          , class SegmentManager
47          , std::size_t NodesPerBlock = 64
48          >
49 class cached_node_allocator_v1
50    :  public ipcdetail::cached_allocator_impl
51          < T
52          , ipcdetail::shared_node_pool
53             < SegmentManager
54             , sizeof_value<T>::value
55             , NodesPerBlock
56             >
57          , 1>
58 {
59    public:
60    typedef ipcdetail::cached_allocator_impl
61          < T
62          , ipcdetail::shared_node_pool
63             < SegmentManager
64             , sizeof_value<T>::value
65             , NodesPerBlock
66             >
67          , 1> base_t;
68 
69    template<class T2>
70    struct rebind
71    {
72       typedef cached_node_allocator_v1
73          <T2, SegmentManager, NodesPerBlock>  other;
74    };
75 
76    typedef typename base_t::size_type size_type;
77 
cached_node_allocator_v1(SegmentManager * segment_mngr,size_type max_cached_nodes=base_t::DEFAULT_MAX_CACHED_NODES)78    cached_node_allocator_v1(SegmentManager *segment_mngr,
79                          size_type max_cached_nodes = base_t::DEFAULT_MAX_CACHED_NODES)
80       : base_t(segment_mngr, max_cached_nodes)
81    {}
82 
83    template<class T2>
cached_node_allocator_v1(const cached_node_allocator_v1<T2,SegmentManager,NodesPerBlock> & other)84    cached_node_allocator_v1
85       (const cached_node_allocator_v1
86          <T2, SegmentManager, NodesPerBlock> &other)
87       : base_t(other)
88    {}
89 };
90 
91 }  //namespace ipcdetail{
92 
93 #endif   //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
94 
95 template < class T
96          , class SegmentManager
97          , std::size_t NodesPerBlock
98          >
99 class cached_node_allocator
100    #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
101    :  public ipcdetail::cached_allocator_impl
102          < T
103          , ipcdetail::shared_node_pool
104             < SegmentManager
105             , sizeof_value<T>::value
106             , NodesPerBlock
107             >
108          , 2>
109    #endif   //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
110 {
111 
112    #ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
113    public:
114    typedef ipcdetail::cached_allocator_impl
115          < T
116          , ipcdetail::shared_node_pool
117             < SegmentManager
118             , sizeof_value<T>::value
119             , NodesPerBlock
120             >
121          , 2> base_t;
122 
123    public:
124    typedef boost::interprocess::version_type<cached_node_allocator, 2>   version;
125    typedef typename base_t::size_type size_type;
126 
127    template<class T2>
128    struct rebind
129    {
130       typedef cached_node_allocator<T2, SegmentManager, NodesPerBlock>  other;
131    };
132 
cached_node_allocator(SegmentManager * segment_mngr,size_type max_cached_nodes=base_t::DEFAULT_MAX_CACHED_NODES)133    cached_node_allocator(SegmentManager *segment_mngr,
134                          size_type max_cached_nodes = base_t::DEFAULT_MAX_CACHED_NODES)
135       : base_t(segment_mngr, max_cached_nodes)
136    {}
137 
138    template<class T2>
cached_node_allocator(const cached_node_allocator<T2,SegmentManager,NodesPerBlock> & other)139    cached_node_allocator
140       (const cached_node_allocator<T2, SegmentManager, NodesPerBlock> &other)
141       : base_t(other)
142    {}
143 
144    #else
145    public:
146    typedef implementation_defined::segment_manager       segment_manager;
147    typedef segment_manager::void_pointer                 void_pointer;
148    typedef implementation_defined::pointer               pointer;
149    typedef implementation_defined::const_pointer         const_pointer;
150    typedef T                                             value_type;
151    typedef typename ipcdetail::add_reference
152                      <value_type>::type                  reference;
153    typedef typename ipcdetail::add_reference
154                      <const value_type>::type            const_reference;
155    typedef typename SegmentManager::size_type            size_type;
156    typedef typename SegmentManager::difference_type      difference_type;
157 
158    //!Obtains cached_node_allocator from
159    //!cached_node_allocator
160    template<class T2>
161    struct rebind
162    {
163       typedef cached_node_allocator<T2, SegmentManager> other;
164    };
165 
166    private:
167    //!Not assignable from
168    //!related cached_node_allocator
169    template<class T2, class SegmentManager2, std::size_t N2>
170    cached_node_allocator& operator=
171       (const cached_node_allocator<T2, SegmentManager2, N2>&);
172 
173    //!Not assignable from
174    //!other cached_node_allocator
175    cached_node_allocator& operator=(const cached_node_allocator&);
176 
177    public:
178    //!Constructor from a segment manager. If not present, constructs a node
179    //!pool. Increments the reference count of the associated node pool.
180    //!Can throw boost::interprocess::bad_alloc
181    cached_node_allocator(segment_manager *segment_mngr);
182 
183    //!Copy constructor from other cached_node_allocator. Increments the reference
184    //!count of the associated node pool. Never throws
185    cached_node_allocator(const cached_node_allocator &other);
186 
187    //!Copy constructor from related cached_node_allocator. If not present, constructs
188    //!a node pool. Increments the reference count of the associated node pool.
189    //!Can throw boost::interprocess::bad_alloc
190    template<class T2>
191    cached_node_allocator
192       (const cached_node_allocator<T2, SegmentManager, NodesPerBlock> &other);
193 
194    //!Destructor, removes node_pool_t from memory
195    //!if its reference count reaches to zero. Never throws
196    ~cached_node_allocator();
197 
198    //!Returns a pointer to the node pool.
199    //!Never throws
200    node_pool_t* get_node_pool() const;
201 
202    //!Returns the segment manager.
203    //!Never throws
204    segment_manager* get_segment_manager()const;
205 
206    //!Returns the number of elements that could be allocated.
207    //!Never throws
208    size_type max_size() const;
209 
210    //!Allocate memory for an array of count elements.
211    //!Throws boost::interprocess::bad_alloc if there is no enough memory
212    pointer allocate(size_type count, cvoid_pointer hint = 0);
213 
214    //!Deallocate allocated memory.
215    //!Never throws
216    void deallocate(const pointer &ptr, size_type count);
217 
218    //!Deallocates all free blocks
219    //!of the pool
220    void deallocate_free_blocks();
221 
222    //!Swaps allocators. Does not throw. If each allocator is placed in a
223    //!different memory segment, the result is undefined.
224    friend void swap(self_t &alloc1, self_t &alloc2);
225 
226    //!Returns address of mutable object.
227    //!Never throws
228    pointer address(reference value) const;
229 
230    //!Returns address of non mutable object.
231    //!Never throws
232    const_pointer address(const_reference value) const;
233 
234    //!Default construct an object.
235    //!Throws if T's default constructor throws
236    void construct(const pointer &ptr, const_reference v);
237 
238    //!Destroys object. Throws if object's
239    //!destructor throws
240    void destroy(const pointer &ptr);
241 
242    //!Returns maximum the number of objects the previously allocated memory
243    //!pointed by p can hold. This size only works for memory allocated with
244    //!allocate, allocation_command and allocate_many.
245    size_type size(const pointer &p) const;
246 
247    pointer allocation_command(boost::interprocess::allocation_type command,
248                            size_type limit_size, size_type &prefer_in_recvd_out_size, pointer &reuse);
249 
250    //!Allocates many elements of size elem_size in a contiguous block
251    //!of memory. The minimum number to be allocated is min_elements,
252    //!the preferred and maximum number is
253    //!preferred_elements. The number of actually allocated elements is
254    //!will be assigned to received_size. The elements must be deallocated
255    //!with deallocate(...)
256    void allocate_many(size_type elem_size, size_type num_elements, multiallocation_chain &chain);
257 
258    //!Allocates n_elements elements, each one of size elem_sizes[i]in a
259    //!contiguous block
260    //!of memory. The elements must be deallocated
261    void allocate_many(const size_type *elem_sizes, size_type n_elements, multiallocation_chain &chain);
262 
263    //!Allocates many elements of size elem_size in a contiguous block
264    //!of memory. The minimum number to be allocated is min_elements,
265    //!the preferred and maximum number is
266    //!preferred_elements. The number of actually allocated elements is
267    //!will be assigned to received_size. The elements must be deallocated
268    //!with deallocate(...)
269    void deallocate_many(multiallocation_chain &chain);
270 
271    //!Allocates just one object. Memory allocated with this function
272    //!must be deallocated only with deallocate_one().
273    //!Throws boost::interprocess::bad_alloc if there is no enough memory
274    pointer allocate_one();
275 
276    //!Allocates many elements of size == 1 in a contiguous block
277    //!of memory. The minimum number to be allocated is min_elements,
278    //!the preferred and maximum number is
279    //!preferred_elements. The number of actually allocated elements is
280    //!will be assigned to received_size. Memory allocated with this function
281    //!must be deallocated only with deallocate_one().
282    multiallocation_chain allocate_individual(size_type num_elements);
283 
284    //!Deallocates memory previously allocated with allocate_one().
285    //!You should never use deallocate_one to deallocate memory allocated
286    //!with other functions different from allocate_one(). Never throws
287    void deallocate_one(const pointer &p);
288 
289    //!Allocates many elements of size == 1 in a contiguous block
290    //!of memory. The minimum number to be allocated is min_elements,
291    //!the preferred and maximum number is
292    //!preferred_elements. The number of actually allocated elements is
293    //!will be assigned to received_size. Memory allocated with this function
294    //!must be deallocated only with deallocate_one().
295    void deallocate_individual(multiallocation_chain it);
296    //!Sets the new max cached nodes value. This can provoke deallocations
297    //!if "newmax" is less than current cached nodes. Never throws
298    void set_max_cached_nodes(size_type newmax);
299 
300    //!Returns the max cached nodes parameter.
301    //!Never throws
302    size_type get_max_cached_nodes() const;
303    #endif
304 };
305 
306 #ifdef BOOST_INTERPROCESS_DOXYGEN_INVOKED
307 
308 //!Equality test for same type
309 //!of cached_node_allocator
310 template<class T, class S, std::size_t NPC> inline
311 bool operator==(const cached_node_allocator<T, S, NPC> &alloc1,
312                 const cached_node_allocator<T, S, NPC> &alloc2);
313 
314 //!Inequality test for same type
315 //!of cached_node_allocator
316 template<class T, class S, std::size_t NPC> inline
317 bool operator!=(const cached_node_allocator<T, S, NPC> &alloc1,
318                 const cached_node_allocator<T, S, NPC> &alloc2);
319 
320 #endif
321 
322 }  //namespace interprocess {
323 }  //namespace boost {
324 
325 #include <boost/interprocess/detail/config_end.hpp>
326 
327 #endif   //#ifndef BOOST_INTERPROCESS_CACHED_NODE_ALLOCATOR_HPP
328 
329