1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
|
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2006-2012. 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/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;
//<-
(void)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;
}
//]
|