1809a8d91aa755a7dd6d68688903f71ee83ea5b3
[platform/upstream/boost.git] / boost / interprocess / detail / segment_manager_helper.hpp
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_SEGMENT_MANAGER_BASE_HPP
12 #define BOOST_INTERPROCESS_SEGMENT_MANAGER_BASE_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/intrusive/pointer_traits.hpp>
22
23 #include <boost/detail/no_exceptions_support.hpp>
24 #include <boost/interprocess/detail/type_traits.hpp>
25 #include <boost/interprocess/detail/utilities.hpp>
26 #include <boost/interprocess/detail/in_place_interface.hpp>
27 #include <boost/interprocess/exceptions.hpp>
28 #include <boost/type_traits/make_unsigned.hpp>
29 #include <boost/type_traits/alignment_of.hpp>
30 #include <boost/intrusive/pointer_traits.hpp>
31 #include <cstddef>   //std::size_t
32 #include <string>    //char_traits
33 #include <new>       //std::nothrow
34 #include <utility>   //std::pair
35 #include <iterator>  //std::iterator_traits
36 #include <boost/assert.hpp>   //BOOST_ASSERT
37 #include <functional>   //unary_function
38 #ifndef BOOST_NO_EXCEPTIONS
39 #include <exception>
40 #endif
41
42 //!\file
43 //!Describes the object placed in a memory segment that provides
44 //!named object allocation capabilities.
45
46 namespace boost{
47 namespace interprocess{
48
49 template<class MemoryManager>
50 class segment_manager_base;
51
52 //!An integer that describes the type of the
53 //!instance constructed in memory
54 enum instance_type {   anonymous_type, named_type, unique_type, max_allocation_type };
55
56 namespace ipcdetail{
57
58 template<class MemoryAlgorithm>
59 class mem_algo_deallocator
60 {
61    void *            m_ptr;
62    MemoryAlgorithm & m_algo;
63
64    public:
65    mem_algo_deallocator(void *ptr, MemoryAlgorithm &algo)
66       :  m_ptr(ptr), m_algo(algo)
67    {}
68
69    void release()
70    {  m_ptr = 0;  }
71
72    ~mem_algo_deallocator()
73    {  if(m_ptr) m_algo.deallocate(m_ptr);  }
74 };
75
76 template<class size_type>
77 struct block_header
78 {
79    size_type      m_value_bytes;
80    unsigned short m_num_char;
81    unsigned char  m_value_alignment;
82    unsigned char  m_alloc_type_sizeof_char;
83
84    block_header(size_type val_bytes
85                ,size_type val_alignment
86                ,unsigned char al_type
87                ,std::size_t szof_char
88                ,std::size_t num_char
89                )
90       :  m_value_bytes(val_bytes)
91       ,  m_num_char((unsigned short)num_char)
92       ,  m_value_alignment((unsigned char)val_alignment)
93       ,  m_alloc_type_sizeof_char( (al_type << 5u) | ((unsigned char)szof_char & 0x1F) )
94    {};
95
96    template<class T>
97    block_header &operator= (const T& )
98    {  return *this;  }
99
100    size_type total_size() const
101    {
102       if(alloc_type() != anonymous_type){
103          return name_offset() + (m_num_char+1)*sizeof_char();
104       }
105       else{
106          return this->value_offset() + m_value_bytes;
107       }
108    }
109
110    size_type value_bytes() const
111    {  return m_value_bytes;   }
112
113    template<class Header>
114    size_type total_size_with_header() const
115    {
116       return get_rounded_size
117                ( size_type(sizeof(Header))
118             , size_type(::boost::alignment_of<block_header<size_type> >::value))
119            + total_size();
120    }
121
122    unsigned char alloc_type() const
123    {  return (m_alloc_type_sizeof_char >> 5u)&(unsigned char)0x7;  }
124
125    unsigned char sizeof_char() const
126    {  return m_alloc_type_sizeof_char & (unsigned char)0x1F;  }
127
128    template<class CharType>
129    CharType *name() const
130    {
131       return const_cast<CharType*>(reinterpret_cast<const CharType*>
132          (reinterpret_cast<const char*>(this) + name_offset()));
133    }
134
135    unsigned short name_length() const
136    {  return m_num_char;   }
137
138    size_type name_offset() const
139    {
140       return this->value_offset() + get_rounded_size(size_type(m_value_bytes), size_type(sizeof_char()));
141    }
142
143    void *value() const
144    {
145       return const_cast<char*>((reinterpret_cast<const char*>(this) + this->value_offset()));
146    }
147
148    size_type value_offset() const
149    {
150       return get_rounded_size(size_type(sizeof(block_header<size_type>)), size_type(m_value_alignment));
151    }
152
153    template<class CharType>
154    bool less_comp(const block_header<size_type> &b) const
155    {
156       return m_num_char < b.m_num_char ||
157              (m_num_char < b.m_num_char &&
158                std::char_traits<CharType>::compare
159                   (name<CharType>(), b.name<CharType>(), m_num_char) < 0);
160    }
161
162    template<class CharType>
163    bool equal_comp(const block_header<size_type> &b) const
164    {
165       return m_num_char == b.m_num_char &&
166              std::char_traits<CharType>::compare
167                (name<CharType>(), b.name<CharType>(), m_num_char) == 0;
168    }
169
170    template<class T>
171    static block_header<size_type> *block_header_from_value(T *value)
172    {  return block_header_from_value(value, sizeof(T), ::boost::alignment_of<T>::value);  }
173
174    static block_header<size_type> *block_header_from_value(const void *value, std::size_t sz, std::size_t algn)
175    {
176       block_header * hdr =
177          const_cast<block_header*>
178             (reinterpret_cast<const block_header*>(reinterpret_cast<const char*>(value) -
179                get_rounded_size(sizeof(block_header), algn)));
180       (void)sz;
181       //Some sanity checks
182       BOOST_ASSERT(hdr->m_value_alignment == algn);
183       BOOST_ASSERT(hdr->m_value_bytes % sz == 0);
184       return hdr;
185    }
186
187    template<class Header>
188    static block_header<size_type> *from_first_header(Header *header)
189    {
190       block_header<size_type> * hdr =
191          reinterpret_cast<block_header<size_type>*>(reinterpret_cast<char*>(header) +
192        get_rounded_size(size_type(sizeof(Header)), size_type(::boost::alignment_of<block_header<size_type> >::value)));
193       //Some sanity checks
194       return hdr;
195    }
196
197    template<class Header>
198    static Header *to_first_header(block_header<size_type> *bheader)
199    {
200       Header * hdr =
201          reinterpret_cast<Header*>(reinterpret_cast<char*>(bheader) -
202        get_rounded_size(size_type(sizeof(Header)), size_type(::boost::alignment_of<block_header<size_type> >::value)));
203       //Some sanity checks
204       return hdr;
205    }
206 };
207
208 inline void array_construct(void *mem, std::size_t num, in_place_interface &table)
209 {
210    //Try constructors
211    std::size_t constructed = 0;
212    BOOST_TRY{
213       table.construct_n(mem, num, constructed);
214    }
215    //If there is an exception call destructors and erase index node
216    BOOST_CATCH(...){
217       std::size_t destroyed = 0;
218       table.destroy_n(mem, constructed, destroyed);
219       BOOST_RETHROW
220    }
221    BOOST_CATCH_END
222 }
223
224 template<class CharT>
225 struct intrusive_compare_key
226 {
227    typedef CharT char_type;
228
229    intrusive_compare_key(const CharT *str, std::size_t len)
230       :  mp_str(str), m_len(len)
231    {}
232
233    const CharT *  mp_str;
234    std::size_t    m_len;
235 };
236
237 //!This struct indicates an anonymous object creation
238 //!allocation
239 template<instance_type type>
240 class instance_t
241 {
242    instance_t(){}
243 };
244
245 template<class T>
246 struct char_if_void
247 {
248    typedef T type;
249 };
250
251 template<>
252 struct char_if_void<void>
253 {
254    typedef char type;
255 };
256
257 typedef instance_t<anonymous_type>  anonymous_instance_t;
258 typedef instance_t<unique_type>     unique_instance_t;
259
260
261 template<class Hook, class CharType, class SizeType>
262 struct intrusive_value_type_impl
263    :  public Hook
264 {
265    private:
266    //Non-copyable
267    intrusive_value_type_impl(const intrusive_value_type_impl &);
268    intrusive_value_type_impl& operator=(const intrusive_value_type_impl &);
269
270    public:
271    typedef CharType char_type;
272    typedef SizeType size_type;
273
274    intrusive_value_type_impl(){}
275
276    enum  {  BlockHdrAlignment = ::boost::alignment_of<block_header<size_type> >::value  };
277
278    block_header<size_type> *get_block_header() const
279    {
280       return const_cast<block_header<size_type>*>
281          (reinterpret_cast<const block_header<size_type> *>(reinterpret_cast<const char*>(this) +
282             get_rounded_size(size_type(sizeof(*this)), size_type(BlockHdrAlignment))));
283    }
284
285    bool operator <(const intrusive_value_type_impl<Hook, CharType, SizeType> & other) const
286    {  return (this->get_block_header())->template less_comp<CharType>(*other.get_block_header());  }
287
288    bool operator ==(const intrusive_value_type_impl<Hook, CharType, SizeType> & other) const
289    {  return (this->get_block_header())->template equal_comp<CharType>(*other.get_block_header());  }
290
291    static intrusive_value_type_impl *get_intrusive_value_type(block_header<size_type> *hdr)
292    {
293       return reinterpret_cast<intrusive_value_type_impl *>(reinterpret_cast<char*>(hdr) -
294          get_rounded_size(size_type(sizeof(intrusive_value_type_impl)), size_type(BlockHdrAlignment)));
295    }
296
297    CharType *name() const
298    {  return get_block_header()->template name<CharType>(); }
299
300    unsigned short name_length() const
301    {  return get_block_header()->name_length(); }
302
303    void *value() const
304    {  return get_block_header()->value(); }
305 };
306
307 template<class CharType>
308 class char_ptr_holder
309 {
310    public:
311    char_ptr_holder(const CharType *name)
312       : m_name(name)
313    {}
314
315    char_ptr_holder(const anonymous_instance_t *)
316       : m_name(static_cast<CharType*>(0))
317    {}
318
319    char_ptr_holder(const unique_instance_t *)
320       : m_name(reinterpret_cast<CharType*>(-1))
321    {}
322
323    operator const CharType *()
324    {  return m_name;  }
325
326    const CharType *get() const
327    {  return m_name;  }
328
329    bool is_unique() const
330    {  return m_name == reinterpret_cast<CharType*>(-1);  }
331
332    bool is_anonymous() const
333    {  return m_name == static_cast<CharType*>(0);  }
334
335    private:
336    const CharType *m_name;
337 };
338
339 //!The key of the the named allocation information index. Stores an offset pointer
340 //!to a null terminated string and the length of the string to speed up sorting
341 template<class CharT, class VoidPointer>
342 struct index_key
343 {
344    typedef typename boost::intrusive::
345       pointer_traits<VoidPointer>::template
346          rebind_pointer<const CharT>::type               const_char_ptr_t;
347    typedef CharT                                         char_type;
348    typedef typename boost::intrusive::pointer_traits<const_char_ptr_t>::difference_type difference_type;
349    typedef typename boost::make_unsigned<difference_type>::type size_type;
350
351    private:
352    //Offset pointer to the object's name
353    const_char_ptr_t  mp_str;
354    //Length of the name buffer (null NOT included)
355    size_type         m_len;
356    public:
357
358    //!Constructor of the key
359    index_key (const char_type *nm, size_type length)
360       : mp_str(nm), m_len(length)
361    {}
362
363    //!Less than function for index ordering
364    bool operator < (const index_key & right) const
365    {
366       return (m_len < right.m_len) ||
367                (m_len == right.m_len &&
368                std::char_traits<char_type>::compare
369                   (to_raw_pointer(mp_str)
370               ,to_raw_pointer(right.mp_str), m_len) < 0);
371    }
372
373    //!Equal to function for index ordering
374    bool operator == (const index_key & right) const
375    {
376       return   m_len == right.m_len &&
377                std::char_traits<char_type>::compare
378                   (to_raw_pointer(mp_str),
379                    to_raw_pointer(right.mp_str), m_len) == 0;
380    }
381
382    void name(const CharT *nm)
383    {  mp_str = nm; }
384
385    void name_length(size_type len)
386    {  m_len = len; }
387
388    const CharT *name() const
389    {  return to_raw_pointer(mp_str); }
390
391    size_type name_length() const
392    {  return m_len; }
393 };
394
395 //!The index_data stores a pointer to a buffer and the element count needed
396 //!to know how many destructors must be called when calling destroy
397 template<class VoidPointer>
398 struct index_data
399 {
400    typedef VoidPointer void_pointer;
401    void_pointer    m_ptr;
402    index_data(void *ptr) : m_ptr(ptr){}
403
404    void *value() const
405    {  return static_cast<void*>(to_raw_pointer(m_ptr));  }
406 };
407
408 template<class MemoryAlgorithm>
409 struct segment_manager_base_type
410 {  typedef segment_manager_base<MemoryAlgorithm> type;   };
411
412 template<class CharT, class MemoryAlgorithm>
413 struct index_config
414 {
415    typedef typename MemoryAlgorithm::void_pointer        void_pointer;
416    typedef CharT                                         char_type;
417    typedef index_key<CharT, void_pointer>        key_type;
418    typedef index_data<void_pointer>              mapped_type;
419    typedef typename segment_manager_base_type
420       <MemoryAlgorithm>::type                            segment_manager_base;
421
422    template<class HeaderBase>
423    struct intrusive_value_type
424    {  typedef intrusive_value_type_impl<HeaderBase, CharT, typename segment_manager_base::size_type>  type; };
425
426    typedef intrusive_compare_key<CharT>            intrusive_compare_key_type;
427 };
428
429 template<class Iterator, bool intrusive>
430 class segment_manager_iterator_value_adaptor
431 {
432    typedef typename Iterator::value_type        iterator_val_t;
433    typedef typename iterator_val_t::char_type   char_type;
434
435    public:
436    segment_manager_iterator_value_adaptor(const typename Iterator::value_type &val)
437       :  m_val(&val)
438    {}
439
440    const char_type *name() const
441    {  return m_val->name(); }
442
443    unsigned short name_length() const
444    {  return m_val->name_length(); }
445
446    const void *value() const
447    {  return m_val->value(); }
448
449    const typename Iterator::value_type *m_val;
450 };
451
452
453 template<class Iterator>
454 class segment_manager_iterator_value_adaptor<Iterator, false>
455 {
456    typedef typename Iterator::value_type        iterator_val_t;
457    typedef typename iterator_val_t::first_type  first_type;
458    typedef typename iterator_val_t::second_type second_type;
459    typedef typename first_type::char_type       char_type;
460    typedef typename first_type::size_type       size_type;
461
462    public:
463    segment_manager_iterator_value_adaptor(const typename Iterator::value_type &val)
464       :  m_val(&val)
465    {}
466
467    const char_type *name() const
468    {  return m_val->first.name(); }
469
470    size_type name_length() const
471    {  return m_val->first.name_length(); }
472
473    const void *value() const
474    {
475       return reinterpret_cast<block_header<size_type>*>
476          (to_raw_pointer(m_val->second.m_ptr))->value();
477    }
478
479    const typename Iterator::value_type *m_val;
480 };
481
482 template<class Iterator, bool intrusive>
483 struct segment_manager_iterator_transform
484    :  std::unary_function< typename std::iterator_traits<Iterator>::value_type
485                          , segment_manager_iterator_value_adaptor<Iterator, intrusive> >
486 {
487    typedef segment_manager_iterator_value_adaptor<Iterator, intrusive> result_type;
488
489    result_type operator()(const typename std::iterator_traits<Iterator>::value_type &arg) const
490    {  return result_type(arg); }
491 };
492
493 }  //namespace ipcdetail {
494
495 //These pointers are the ones the user will use to
496 //indicate previous allocation types
497 static const ipcdetail::anonymous_instance_t   * anonymous_instance = 0;
498 static const ipcdetail::unique_instance_t      * unique_instance = 0;
499
500 namespace ipcdetail_really_deep_namespace {
501
502 //Otherwise, gcc issues a warning of previously defined
503 //anonymous_instance and unique_instance
504 struct dummy
505 {
506    dummy()
507    {
508       (void)anonymous_instance;
509       (void)unique_instance;
510    }
511 };
512
513 }  //detail_really_deep_namespace
514
515 }} //namespace boost { namespace interprocess
516
517 #include <boost/interprocess/detail/config_end.hpp>
518
519 #endif //#ifndef BOOST_INTERPROCESS_SEGMENT_MANAGER_BASE_HPP
520