1 //////////////////////////////////////////////////////////////////////////////
2 //
3 // (C) Copyright Ion Gaztanaga 2006-2012.
4 // Distributed under the Boost Software License, Version 1.0.
5 // (See accompanying file LICENSE_1_0.txt or copy at
6 // http://www.boost.org/LICENSE_1_0.txt)
7 //
8 // See http://www.boost.org/libs/interprocess for documentation.
9 //
10 //////////////////////////////////////////////////////////////////////////////
11 #include <boost/interprocess/detail/config_begin.hpp>
12 #include <boost/interprocess/detail/workaround.hpp>
13 
14 //[doc_shared_ptr
15 #include <boost/interprocess/managed_mapped_file.hpp>
16 #include <boost/interprocess/smart_ptr/shared_ptr.hpp>
17 #include <boost/interprocess/smart_ptr/weak_ptr.hpp>
18 #include <cassert>
19 //<-
20 #include "../test/get_process_id_name.hpp"
21 //->
22 
23 using namespace boost::interprocess;
24 
25 //This is type of the object we want to share
26 struct type_to_share
27 {};
28 
29 //This is the type of a shared pointer to the previous type
30 //that will be built in the mapped file
31 typedef managed_shared_ptr<type_to_share, managed_mapped_file>::type shared_ptr_type;
32 typedef managed_weak_ptr<type_to_share, managed_mapped_file>::type   weak_ptr_type;
33 
34 //This is a type holding a shared pointer
35 struct shared_ptr_owner
36 {
shared_ptr_ownershared_ptr_owner37    shared_ptr_owner(const shared_ptr_type &other_shared_ptr)
38       : shared_ptr_(other_shared_ptr)
39    {}
40 
shared_ptr_ownershared_ptr_owner41    shared_ptr_owner(const shared_ptr_owner &other_owner)
42       : shared_ptr_(other_owner.shared_ptr_)
43    {}
44 
45    shared_ptr_type shared_ptr_;
46    //...
47 };
48 
main()49 int main ()
50 {
51    //Define file names
52    //<-
53    #if 1
54    std::string mapped_file(boost::interprocess::ipcdetail::get_temporary_path());
55    mapped_file += "/"; mapped_file += test::get_process_id_name();
56    const char *MappedFile = mapped_file.c_str();
57    #else
58    //->
59    const char *MappedFile  = "MyMappedFile";
60    //<-
61    #endif
62    //->
63 
64    //Destroy any previous file with the name to be used.
65    struct file_remove
66    {
67       file_remove(const char *MappedFile)
68          : MappedFile_(MappedFile) { file_mapping::remove(MappedFile_); }
69       ~file_remove(){ file_mapping::remove(MappedFile_); }
70       const char *MappedFile_;
71    } remover(MappedFile);
72    {
73       managed_mapped_file file(create_only, MappedFile, 65536);
74 
75       //Construct the shared type in the file and
76       //pass ownership to this local shared pointer
77       shared_ptr_type local_shared_ptr = make_managed_shared_ptr
78          (file.construct<type_to_share>("object to share")(), file);
79       assert(local_shared_ptr.use_count() == 1);
80 
81       //Share ownership of the object between local_shared_ptr and a new "owner1"
82       shared_ptr_owner *owner1 =
83          file.construct<shared_ptr_owner>("owner1")(local_shared_ptr);
84       assert(local_shared_ptr.use_count() == 2);
85 
86       //local_shared_ptr releases object ownership
87       local_shared_ptr.reset();
88       assert(local_shared_ptr.use_count() == 0);
89       assert(owner1->shared_ptr_.use_count() == 1);
90 
91       //Share ownership of the object between "owner1" and a new "owner2"
92       shared_ptr_owner *owner2 =
93          file.construct<shared_ptr_owner>("owner2")(*owner1);
94       assert(owner1->shared_ptr_.use_count() == 2);
95       assert(owner2->shared_ptr_.use_count() == 2);
96       assert(owner1->shared_ptr_.get() == owner2->shared_ptr_.get());
97       //<-
98       (void)owner2;
99       //->
100       //The mapped file is unmapped here. Objects have been flushed to disk
101    }
102    {
103       //Reopen the mapped file and find again all owners
104       managed_mapped_file file(open_only, MappedFile);
105 
106       shared_ptr_owner *owner1 = file.find<shared_ptr_owner>("owner1").first;
107       shared_ptr_owner *owner2 = file.find<shared_ptr_owner>("owner2").first;
108       assert(owner1 && owner2);
109 
110       //Check everything is as expected
111       assert(file.find<type_to_share>("object to share").first != 0);
112       assert(owner1->shared_ptr_.use_count() == 2);
113       assert(owner2->shared_ptr_.use_count() == 2);
114       assert(owner1->shared_ptr_.get() == owner2->shared_ptr_.get());
115 
116       //Now destroy one of the owners, the reference count drops.
117       file.destroy_ptr(owner1);
118       assert(owner2->shared_ptr_.use_count() == 1);
119 
120       //Create a weak pointer
121       weak_ptr_type local_observer1(owner2->shared_ptr_);
122       assert(local_observer1.use_count() == owner2->shared_ptr_.use_count());
123 
124       {  //Create a local shared pointer from the weak pointer
125       shared_ptr_type local_shared_ptr = local_observer1.lock();
126       assert(local_observer1.use_count() == owner2->shared_ptr_.use_count());
127       assert(local_observer1.use_count() == 2);
128       }
129 
130       //Now destroy the remaining owner. "object to share" will be destroyed
131       file.destroy_ptr(owner2);
132       assert(file.find<type_to_share>("object to share").first == 0);
133 
134       //Test observer
135       assert(local_observer1.expired());
136       assert(local_observer1.use_count() == 0);
137 
138       //The reference count will be deallocated when all weak pointers
139       //disappear. After that, the file is unmapped.
140    }
141    return 0;
142 }
143 //]
144 #include <boost/interprocess/detail/config_end.hpp>
145