Chris@16: ////////////////////////////////////////////////////////////////////////////// Chris@16: // Chris@16: // (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost Chris@16: // Software License, Version 1.0. (See accompanying file Chris@16: // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) Chris@16: // Chris@16: // See http://www.boost.org/libs/interprocess for documentation. Chris@16: // Chris@16: ////////////////////////////////////////////////////////////////////////////// Chris@16: Chris@16: #ifndef BOOST_INTERPROCESS_SEGMENT_MANAGER_BASE_HPP Chris@16: #define BOOST_INTERPROCESS_SEGMENT_MANAGER_BASE_HPP Chris@16: Chris@101: #ifndef BOOST_CONFIG_HPP Chris@101: # include Chris@101: #endif Chris@101: # Chris@101: #if defined(BOOST_HAS_PRAGMA_ONCE) Chris@16: # pragma once Chris@16: #endif Chris@16: Chris@16: #include Chris@16: #include Chris@16: Chris@101: // interprocess Chris@101: #include Chris@101: // interprocess/detail Chris@16: #include Chris@16: #include Chris@16: #include Chris@101: // container/detail Chris@101: #include //alignment_of Chris@101: #include Chris@101: // intrusive Chris@16: #include Chris@101: // move/detail Chris@101: #include //make_unsigned Chris@101: // other boost Chris@101: #include //BOOST_ASSERT Chris@101: #include Chris@101: // std Chris@16: #include //std::size_t Chris@16: Chris@16: //!\file Chris@16: //!Describes the object placed in a memory segment that provides Chris@16: //!named object allocation capabilities. Chris@16: Chris@16: namespace boost{ Chris@16: namespace interprocess{ Chris@16: Chris@16: template Chris@16: class segment_manager_base; Chris@16: Chris@16: //!An integer that describes the type of the Chris@16: //!instance constructed in memory Chris@16: enum instance_type { anonymous_type, named_type, unique_type, max_allocation_type }; Chris@16: Chris@16: namespace ipcdetail{ Chris@16: Chris@16: template Chris@16: class mem_algo_deallocator Chris@16: { Chris@16: void * m_ptr; Chris@16: MemoryAlgorithm & m_algo; Chris@16: Chris@16: public: Chris@16: mem_algo_deallocator(void *ptr, MemoryAlgorithm &algo) Chris@16: : m_ptr(ptr), m_algo(algo) Chris@16: {} Chris@16: Chris@16: void release() Chris@16: { m_ptr = 0; } Chris@16: Chris@16: ~mem_algo_deallocator() Chris@16: { if(m_ptr) m_algo.deallocate(m_ptr); } Chris@16: }; Chris@16: Chris@16: template Chris@16: struct block_header Chris@16: { Chris@16: size_type m_value_bytes; Chris@16: unsigned short m_num_char; Chris@16: unsigned char m_value_alignment; Chris@16: unsigned char m_alloc_type_sizeof_char; Chris@16: Chris@16: block_header(size_type val_bytes Chris@16: ,size_type val_alignment Chris@16: ,unsigned char al_type Chris@16: ,std::size_t szof_char Chris@16: ,std::size_t num_char Chris@16: ) Chris@16: : m_value_bytes(val_bytes) Chris@16: , m_num_char((unsigned short)num_char) Chris@16: , m_value_alignment((unsigned char)val_alignment) Chris@16: , m_alloc_type_sizeof_char( (al_type << 5u) | ((unsigned char)szof_char & 0x1F) ) Chris@16: {}; Chris@16: Chris@16: template Chris@16: block_header &operator= (const T& ) Chris@16: { return *this; } Chris@16: Chris@16: size_type total_size() const Chris@16: { Chris@16: if(alloc_type() != anonymous_type){ Chris@16: return name_offset() + (m_num_char+1)*sizeof_char(); Chris@16: } Chris@16: else{ Chris@16: return this->value_offset() + m_value_bytes; Chris@16: } Chris@16: } Chris@16: Chris@16: size_type value_bytes() const Chris@16: { return m_value_bytes; } Chris@16: Chris@16: template Chris@16: size_type total_size_with_header() const Chris@16: { Chris@16: return get_rounded_size Chris@16: ( size_type(sizeof(Header)) Chris@101: , size_type(::boost::container::container_detail::alignment_of >::value)) Chris@16: + total_size(); Chris@16: } Chris@16: Chris@16: unsigned char alloc_type() const Chris@16: { return (m_alloc_type_sizeof_char >> 5u)&(unsigned char)0x7; } Chris@16: Chris@16: unsigned char sizeof_char() const Chris@16: { return m_alloc_type_sizeof_char & (unsigned char)0x1F; } Chris@16: Chris@16: template Chris@16: CharType *name() const Chris@16: { Chris@16: return const_cast(reinterpret_cast Chris@16: (reinterpret_cast(this) + name_offset())); Chris@16: } Chris@16: Chris@16: unsigned short name_length() const Chris@16: { return m_num_char; } Chris@16: Chris@16: size_type name_offset() const Chris@16: { Chris@16: return this->value_offset() + get_rounded_size(size_type(m_value_bytes), size_type(sizeof_char())); Chris@16: } Chris@16: Chris@16: void *value() const Chris@16: { Chris@16: return const_cast((reinterpret_cast(this) + this->value_offset())); Chris@16: } Chris@16: Chris@16: size_type value_offset() const Chris@16: { Chris@16: return get_rounded_size(size_type(sizeof(block_header)), size_type(m_value_alignment)); Chris@16: } Chris@16: Chris@16: template Chris@16: bool less_comp(const block_header &b) const Chris@16: { Chris@16: return m_num_char < b.m_num_char || Chris@16: (m_num_char < b.m_num_char && Chris@101: std::char_traits::compare(name(), b.name(), m_num_char) < 0); Chris@16: } Chris@16: Chris@16: template Chris@16: bool equal_comp(const block_header &b) const Chris@16: { Chris@16: return m_num_char == b.m_num_char && Chris@101: std::char_traits::compare(name(), b.name(), m_num_char) == 0; Chris@16: } Chris@16: Chris@16: template Chris@16: static block_header *block_header_from_value(T *value) Chris@101: { return block_header_from_value(value, sizeof(T), ::boost::container::container_detail::alignment_of::value); } Chris@16: Chris@16: static block_header *block_header_from_value(const void *value, std::size_t sz, std::size_t algn) Chris@16: { Chris@16: block_header * hdr = Chris@16: const_cast Chris@16: (reinterpret_cast(reinterpret_cast(value) - Chris@16: get_rounded_size(sizeof(block_header), algn))); Chris@16: (void)sz; Chris@16: //Some sanity checks Chris@16: BOOST_ASSERT(hdr->m_value_alignment == algn); Chris@16: BOOST_ASSERT(hdr->m_value_bytes % sz == 0); Chris@16: return hdr; Chris@16: } Chris@16: Chris@16: template Chris@16: static block_header *from_first_header(Header *header) Chris@16: { Chris@16: block_header * hdr = Chris@16: reinterpret_cast*>(reinterpret_cast(header) + Chris@101: get_rounded_size( size_type(sizeof(Header)) Chris@101: , size_type(::boost::container::container_detail::alignment_of >::value))); Chris@16: //Some sanity checks Chris@16: return hdr; Chris@16: } Chris@16: Chris@16: template Chris@16: static Header *to_first_header(block_header *bheader) Chris@16: { Chris@16: Header * hdr = Chris@16: reinterpret_cast(reinterpret_cast(bheader) - Chris@101: get_rounded_size( size_type(sizeof(Header)) Chris@101: , size_type(::boost::container::container_detail::alignment_of >::value))); Chris@16: //Some sanity checks Chris@16: return hdr; Chris@16: } Chris@16: }; Chris@16: Chris@16: inline void array_construct(void *mem, std::size_t num, in_place_interface &table) Chris@16: { Chris@16: //Try constructors Chris@16: std::size_t constructed = 0; Chris@16: BOOST_TRY{ Chris@16: table.construct_n(mem, num, constructed); Chris@16: } Chris@16: //If there is an exception call destructors and erase index node Chris@16: BOOST_CATCH(...){ Chris@16: std::size_t destroyed = 0; Chris@16: table.destroy_n(mem, constructed, destroyed); Chris@16: BOOST_RETHROW Chris@16: } Chris@16: BOOST_CATCH_END Chris@16: } Chris@16: Chris@16: template Chris@16: struct intrusive_compare_key Chris@16: { Chris@16: typedef CharT char_type; Chris@16: Chris@16: intrusive_compare_key(const CharT *str, std::size_t len) Chris@16: : mp_str(str), m_len(len) Chris@16: {} Chris@16: Chris@16: const CharT * mp_str; Chris@16: std::size_t m_len; Chris@16: }; Chris@16: Chris@16: //!This struct indicates an anonymous object creation Chris@16: //!allocation Chris@16: template Chris@16: class instance_t Chris@16: { Chris@16: instance_t(){} Chris@16: }; Chris@16: Chris@16: template Chris@16: struct char_if_void Chris@16: { Chris@16: typedef T type; Chris@16: }; Chris@16: Chris@16: template<> Chris@16: struct char_if_void Chris@16: { Chris@16: typedef char type; Chris@16: }; Chris@16: Chris@16: typedef instance_t anonymous_instance_t; Chris@16: typedef instance_t unique_instance_t; Chris@16: Chris@16: Chris@16: template Chris@16: struct intrusive_value_type_impl Chris@16: : public Hook Chris@16: { Chris@16: private: Chris@16: //Non-copyable Chris@16: intrusive_value_type_impl(const intrusive_value_type_impl &); Chris@16: intrusive_value_type_impl& operator=(const intrusive_value_type_impl &); Chris@16: Chris@16: public: Chris@16: typedef CharType char_type; Chris@16: typedef SizeType size_type; Chris@16: Chris@16: intrusive_value_type_impl(){} Chris@16: Chris@101: enum { BlockHdrAlignment = ::boost::container::container_detail::alignment_of >::value }; Chris@16: Chris@16: block_header *get_block_header() const Chris@16: { Chris@16: return const_cast*> Chris@16: (reinterpret_cast *>(reinterpret_cast(this) + Chris@16: get_rounded_size(size_type(sizeof(*this)), size_type(BlockHdrAlignment)))); Chris@16: } Chris@16: Chris@16: bool operator <(const intrusive_value_type_impl & other) const Chris@16: { return (this->get_block_header())->template less_comp(*other.get_block_header()); } Chris@16: Chris@16: bool operator ==(const intrusive_value_type_impl & other) const Chris@16: { return (this->get_block_header())->template equal_comp(*other.get_block_header()); } Chris@16: Chris@16: static intrusive_value_type_impl *get_intrusive_value_type(block_header *hdr) Chris@16: { Chris@16: return reinterpret_cast(reinterpret_cast(hdr) - Chris@16: get_rounded_size(size_type(sizeof(intrusive_value_type_impl)), size_type(BlockHdrAlignment))); Chris@16: } Chris@16: Chris@16: CharType *name() const Chris@16: { return get_block_header()->template name(); } Chris@16: Chris@16: unsigned short name_length() const Chris@16: { return get_block_header()->name_length(); } Chris@16: Chris@16: void *value() const Chris@16: { return get_block_header()->value(); } Chris@16: }; Chris@16: Chris@16: template Chris@16: class char_ptr_holder Chris@16: { Chris@16: public: Chris@16: char_ptr_holder(const CharType *name) Chris@16: : m_name(name) Chris@16: {} Chris@16: Chris@16: char_ptr_holder(const anonymous_instance_t *) Chris@16: : m_name(static_cast(0)) Chris@16: {} Chris@16: Chris@16: char_ptr_holder(const unique_instance_t *) Chris@16: : m_name(reinterpret_cast(-1)) Chris@16: {} Chris@16: Chris@16: operator const CharType *() Chris@16: { return m_name; } Chris@16: Chris@101: const CharType *get() const Chris@101: { return m_name; } Chris@101: Chris@101: bool is_unique() const Chris@101: { return m_name == reinterpret_cast(-1); } Chris@101: Chris@101: bool is_anonymous() const Chris@101: { return m_name == static_cast(0); } Chris@101: Chris@16: private: Chris@16: const CharType *m_name; Chris@16: }; Chris@16: Chris@16: //!The key of the the named allocation information index. Stores an offset pointer Chris@16: //!to a null terminated string and the length of the string to speed up sorting Chris@16: template Chris@16: struct index_key Chris@16: { Chris@16: typedef typename boost::intrusive:: Chris@16: pointer_traits::template Chris@16: rebind_pointer::type const_char_ptr_t; Chris@16: typedef CharT char_type; Chris@16: typedef typename boost::intrusive::pointer_traits::difference_type difference_type; Chris@101: typedef typename boost::move_detail::make_unsigned::type size_type; Chris@16: Chris@16: private: Chris@16: //Offset pointer to the object's name Chris@16: const_char_ptr_t mp_str; Chris@16: //Length of the name buffer (null NOT included) Chris@16: size_type m_len; Chris@16: public: Chris@16: Chris@16: //!Constructor of the key Chris@16: index_key (const char_type *nm, size_type length) Chris@16: : mp_str(nm), m_len(length) Chris@16: {} Chris@16: Chris@16: //!Less than function for index ordering Chris@16: bool operator < (const index_key & right) const Chris@16: { Chris@16: return (m_len < right.m_len) || Chris@16: (m_len == right.m_len && Chris@101: std::char_traits::compare Chris@101: (to_raw_pointer(mp_str),to_raw_pointer(right.mp_str), m_len) < 0); Chris@16: } Chris@16: Chris@16: //!Equal to function for index ordering Chris@16: bool operator == (const index_key & right) const Chris@16: { Chris@16: return m_len == right.m_len && Chris@16: std::char_traits::compare Chris@101: (to_raw_pointer(mp_str), to_raw_pointer(right.mp_str), m_len) == 0; Chris@16: } Chris@16: Chris@16: void name(const CharT *nm) Chris@16: { mp_str = nm; } Chris@16: Chris@16: void name_length(size_type len) Chris@16: { m_len = len; } Chris@16: Chris@16: const CharT *name() const Chris@16: { return to_raw_pointer(mp_str); } Chris@16: Chris@16: size_type name_length() const Chris@16: { return m_len; } Chris@16: }; Chris@16: Chris@16: //!The index_data stores a pointer to a buffer and the element count needed Chris@16: //!to know how many destructors must be called when calling destroy Chris@16: template Chris@16: struct index_data Chris@16: { Chris@16: typedef VoidPointer void_pointer; Chris@16: void_pointer m_ptr; Chris@101: explicit index_data(void *ptr) : m_ptr(ptr){} Chris@16: Chris@16: void *value() const Chris@16: { return static_cast(to_raw_pointer(m_ptr)); } Chris@16: }; Chris@16: Chris@16: template Chris@16: struct segment_manager_base_type Chris@16: { typedef segment_manager_base type; }; Chris@16: Chris@16: template Chris@16: struct index_config Chris@16: { Chris@16: typedef typename MemoryAlgorithm::void_pointer void_pointer; Chris@16: typedef CharT char_type; Chris@16: typedef index_key key_type; Chris@16: typedef index_data mapped_type; Chris@16: typedef typename segment_manager_base_type Chris@16: ::type segment_manager_base; Chris@16: Chris@16: template Chris@16: struct intrusive_value_type Chris@16: { typedef intrusive_value_type_impl type; }; Chris@16: Chris@16: typedef intrusive_compare_key intrusive_compare_key_type; Chris@16: }; Chris@16: Chris@16: template Chris@16: class segment_manager_iterator_value_adaptor Chris@16: { Chris@16: typedef typename Iterator::value_type iterator_val_t; Chris@16: typedef typename iterator_val_t::char_type char_type; Chris@16: Chris@16: public: Chris@16: segment_manager_iterator_value_adaptor(const typename Iterator::value_type &val) Chris@16: : m_val(&val) Chris@16: {} Chris@16: Chris@16: const char_type *name() const Chris@16: { return m_val->name(); } Chris@16: Chris@16: unsigned short name_length() const Chris@16: { return m_val->name_length(); } Chris@16: Chris@16: const void *value() const Chris@16: { return m_val->value(); } Chris@16: Chris@16: const typename Iterator::value_type *m_val; Chris@16: }; Chris@16: Chris@16: Chris@16: template Chris@16: class segment_manager_iterator_value_adaptor Chris@16: { Chris@16: typedef typename Iterator::value_type iterator_val_t; Chris@16: typedef typename iterator_val_t::first_type first_type; Chris@16: typedef typename iterator_val_t::second_type second_type; Chris@16: typedef typename first_type::char_type char_type; Chris@16: typedef typename first_type::size_type size_type; Chris@16: Chris@16: public: Chris@16: segment_manager_iterator_value_adaptor(const typename Iterator::value_type &val) Chris@16: : m_val(&val) Chris@16: {} Chris@16: Chris@16: const char_type *name() const Chris@16: { return m_val->first.name(); } Chris@16: Chris@16: size_type name_length() const Chris@16: { return m_val->first.name_length(); } Chris@16: Chris@16: const void *value() const Chris@16: { Chris@16: return reinterpret_cast*> Chris@16: (to_raw_pointer(m_val->second.m_ptr))->value(); Chris@16: } Chris@16: Chris@16: const typename Iterator::value_type *m_val; Chris@16: }; Chris@16: Chris@16: template Chris@16: struct segment_manager_iterator_transform Chris@16: { Chris@16: typedef segment_manager_iterator_value_adaptor result_type; Chris@16: Chris@101: template result_type operator()(const T &arg) const Chris@16: { return result_type(arg); } Chris@16: }; Chris@16: Chris@16: } //namespace ipcdetail { Chris@16: Chris@16: //These pointers are the ones the user will use to Chris@16: //indicate previous allocation types Chris@16: static const ipcdetail::anonymous_instance_t * anonymous_instance = 0; Chris@16: static const ipcdetail::unique_instance_t * unique_instance = 0; Chris@16: Chris@16: namespace ipcdetail_really_deep_namespace { Chris@16: Chris@16: //Otherwise, gcc issues a warning of previously defined Chris@16: //anonymous_instance and unique_instance Chris@16: struct dummy Chris@16: { Chris@16: dummy() Chris@16: { Chris@16: (void)anonymous_instance; Chris@16: (void)unique_instance; Chris@16: } Chris@16: }; Chris@16: Chris@16: } //detail_really_deep_namespace Chris@16: Chris@16: }} //namespace boost { namespace interprocess Chris@16: Chris@16: #include Chris@16: Chris@16: #endif //#ifndef BOOST_INTERPROCESS_SEGMENT_MANAGER_BASE_HPP Chris@16: