blob: da39c14fe0561588e1e83094aa22b546cb36e39f [file] [log] [blame]
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2006-2009. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/interprocess for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
//[doc_intrusive
#include <boost/interprocess/managed_shared_memory.hpp>
#include <boost/interprocess/smart_ptr/intrusive_ptr.hpp>
//<-
#include "../test/get_process_id_name.hpp"
//->
using namespace boost::interprocess;
namespace N {
//A class that has an internal reference count
class reference_counted_class
{
private:
//Non-copyable
reference_counted_class(const reference_counted_class &);
//Non-assignable
reference_counted_class & operator=(const reference_counted_class &);
//A typedef to save typing
typedef managed_shared_memory::segment_manager segment_manager;
//This is the reference count
unsigned int m_use_count;
//The segment manager allows deletion from shared memory segment
offset_ptr<segment_manager> mp_segment_manager;
public:
//Constructor
reference_counted_class(segment_manager *s_mngr)
: m_use_count(0), mp_segment_manager(s_mngr){}
//Destructor
~reference_counted_class(){}
public:
//Returns the reference count
unsigned int use_count() const
{ return m_use_count; }
//Adds a reference
inline friend void intrusive_ptr_add_ref(reference_counted_class * p)
{ ++p->m_use_count; }
//Releases a reference
inline friend void intrusive_ptr_release(reference_counted_class * p)
{ if(--p->m_use_count == 0) p->mp_segment_manager->destroy_ptr(p); }
};
} //namespace N {
//A class that has an intrusive pointer to reference_counted_class
class intrusive_ptr_owner
{
typedef intrusive_ptr<N::reference_counted_class,
offset_ptr<void> > intrusive_ptr_t;
intrusive_ptr_t m_intrusive_ptr;
public:
//Takes a pointer to the reference counted class
intrusive_ptr_owner(N::reference_counted_class *ptr)
: m_intrusive_ptr(ptr){}
};
int main()
{
//Remove shared memory on construction and destruction
struct shm_remove
{
//<-
#if 1
shm_remove() { shared_memory_object::remove(test::get_process_id_name()); }
~shm_remove(){ shared_memory_object::remove(test::get_process_id_name()); }
#else
//->
shm_remove() { shared_memory_object::remove("MySharedMemory"); }
~shm_remove(){ shared_memory_object::remove("MySharedMemory"); }
//<-
#endif
//->
} remover;
//Create shared memory
//<-
#if 1
managed_shared_memory shmem(create_only, test::get_process_id_name(), 10000);
#else
//->
managed_shared_memory shmem(create_only, "MySharedMemory", 10000);
//<-
#endif
//->
//Create the unique reference counted object in shared memory
N::reference_counted_class *ref_counted =
shmem.construct<N::reference_counted_class>
("ref_counted")(shmem.get_segment_manager());
//Create an array of ten intrusive pointer owners in shared memory
intrusive_ptr_owner *intrusive_owner_array =
shmem.construct<intrusive_ptr_owner>
(anonymous_instance)[10](ref_counted);
//Now test that reference count is ten
if(ref_counted->use_count() != 10)
return 1;
//Now destroy the array of intrusive pointer owners
//This should destroy every intrusive_ptr and because of
//that reference_counted_class will be destroyed
shmem.destroy_ptr(intrusive_owner_array);
//Now the reference counted object should have been destroyed
if(shmem.find<intrusive_ptr_owner>("ref_counted").first)
return 1;
//Success!
return 0;
}
//]
#include <boost/interprocess/detail/config_end.hpp>