Update of /cvsroot/boost/boost/boost/interprocess
In directory sc8-pr-cvs3.sourceforge.net:/tmp/cvs-serv22035
Modified Files:
offset_ptr.hpp segment_manager.hpp shared_memory_object.hpp
windows_shared_memory.hpp
Log Message:
New Interprocess version
Index: offset_ptr.hpp
===================================================================
RCS file: /cvsroot/boost/boost/boost/interprocess/offset_ptr.hpp,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -d -r1.8 -r1.9
--- offset_ptr.hpp 23 Jun 2007 12:53:00 -0000 1.8
+++ offset_ptr.hpp 22 Jul 2007 14:06:03 -0000 1.9
@@ -325,6 +325,7 @@
} //namespace interprocess {
/// @cond
+
//!has_trivial_constructor<> == true_type specialization for optimizations
template <class T>
struct has_trivial_constructor< boost::interprocess::offset_ptr<T> >
Index: segment_manager.hpp
===================================================================
RCS file: /cvsroot/boost/boost/boost/interprocess/segment_manager.hpp,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -d -r1.8 -r1.9
--- segment_manager.hpp 23 Jun 2007 12:53:00 -0000 1.8
+++ segment_manager.hpp 22 Jul 2007 14:06:04 -0000 1.9
@@ -24,7 +24,7 @@
#include <boost/interprocess/detail/iterators.hpp>
#include <boost/interprocess/detail/mpl.hpp>
-#include <boost/interprocess/detail/basic_segment_manager.hpp>
+#include <boost/interprocess/detail/segment_manager_helper.hpp>
#include <boost/interprocess/detail/named_proxy.hpp>
#include <boost/interprocess/detail/utilities.hpp>
#include <boost/interprocess/offset_ptr.hpp>
@@ -46,284 +46,238 @@
namespace boost{
namespace interprocess{
-/// @cond
-
-namespace detail{
-
-//Anti-exception node eraser
-template<class Cont>
-class value_eraser
+//!This object is the public base class of segment manager.
+//!This class only depends on the memory allocation algorithm
+//!and implements all the allocation features not related
+//!to named or unique objects.
+//!
+//!Storing a reference to segment_manager forces
+//!the holder class to be dependent on index types and character types.
+//!When such dependence is not desirable and only anonymous and raw
+//!allocations are needed, segment_manager_base is the correct answer.
+template<class MemoryAlgorithm>
+class segment_manager_base
+ : private MemoryAlgorithm
{
public:
- value_eraser(Cont & cont, typename Cont::iterator it)
- : m_cont(cont), m_index_it(it), m_erase(true){}
- ~value_eraser()
- { if(m_erase) m_cont.erase(m_index_it); }
-
- void release() { m_erase = false; }
-
- private:
- Cont &m_cont;
- typename Cont::iterator m_index_it;
- bool m_erase;
-};
-
-template<class CharT>
-struct intrusive_compare_key
-{
- typedef CharT char_type;
-
- intrusive_compare_key(const CharT *str, std::size_t len)
- : mp_str(str), m_len(len)
- {}
-
- const CharT * mp_str;
- std::size_t m_len;
-};
+ typedef segment_manager_base<MemoryAlgorithm> segment_manager_base_type;
+ typedef typename MemoryAlgorithm::void_pointer void_pointer;
+ typedef typename MemoryAlgorithm::mutex_family mutex_family;
+ typedef MemoryAlgorithm memory_algorithm;
+
+ /// @cond
+
+ //Experimental. Don't use
+ typedef typename MemoryAlgorithm::multiallocation_iterator
multiallocation_iterator;
-//!This struct indicates an anonymous object creation
-//!allocation
-template<instance_type type>
-class instance_t
-{
- instance_t(){}
-};
+ /// @endcond
-template<class T>
-struct char_if_void
-{
- typedef T type;
-};
+ //!This constant indicates the payload size
+ //!associated with each allocation of the memory algorithm
+ static const std::size_t PayloadPerAllocation =
MemoryAlgorithm::PayloadPerAllocation;
-template<>
-struct char_if_void<void>
-{
- typedef char type;
-};
+ //!Constructor of the segment_manager_base
+ //!
+ //!"size" is the size of the memory segment where
+ //!the basic segment manager is being constructed.
+ //!
+ //!"reserved_bytes" is the number of bytes
+ //!after the end of the memory algorithm object itself
+ //!that the memory algorithm will exclude from
+ //!dynamic allocation
+ //!
+ //!Can throw
+ segment_manager_base(std::size_t size, std::size_t reserved_bytes)
+ : MemoryAlgorithm(size, reserved_bytes)
+ {
+ assert((sizeof(segment_manager_base<MemoryAlgorithm>) ==
sizeof(MemoryAlgorithm)));
+ }
-typedef instance_t<anonymous_type> anonymous_instance_t;
-typedef instance_t<unique_type> unique_instance_t;
+ //!Returns the size of the memory
+ //!segment
+ std::size_t get_size() const
+ { return MemoryAlgorithm::get_size(); }
-template<class Hook, class CharType>
-struct intrusive_value_type_impl
- : public Hook
-{
- private:
- //Non-copyable
- intrusive_value_type_impl(const intrusive_value_type_impl &);
- intrusive_value_type_impl& operator=(const intrusive_value_type_impl &);
+ //!Returns the number of free bytes of the memory
+ //!segment
+ std::size_t get_free_memory() const
+ { return MemoryAlgorithm::get_free_memory(); }
- public:
- typedef CharType char_type;
+ //!Obtains the minimum size needed by
+ //!the segment manager
+ static std::size_t get_min_size (std::size_t size)
+ { return MemoryAlgorithm::get_min_size(size); }
- intrusive_value_type_impl(){}
+ //!Allocates nbytes bytes. This function is only used in
+ //!single-segment management. Never throws
+ void * allocate (std::size_t nbytes, std::nothrow_t)
+ { return MemoryAlgorithm::allocate(nbytes); }
- enum { BlockHdrAlignment = detail::alignment_of<block_header>::value };
+ /// @cond
- block_header *get_block_header() const
+ //Experimental. Dont' use.
+ //!Allocates n_elements of
+ //!elem_size bytes. Throws bad_alloc on failure.
+ multiallocation_iterator allocate_many
+ (std::size_t elem_bytes, std::size_t min_elements, std::size_t
preferred_elements, std::size_t &received_elements)
{
- return (block_header *)(detail::char_ptr_cast(this) +
- get_rounded_size(sizeof(*this), BlockHdrAlignment));
+ multiallocation_iterator ret =
MemoryAlgorithm::allocate_many(elem_bytes, min_elements, preferred_elements,
received_elements);
+ if(!ret) throw bad_alloc();
+ return ret;
}
- bool operator <(const intrusive_value_type_impl<Hook, CharType> & other)
const
- { return this->get_block_header()->template
less<CharType>(*other.get_block_header()); }
-
- bool operator ==(const intrusive_value_type_impl<Hook, CharType> & other)
const
- { return this->get_block_header()->template
equal<CharType>(*other.get_block_header()); }
-
- static intrusive_value_type_impl *get_intrusive_value_type(block_header
*hdr)
+ //!Allocates n_elements, each one of
+ //!element_lenghts[i]*sizeof_element bytes. Throws bad_alloc on failure.
+ multiallocation_iterator allocate_many
+ (const std::size_t *element_lenghts, std::size_t n_elements, std::size_t
sizeof_element = 1)
{
- return (intrusive_value_type_impl *)(detail::char_ptr_cast(hdr) -
- get_rounded_size(sizeof(intrusive_value_type_impl),
BlockHdrAlignment));
+ multiallocation_iterator ret =
MemoryAlgorithm::allocate_many(element_lenghts, n_elements, sizeof_element);
+ if(!ret) throw bad_alloc();
+ return ret;
}
- CharType *name() const
- { return get_block_header()->template name<CharType>(); }
-
- std::size_t name_length() const
- { return get_block_header()->name_length(); }
-
- void *value() const
- { return get_block_header()->value(); }
-};
-
-template<class CharType>
-class char_ptr_holder
-{
- public:
- char_ptr_holder(const CharType *name)
- : m_name(name)
- {}
-
- char_ptr_holder(const detail::anonymous_instance_t *)
- : m_name((CharType*)0)
- {}
-
- char_ptr_holder(const detail::unique_instance_t *)
- : m_name((CharType*)-1)
- {}
-
- operator const CharType *()
- { return m_name; }
+ //!Allocates n_elements of
+ //!elem_size bytes. Returns a default constructed iterator on failure.
+ multiallocation_iterator allocate_many(std::size_t elem_size, std::size_t
min_elements, std::size_t preferred_elements, std::size_t &received_elements,
std::nothrow_t)
+ { return MemoryAlgorithm::allocate_many(elem_size, min_elements,
preferred_elements, received_elements); }
- private:
- const CharType *m_name;
-};
+ //!Allocates n_elements, each one of
+ //!element_lenghts[i]*sizeof_element bytes.
+ //!Returns a default constructed iterator on failure.
+ multiallocation_iterator allocate_many(const std::size_t *elem_sizes,
std::size_t n_elements, std::size_t sizeof_element, std::nothrow_t)
+ { return MemoryAlgorithm::allocate_many(elem_sizes, n_elements,
sizeof_element); }
-//!The key of the the named allocation information index. Stores an offset
pointer
-//!to a null terminated string and the length of the string to speed up sorting
-template<class CharT, class VoidPointer>
-struct index_key
-{
- typedef typename detail::
- pointer_to_other<VoidPointer, const CharT>::type const_char_ptr_t;
- typedef CharT char_type;
+ /// @endcond
- private:
- //Offset pointer to the object's name
- const_char_ptr_t mp_str;
- //Length of the name buffer (null NOT included)
- std::size_t m_len;
- public:
+ //!Allocates nbytes bytes. Throws boost::interprocess::bad_alloc
+ //!on failure
+ void * allocate(std::size_t nbytes)
+ {
+ void * ret = MemoryAlgorithm::allocate(nbytes);
+ if(!ret)
+ throw bad_alloc();
+ return ret;
+ }
- //!Constructor of the key
- index_key (const char_type *name, std::size_t length)
- : mp_str(name), m_len(length) {}
+ //!Allocates nbytes bytes. This function is only used in
+ //!single-segment management. Never throws
+ void * allocate_aligned (std::size_t nbytes, std::size_t alignment,
std::nothrow_t)
+ { return MemoryAlgorithm::allocate_aligned(nbytes, alignment); }
- //!Less than function for index ordering
- bool operator < (const index_key & right) const
- {
- return (m_len < right.m_len) ||
- (m_len == right.m_len &&
- std::char_traits<char_type>::compare
- (detail::get_pointer(mp_str)
- ,detail::get_pointer(right.mp_str), m_len) < 0);
+ //!Allocates nbytes bytes. This function is only used in
+ //!single-segment management. Throws bad_alloc when fails
+ void * allocate_aligned(std::size_t nbytes, std::size_t alignment)
+ {
+ void * ret = MemoryAlgorithm::allocate_aligned(nbytes, alignment);
+ if(!ret)
+ throw bad_alloc();
+ return ret;
}
- //!Equal to function for index ordering
- bool operator == (const index_key & right) const
+ template<class T>
+ std::pair<T *, bool>
+ allocation_command (allocation_type command, std::size_t limit_size,
+ std::size_t preferred_size,std::size_t
&received_size,
+ T *reuse_ptr = 0)
{
- return m_len == right.m_len &&
- std::char_traits<char_type>::compare
- (detail::get_pointer(mp_str),
- detail::get_pointer(right.mp_str), m_len) == 0;
+ std::pair<T *, bool> ret = MemoryAlgorithm::allocation_command
+ ( command | nothrow_allocation, limit_size, preferred_size,
received_size
+ , reuse_ptr);
+ if(!(command & nothrow_allocation) && !ret.first)
+ throw bad_alloc();
+ return ret;
}
- void name(const CharT *name)
- { mp_str = name; }
-
- void name_length(std::size_t len)
- { m_len = len; }
-
- const CharT *name() const
- { return detail::get_pointer(mp_str); }
-
- std::size_t name_length() const
- { return m_len; }
-};
-
-//!The index_data stores a pointer to a buffer and the element count needed
-//!to know how many destructors must be called when calling destroy
-template<class VoidPointer>
-struct index_data
-{
- typedef VoidPointer void_ptr;
- void_ptr m_ptr;
- index_data(void *ptr) : m_ptr(ptr){}
-
- void *value() const
- { return (void*)detail::get_pointer(m_ptr); }
-};
+ //!Deallocates the bytes allocated with allocate/allocate_many()
+ //!pointed by addr
+ void deallocate (void *addr)
+ { MemoryAlgorithm::deallocate(addr); }
-template<class MemoryAlgorithm>
-struct basic_segment_manager_type
-{ typedef basic_segment_manager<MemoryAlgorithm> type; };
+ //!Increases managed memory in extra_size bytes more. This only works
+ //!with single-segment management*
+ void grow(std::size_t extra_size)
+ { MemoryAlgorithm::grow(extra_size); }
-template<class CharT, class MemoryAlgorithm>
-struct index_config
-{
- typedef typename MemoryAlgorithm::void_pointer void_pointer;
- typedef CharT char_type;
- typedef detail::index_key<CharT, void_pointer> key_type;
- typedef detail::index_data<void_pointer> mapped_type;
- typedef typename basic_segment_manager_type
- <MemoryAlgorithm>::type basic_segment_manager;
+ //!Returns the result of "all_memory_deallocated()" function
+ //!of the used memory algorithm
+ bool all_memory_deallocated()
+ { return MemoryAlgorithm::all_memory_deallocated(); }
- template<class HeaderBase>
- struct intrusive_value_type
- { typedef detail::intrusive_value_type_impl<HeaderBase, CharT> type; };
+ //!Returns the result of "check_sanity()" function
+ //!of the used memory algorithm
+ bool check_sanity()
+ { return MemoryAlgorithm::check_sanity(); }
- typedef intrusive_compare_key<CharT> intrusive_compare_key_type;
-};
+ //!Writes to zero free memory (memory not yet allocated) of the memory
algorithm
+ void zero_free_memory()
+ { MemoryAlgorithm::zero_free_memory(); }
-template<class Iterator, bool intrusive>
-class iterator_value_adaptor
-{
- typedef typename Iterator::value_type iterator_val_t;
- typedef typename iterator_val_t::char_type char_type;
+ /// @cond
+ protected:
+ void * prot_anonymous_construct
+ (std::size_t num, bool dothrow, detail::in_place_interface &table)
+ {
+ typedef detail::block_header block_header_t;
+ block_header_t block_info ( table.size*num
+ , table.alignment
+ , anonymous_type
+ , 1
+ , 0);
- public:
- iterator_value_adaptor(const typename Iterator::value_type &val)
- : m_val(&val)
- {}
+ //Allocate memory
+ void *ptr_struct = this->allocate(block_info.total_size(),
std::nothrow_t());
- const char_type *name() const
- { return m_val->name(); }
+ //Check if there is enough memory
+ if(!ptr_struct){
+ if(dothrow){
+ throw bad_alloc();
+ }
+ else{
+ return 0;
+ }
+ }
- std::size_t name_length() const
- { return m_val->name_length(); }
+ //Build scoped ptr to avoid leaks with constructor exception
+ detail::mem_algo_deallocator<MemoryAlgorithm> mem(ptr_struct, *this);
- const void *value() const
- { return m_val->value(); }
+ //Now construct the header
+ block_header_t * hdr = new(ptr_struct) block_header_t(block_info);
+ void *ptr = hdr->value();
- const typename Iterator::value_type *m_val;
-};
+ //Now call constructors
+ detail::array_construct(ptr, num, table);
+ //All constructors successful, we don't want erase memory
+ mem.release();
+ return ptr;
+ }
-template<class Iterator>
-class iterator_value_adaptor<Iterator, false>
-{
- typedef typename Iterator::value_type iterator_val_t;
- typedef typename iterator_val_t::first_type first_type;
- typedef typename iterator_val_t::second_type second_type;
- typedef typename first_type::char_type char_type;
+ //!Calls the destructor and makes an anonymous deallocate
+ void prot_anonymous_destroy(const void *object, detail::in_place_interface
&table)
+ {
- public:
- iterator_value_adaptor(const typename Iterator::value_type &val)
- : m_val(&val)
- {}
+ //Get control data from associated with this object
+ typedef detail::block_header block_header_t;
+ block_header_t *ctrl_data =
block_header_t::block_header_from_value(object, table.size, table.alignment);
- const char_type *name() const
- { return m_val->first.name(); }
+ //-------------------------------
+ //boost::interprocess::scoped_lock<rmutex> guard(m_header);
+ //-------------------------------
- std::size_t name_length() const
- { return m_val->first.name_length(); }
+ if(ctrl_data->allocation_type() != anonymous_type){
+ //This is not an anonymous object, the pointer is wrong!
+ assert(0);
+ }
- const void *value() const
- {
- return reinterpret_cast<block_header*>
- (detail::get_pointer(m_val->second.m_ptr))->value();
+ //Call destructors and free memory
+ //Build scoped ptr to avoid leaks with destructor exception
+ std::size_t destroyed = 0;
+ table.destroy_n((void*)object, ctrl_data->m_value_bytes/table.size,
destroyed);
+ this->deallocate(ctrl_data);
}
-
- const typename Iterator::value_type *m_val;
-};
-
-template<class Iterator, bool intrusive>
-struct iterator_transform
- : std::unary_function< typename Iterator::value_type
- , iterator_value_adaptor<Iterator, intrusive> >
-{
- typedef iterator_value_adaptor<Iterator, intrusive> result_type;
-
- result_type operator()(const typename Iterator::value_type &arg) const
- { return result_type(arg); }
+ /// @endcond
};
-} //namespace detail{
-
-/// @endcond
-
//These pointers are the ones the user will use to
//indicate previous allocation types
static const detail::anonymous_instance_t * anonymous_instance = 0;
@@ -340,26 +294,35 @@
//!The second index contains the association for unique instances. The key will
//!be the const char * returned from type_info.name() function for the unique
//!type to be constructed.
+//!
+//!segment_manager<CharType, MemoryAlgorithm, IndexType> inherits publicly
+//!from segment_manager_base<MemoryAlgorithm> and inherits from it
+//!many public functions related to anonymous object and raw memory allocation.
+//!See segment_manager_base reference to know about those functions.
template<class CharType
,class MemoryAlgorithm
,template<class IndexConfig> class IndexType>
class segment_manager
- : private detail::basic_segment_manager<MemoryAlgorithm>
+ : public segment_manager_base<MemoryAlgorithm>
{
/// @cond
//Non-copyable
segment_manager();
segment_manager(const segment_manager &);
segment_manager &operator=(const segment_manager &);
- typedef detail::basic_segment_manager<MemoryAlgorithm> Base;
+ typedef segment_manager_base<MemoryAlgorithm> Base;
typedef detail::block_header block_header_t;
/// @endcond
public:
+ typedef MemoryAlgorithm memory_algorithm;
typedef typename Base::void_pointer void_pointer;
typedef CharType char_type;
+ typedef typename Base::multiallocation_iterator multiallocation_iterator;
- enum { PayloadPerAllocation = Base::PayloadPerAllocation };
+ typedef segment_manager_base<MemoryAlgorithm> segment_manager_base_type;
+
+ static const std::size_t PayloadPerAllocation = Base::PayloadPerAllocation;
/// @cond
private:
@@ -373,11 +336,11 @@
typedef IndexType<index_config_named> named_index_t;
typedef IndexType<index_config_unique> unique_index_t;
typedef detail::char_ptr_holder<CharType> char_ptr_holder_t;
- typedef detail::iterator_transform
+ typedef detail::segment_manager_iterator_transform
<typename named_index_t::const_iterator
,is_intrusive_index<index_type>::value> named_transform;
- typedef detail::iterator_transform
+ typedef detail::segment_manager_iterator_transform
<typename unique_index_t::const_iterator
,is_intrusive_index<index_type>::value> unique_transform;
/// @endcond
@@ -389,28 +352,36 @@
typedef transform_iterator
<typename unique_index_t::const_iterator, unique_transform>
const_unique_iterator;
+ /// @cond
+
//!Constructor proxy object definition helper class
template<class T>
struct construct_proxy
{
- typedef detail::named_proxy<segment_manager, T, true> type;
+ typedef detail::named_proxy<segment_manager, T, false> type;
};
//!Constructor proxy object definition helper class
template<class T>
struct construct_iter_proxy
{
- typedef detail::named_proxy<segment_manager, T, false> type;
+ typedef detail::named_proxy<segment_manager, T, true> type;
};
- //!Constructor. Can throw
+ /// @endcond
+
+ //!Constructor of the segment manager
+ //!"size" is the size of the memory segment where
+ //!the segment manager is being constructed.
+ //!Can throw
segment_manager(std::size_t size)
: Base(size, priv_get_reserved_bytes())
, m_header(static_cast<Base*>(get_this_pointer()))
{ (void) anonymous_instance; (void) unique_instance; }
- //!Tries to find a previous named allocation address. Returns a memory
- //!buffer and the object count.
+ //!Tries to find a previous named allocation. Returns the address
+ //!and the object count. On failure the first member of the
+ //!returned pair is 0.
template <class T>
std::pair<T*, std::size_t> find (const CharType* name)
{
@@ -429,6 +400,9 @@
return std::pair<T*, std::size_t>(static_cast<T*>(ret), size);
}
+ //!Tries to find a previous unique allocation. Returns the address
+ //!and the object count. On failure the first member of the
+ //!returned pair is 0.
template <class T>
std::pair<T*, std::size_t> find (const detail::unique_instance_t* name)
{
@@ -469,7 +443,7 @@
template <class T>
typename construct_iter_proxy<T>::type
construct_it(char_ptr_holder_t name)
- { return construct_iter_proxy<T>::type (this, name, false, true); }
+ { return typename construct_iter_proxy<T>::type (this, name, false, true);
}
//!Returns throwing "search or construct from iterators"
//!proxy object
@@ -499,8 +473,8 @@
void atomic_func(Func &f)
{ boost::interprocess::scoped_lock<rmutex> guard(m_header); f(); }
- //!Calls the destructor and makes an unique
- //!deallocate
+ //!Destroys a previously created unique instance.
+ //!Returns false if the object was not present.
template <class T>
bool destroy(const detail::unique_instance_t *)
{
@@ -509,6 +483,8 @@
(typeid(T).name(), m_header.m_unique_index, dtor, is_intrusive_t());
}
+ //!Destroys the named object with
+ //!the given name. Returns false if that object can't be found.
template <class T>
bool destroy(const CharType *name)
{
@@ -517,41 +493,34 @@
(name, m_header.m_named_index, dtor, is_intrusive_t());
}
+ //!Destroys an anonymous, unique or named object
+ //!using it's address
template <class T>
- bool destroy_ptr(const T *p)
+ void destroy_ptr(const T *p)
{
//If T is void transform it to char
typedef typename detail::char_if_void<T>::type data_t;
detail::placement_destroy<data_t> dtor;
- return priv_destroy_ptr(p, dtor);
+ priv_destroy_ptr(p, dtor);
}
//!Returns the name of an object created with construct/find_or_construct
//!functions. Does not throw
template<class T>
- const CharType *get_name(const T *ptr)
- {
- //Get header
- block_header_t *ctrl_data = block_header_t::block_header_from_value(ptr);
- CharType *name = static_cast<CharType*>(ctrl_data->template
name<CharType>());
-
- //Sanity checks
- assert(ctrl_data->sizeof_char() == sizeof(CharType));
- assert(ctrl_data->m_num_char ==
std::char_traits<CharType>::length(name));
+ static const CharType *get_instance_name(const T *ptr)
+ { return
priv_get_instance_name(block_header_t::block_header_from_value(ptr)); }
- return name;
- }
+ //!Returns the length of an object created with construct/find_or_construct
+ //!functions. Does not throw.
+ template<class T>
+ static std::size_t get_instance_length(const T *ptr)
+ { return
priv_get_instance_length(block_header_t::block_header_from_value(ptr),
sizeof(T)); }
//!Returns is the the name of an object created with
construct/find_or_construct
//!functions. Does not throw
template<class T>
- detail::instance_type get_type(const T *ptr)
- {
- //Get header
- block_header_t *ctrl_data = block_header_t::block_header_from_value(ptr);
- assert((detail::instance_type)ctrl_data->allocation_type() <
detail::max_allocation_type);
- return (detail::instance_type)ctrl_data->allocation_type();
- }
+ static instance_type get_instance_type(const T *ptr)
+ { return
priv_get_instance_type(block_header_t::block_header_from_value(ptr)); }
//!Preallocates needed index resources to optimize the
//!creation of "num" named objects in the managed memory segment.
@@ -575,6 +544,17 @@
m_header.m_unique_index.reserve(num);
}
+ //!Calls shrink_to_fit in both named and unique object indexes
+ //!to try to free unused memory from those indexes.
+ void shrink_to_fit_indexes()
+ {
+ //-------------------------------
+ boost::interprocess::scoped_lock<rmutex> guard(m_header);
+ //-------------------------------
+ m_header.m_named_index.shrink_to_fit();
+ m_header.m_unique_index.shrink_to_fit();
+ }
+
//!Returns the number of named objects stored in
//!the segment.
std::size_t get_num_named_objects()
@@ -595,77 +575,13 @@
return m_header.m_unique_index.size();
}
- //!Returns the size of the memory
- //!segment
- std::size_t get_size() const
- { return Base::get_size(); }
-
- //!Returns the number of free bytes of the memory
- //!segment
- std::size_t get_free_memory() const
- { return Base::get_free_memory(); }
-
//!Obtains the minimum size needed by the
//!segment manager
static std::size_t get_min_size()
{ return Base::get_min_size(priv_get_reserved_bytes()); }
- //!Allocates nbytes bytes. Throws boost::interprocess::bad_alloc
- //!when it can allocate
- void * allocate(std::size_t nbytes)
- { return Base::allocate(nbytes); }
-
- //!Allocates nbytes bytes. This function is only used in
- //!single-segment management. Never throws
- void * allocate (std::size_t nbytes, std::nothrow_t nothrow)
- { return Base::allocate(nbytes, nothrow); }
-
- //!Allocates aligned bytes, returns 0 if there is not more memory.
- //!Alignment must be power of 2
- void* allocate_aligned (std::size_t nbytes, std::size_t alignment)
- { return Base::allocate_aligned(nbytes, alignment); }
-
- //!Allocates aligned bytes, throws bad_alloc when
- //!it can allocate. Alignment must be power of 2
- void* allocate_aligned (std::size_t nbytes, std::size_t alignment,
std::nothrow_t nothrow)
- { return Base::allocate_aligned(nbytes, alignment, nothrow); }
-
- std::pair<void *, bool>
- allocation_command (allocation_type command, std::size_t limit_size,
- std::size_t preferred_size,std::size_t
&received_size,
- void *reuse_ptr = 0, std::size_t backwards_multiple
= 1)
- {
- return Base::allocation_command
- (command, limit_size, preferred_size, received_size, reuse_ptr,
backwards_multiple);
- }
-
- //!Deallocates the bytes allocated with allocate/allocate_at_least()
- //!pointed by addr
- void deallocate (void *addr)
- { Base::deallocate(addr); }
-
- //!Increases managed memory in extra_size bytes more. This only works
- //!with single-segment management
- void grow(std::size_t extra_size)
- { Base::grow(extra_size); }
-
- //!Returns the result of "all_memory_deallocated()" function
- //!of the used memory algorithm
- bool all_memory_deallocated()
- { return Base::all_memory_deallocated(); }
-
- //!Returns the result of "check_sanity()" function
- //!of the used memory algorithm
- bool check_sanity()
- { return Base::check_sanity(); }
-
- //!Writes to zero free memory (memory not yet allocated) of
- //!the memory algorithm
- void zero_free_memory()
- { Base::zero_free_memory(); }
-
//!Returns a constant iterator to the beginning of the information about
- //the named allocations performed in this segment manager
+ //!the named allocations performed in this segment manager
const_named_iterator named_begin() const
{
return make_transform_iterator
@@ -673,7 +589,7 @@
}
//!Returns a constant iterator to the end of the information about
- //the named allocations performed in this segment manager
+ //!the named allocations performed in this segment manager
const_named_iterator named_end() const
{
return make_transform_iterator
@@ -681,7 +597,7 @@
}
//!Returns a constant iterator to the beginning of the information about
- //the unique allocations performed in this segment manager
+ //!the unique allocations performed in this segment manager
const_unique_iterator unique_begin() const
{
return make_transform_iterator
@@ -689,7 +605,7 @@
}
//!Returns a constant iterator to the end of the information about
- //the unique allocations performed in this segment manager
+ //!the unique allocations performed in this segment manager
const_unique_iterator unique_end() const
{
return make_transform_iterator
@@ -732,40 +648,72 @@
}
else if(name == reinterpret_cast<const CharType*>(-1)){
ret = this->priv_generic_named_construct<char>
- (detail::unique_type, table.type_name, num, try2find, dothrow,
table, m_header.m_unique_index, is_intrusive_t());
+ (unique_type, table.type_name, num, try2find, dothrow, table,
m_header.m_unique_index, is_intrusive_t());
}
else{
ret = this->priv_generic_named_construct<CharType>
- (detail::named_type, name, num, try2find, dothrow, table,
m_header.m_named_index, is_intrusive_t());
+ (named_type, name, num, try2find, dothrow, table,
m_header.m_named_index, is_intrusive_t());
}
return ret;
}
- bool priv_destroy_ptr(const void *ptr, detail::in_place_interface &dtor)
+ void priv_destroy_ptr(const void *ptr, detail::in_place_interface &dtor)
{
block_header_t *ctrl_data = block_header_t::block_header_from_value(ptr,
dtor.size, dtor.alignment);
switch(ctrl_data->allocation_type()){
- case detail::anonymous_type:
- return this->prot_anonymous_destroy(ptr, dtor);
+ case anonymous_type:
+ this->prot_anonymous_destroy(ptr, dtor);
break;
- case detail::named_type:
- return this->priv_generic_named_destroy<CharType>
+ case named_type:
+ this->priv_generic_named_destroy<CharType>
(ctrl_data, m_header.m_named_index, dtor, is_node_index_t());
break;
- case detail::unique_type:
- return this->priv_generic_named_destroy<char>
+ case unique_type:
+ this->priv_generic_named_destroy<char>
(ctrl_data, m_header.m_unique_index, dtor, is_node_index_t());
break;
default:
//This type is unknown, bad pointer passed to this function!
assert(0);
- return false;
break;
}
- return false;
+ }
+
+ //!Returns the name of an object created with construct/find_or_construct
+ //!functions. Does not throw
+ static const CharType *priv_get_instance_name(block_header_t *ctrl_data)
+ {
+ allocation_type type = ctrl_data->allocation_type();
+ if(type != named_type){
+ assert((type == anonymous_type && ctrl_data->m_num_char == 0) ||
+ (type == unique_type && ctrl_data->m_num_char != 0) );
+ return 0;
+ }
+ CharType *name = static_cast<CharType*>(ctrl_data->template
name<CharType>());
+
+ //Sanity checks
+ assert(ctrl_data->sizeof_char() == sizeof(CharType));
+ assert(ctrl_data->m_num_char ==
std::char_traits<CharType>::length(name));
+ return name;
+ }
+
+ static std::size_t priv_get_instance_length(block_header_t *ctrl_data,
std::size_t sizeofvalue)
+ {
+ //Get header
+ assert((ctrl_data->value_bytes() %sizeofvalue) == 0);
+ return ctrl_data->value_bytes()/sizeofvalue;
+ }
+
+ //!Returns is the the name of an object created with
construct/find_or_construct
+ //!functions. Does not throw
+ static instance_type priv_get_instance_type(block_header_t *ctrl_data)
+ {
+ //Get header
+ assert((instance_type)ctrl_data->allocation_type() <
max_allocation_type);
+ return (instance_type)ctrl_data->allocation_type();
}
static std::size_t priv_get_reserved_bytes()
@@ -1113,8 +1061,8 @@
//Avoid constructions if constructor is trivial
//Build scoped ptr to avoid leaks with constructor exception
- detail::mem_algo_deallocator<MemoryAlgorithm> mem
- (buffer_ptr, this->memory_algorithm());
+ detail::mem_algo_deallocator<segment_manager_base_type> mem
+ (buffer_ptr, *static_cast<segment_manager_base_type*>(this));
//Construct array, this can throw
detail::array_construct(ptr, num, table);
@@ -1241,8 +1189,8 @@
it->second.m_ptr = hdr;
//Build scoped ptr to avoid leaks with constructor exception
- detail::mem_algo_deallocator<MemoryAlgorithm> mem
- (buffer_ptr, this->memory_algorithm());
+ detail::mem_algo_deallocator<segment_manager_base_type> mem
+ (buffer_ptr, *static_cast<segment_manager_base_type*>(this));
//Construct array, this can throw
detail::array_construct(ptr, num, table);
Index: shared_memory_object.hpp
===================================================================
RCS file: /cvsroot/boost/boost/boost/interprocess/shared_memory_object.hpp,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- shared_memory_object.hpp 23 Jun 2007 12:53:00 -0000 1.5
+++ shared_memory_object.hpp 22 Jul 2007 14:06:04 -0000 1.6
@@ -13,9 +13,8 @@
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
-#include <boost/interprocess/detail/creation_tags.hpp>
+#include <boost/interprocess/creation_tags.hpp>
#include <boost/interprocess/exceptions.hpp>
-//#include <boost/interprocess/detail/utilities.hpp>
#include <boost/interprocess/detail/move.hpp>
#include <boost/interprocess/interprocess_fwd.hpp>
#include <boost/interprocess/exceptions.hpp>
@@ -34,15 +33,14 @@
# include<boost/interprocess/detail/os_file_functions.hpp>
#endif
-/*!\file
- Describes a shared memory object management class.
-*/
+//!\file
+//!Describes a shared memory object management class.
namespace boost {
namespace interprocess {
-/*!A class that wraps a shared memory mapping that can be used to
- create mapped regions from the mapped files*/
+//!A class that wraps a shared memory mapping that can be used to
+//!create mapped regions from the mapped files
class shared_memory_object
{
/// @cond
@@ -58,19 +56,19 @@
//!Creates a shared memory object with name "name" and mode "mode", with
the access mode "mode"
//!If the file previously exists, throws an error.*/
- shared_memory_object(detail::create_only_t, const char *name, mode_t mode)
- { this->priv_open_or_create(DoCreate, name, mode); }
+ shared_memory_object(create_only_t, const char *name, mode_t mode)
+ { this->priv_open_or_create(detail::DoCreate, name, mode); }
//!Tries to create a shared memory object with name "name" and mode "mode",
with the
//!access mode "mode". If the file previously exists, it tries to open it
with mode "mode".
//!Otherwise throws an error.
- shared_memory_object(detail::open_or_create_t, const char *name, mode_t
mode)
- { this->priv_open_or_create(DoCreateOrOpen, name, mode); }
+ shared_memory_object(open_or_create_t, const char *name, mode_t mode)
+ { this->priv_open_or_create(detail::DoCreateOrOpen, name, mode); }
//!Tries to open a shared memory object with name "name", with the access
mode "mode".
//!If the file does not previously exist, it throws an error.
- shared_memory_object(detail::open_only_t, const char *name, mode_t mode)
- { this->priv_open_or_create(DoOpen, name, mode); }
+ shared_memory_object(open_only_t, const char *name, mode_t mode)
+ { this->priv_open_or_create(detail::DoOpen, name, mode); }
//!Moves the ownership of "moved"'s shared memory object to *this.
//!After the call, "moved" does not represent any shared memory object.
@@ -134,7 +132,7 @@
void priv_close();
//!Closes a previously opened file mapping. Never throws.
- bool priv_open_or_create(create_enum_t type, const char *filename, mode_t
mode);
+ bool priv_open_or_create(detail::create_enum_t type, const char *filename,
mode_t mode);
file_handle_t m_handle;
mode_t m_mode;
@@ -169,7 +167,7 @@
#if !defined(BOOST_INTERPROCESS_POSIX_SHARED_MEMORY_OBJECTS)
inline bool shared_memory_object::priv_open_or_create
- (create_enum_t type, const char *filename, mode_t mode)
+ (detail::create_enum_t type, const char *filename, mode_t mode)
{
m_filename = filename;
@@ -203,13 +201,13 @@
}
switch(type){
- case DoOpen:
+ case detail::DoOpen:
m_handle = detail::open_existing_file(shmfile.c_str(), mode, true);
break;
- case DoCreate:
+ case detail::DoCreate:
m_handle = detail::create_new_file(shmfile.c_str(), mode, true);
break;
- case DoCreateOrOpen:
+ case detail::DoCreateOrOpen:
m_handle = detail::create_or_open_file(shmfile.c_str(), mode, true);
break;
default:
@@ -272,7 +270,7 @@
#else //!defined(BOOST_INTERPROCESS_POSIX_SHARED_MEMORY_OBJECTS)
inline bool shared_memory_object::priv_open_or_create
- (create_enum_t type,
+ (detail::create_enum_t type,
const char *filename,
mode_t mode)
{
@@ -298,13 +296,13 @@
}
switch(type){
- case DoOpen:
+ case detail::DoOpen:
//No addition
break;
- case DoCreate:
+ case detail::DoCreate:
oflag |= (O_CREAT | O_EXCL);
break;
- case DoCreateOrOpen:
+ case detail::DoCreateOrOpen:
oflag |= O_CREAT;
break;
default:
Index: windows_shared_memory.hpp
===================================================================
RCS file: /cvsroot/boost/boost/boost/interprocess/windows_shared_memory.hpp,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- windows_shared_memory.hpp 23 Jun 2007 12:53:54 -0000 1.4
+++ windows_shared_memory.hpp 22 Jul 2007 14:06:04 -0000 1.5
@@ -15,9 +15,11 @@
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/detail/workaround.hpp>
-#if (defined BOOST_WINDOWS) && !(defined BOOST_DISABLE_WIN32)
+#if !defined(BOOST_WINDOWS) || defined(BOOST_DISABLE_WIN32)
+#error "This header can only be used in Windows operating systems"
+#endif
-#include <boost/interprocess/detail/creation_tags.hpp>
+#include <boost/interprocess/creation_tags.hpp>
#include <boost/interprocess/exceptions.hpp>
#include <boost/interprocess/detail/utilities.hpp>
#include <boost/interprocess/detail/os_file_functions.hpp>
@@ -28,24 +30,23 @@
#include <boost/cstdint.hpp>
#include <string>
-/*!\file
- Describes a class representing a native windows shared memory.
-*/
+//!\file
+//!Describes a class representing a native windows shared memory.
namespace boost {
namespace interprocess {
-/*!A class that wraps the native Windows shared memory
- that is implemented as a file mapping of the paging file.
- Unlike shared_memory_object, windows_shared_memory has
- no kernel persistence and the shared memory is destroyed
- when all processes destroy all their windows_shared_memory
- objects and mapped regions for the same shared memory
- or the processes end/crash.
-
- Warning: Windows native shared memory and interprocess portable
- shared memory can't communicate between them.
- */
+//!A class that wraps the native Windows shared memory
+//!that is implemented as a file mapping of the paging file.
+//!Unlike shared_memory_object, windows_shared_memory has
+//!no kernel persistence and the shared memory is destroyed
+//!when all processes destroy all their windows_shared_memory
+//!objects and mapped regions for the same shared memory
+//!or the processes end/crash.
+//!
+//!Warning: Windows native shared memory and interprocess portable
+//!shared memory (boost::interprocess::shared_memory_object)
+//!can't communicate between them.
class windows_shared_memory
{
/// @cond
@@ -61,19 +62,19 @@
//!Creates a new native shared memory with name "name" and mode "mode",
//!with the access mode "mode".
//!If the file previously exists, throws an error.
- windows_shared_memory(detail::create_only_t, const char *name, mode_t mode,
std::size_t size)
- { this->priv_open_or_create(DoCreate, name, mode, size); }
+ windows_shared_memory(create_only_t, const char *name, mode_t mode,
std::size_t size)
+ { this->priv_open_or_create(detail::DoCreate, name, mode, size); }
//!Tries to create a shared memory object with name "name" and mode "mode",
with the
//!access mode "mode". If the file previously exists, it tries to open it
with mode "mode".
//!Otherwise throws an error.
- windows_shared_memory(detail::open_or_create_t, const char *name, mode_t
mode, std::size_t size)
- { this->priv_open_or_create(DoCreateOrOpen, name, mode, size); }
+ windows_shared_memory(open_or_create_t, const char *name, mode_t mode,
std::size_t size)
+ { this->priv_open_or_create(detail::DoCreateOrOpen, name, mode, size); }
//!Tries to open a shared memory object with name "name", with the access
mode "mode".
//!If the file does not previously exist, it throws an error.
- windows_shared_memory(detail::open_only_t, const char *name, mode_t mode)
- { this->priv_open_or_create(DoOpen, name, mode, 0); }
+ windows_shared_memory(open_only_t, const char *name, mode_t mode)
+ { this->priv_open_or_create(detail::DoOpen, name, mode, 0); }
//!Moves the ownership of "moved"'s shared memory object to *this.
//!After the call, "moved" does not represent any shared memory object.
@@ -132,7 +133,7 @@
void priv_close();
//!Closes a previously opened file mapping. Never throws.
- bool priv_open_or_create(create_enum_t type, const char *filename, mode_t
mode, std::size_t size);
+ bool priv_open_or_create(detail::create_enum_t type, const char *filename,
mode_t mode, std::size_t size);
void * m_handle;
mode_t m_mode;
@@ -164,7 +165,7 @@
{ return m_mode; }
inline bool windows_shared_memory::priv_open_or_create
- (create_enum_t type, const char *filename, mode_t mode, std::size_t size)
+ (detail::create_enum_t type, const char *filename, mode_t mode, std::size_t
size)
{
m_name = filename;
@@ -194,12 +195,12 @@
}
switch(type){
- case DoOpen:
+ case detail::DoOpen:
m_handle = winapi::open_file_mapping
(map_access, filename);
break;
- case DoCreate:
- case DoCreateOrOpen:
+ case detail::DoCreate:
+ case detail::DoCreateOrOpen:
{
__int64 s = size;
unsigned long high_size(s >> 32), low_size((boost::uint32_t)s);
@@ -214,7 +215,7 @@
}
}
- if(!m_handle || (type == DoCreate && winapi::get_last_error() ==
winapi::error_already_exists)){
+ if(!m_handle || (type == detail::DoCreate && winapi::get_last_error() ==
winapi::error_already_exists)){
error_info err = system_error_code();
this->priv_close();
throw interprocess_exception(err);
@@ -235,10 +236,6 @@
} //namespace interprocess {
} //namespace boost {
-#else
-#error "This header can only be used in Windows operating systems"
-#endif
-
#include <boost/interprocess/detail/config_end.hpp>
#endif //BOOST_INTERPROCESS_WINDOWS_SHARED_MEMORY_HPP
-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems? Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >> http://get.splunk.com/
_______________________________________________
Boost-cvs mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/boost-cvs