1 | ////////////////////////////////////////////////////////////////////////////// |
2 | // |
3 | // (C) Copyright Ion Gaztanaga 2004-2012. Distributed under the Boost |
4 | // Software License, Version 1.0. (See accompanying file |
5 | // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |
6 | // |
7 | // See http://www.boost.org/libs/interprocess for documentation. |
8 | // |
9 | ////////////////////////////////////////////////////////////////////////////// |
10 | |
11 | #include <boost/interprocess/allocators/allocator.hpp> |
12 | #include <boost/interprocess/containers/vector.hpp> |
13 | #include <boost/interprocess/managed_shared_memory.hpp> |
14 | #include <cstdio> |
15 | #include <string> |
16 | #include "get_process_id_name.hpp" |
17 | |
18 | using namespace boost::interprocess; |
19 | |
20 | template <class CharT> |
21 | struct filename_traits; |
22 | |
23 | template <> |
24 | struct filename_traits<char> |
25 | { |
26 | |
27 | static const char* get() |
28 | { return test::get_process_id_name(); } |
29 | |
30 | static std::string filename; |
31 | }; |
32 | |
33 | #ifdef BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES |
34 | |
35 | template <> |
36 | struct filename_traits<wchar_t> |
37 | { |
38 | |
39 | static const wchar_t* get() |
40 | { return test::get_process_id_wname(); } |
41 | |
42 | static std::wstring filename; |
43 | }; |
44 | |
45 | #endif //#ifdef BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES |
46 | |
47 | |
48 | template<class CharT> |
49 | int test_managed_shared_memory() |
50 | { |
51 | const int ShmemSize = 65536; |
52 | const CharT *const ShmemName = filename_traits<CharT>::get(); |
53 | |
54 | //STL compatible allocator object for memory-mapped shmem |
55 | typedef allocator<int, managed_shared_memory::segment_manager> |
56 | allocator_int_t; |
57 | //A vector that uses that allocator |
58 | typedef boost::interprocess::vector<int, allocator_int_t> MyVect; |
59 | |
60 | { |
61 | //Remove the shmem it is already created |
62 | shared_memory_object::remove(filename: ShmemName); |
63 | |
64 | const int max = 100; |
65 | void *array[std::size_t(max)]; |
66 | //Named allocate capable shared memory allocator |
67 | managed_shared_memory shmem(create_only, ShmemName, ShmemSize); |
68 | |
69 | std::size_t i; |
70 | //Let's allocate some memory |
71 | for(i = 0; i < max; ++i){ |
72 | array[std::ptrdiff_t(i)] = shmem.allocate(nbytes: i+1u); |
73 | } |
74 | |
75 | //Deallocate allocated memory |
76 | for(i = 0; i < max; ++i){ |
77 | shmem.deallocate(addr: array[std::ptrdiff_t(i)]); |
78 | } |
79 | } |
80 | |
81 | { |
82 | //Remove the shmem it is already created |
83 | shared_memory_object::remove(filename: ShmemName); |
84 | |
85 | //Named allocate capable memory mapped shmem managed memory class |
86 | managed_shared_memory tmp(create_only, ShmemName, ShmemSize); |
87 | } |
88 | { |
89 | //Remove the shmem it is already created |
90 | shared_memory_object::remove(filename: ShmemName); |
91 | |
92 | //Now re-create it with create or open |
93 | managed_shared_memory shmem(open_or_create, ShmemName, ShmemSize); |
94 | |
95 | //Construct the STL-like allocator with the segment manager |
96 | const allocator_int_t myallocator (shmem.get_segment_manager()); |
97 | |
98 | //Construct vector |
99 | MyVect *shmem_vect = shmem.construct<MyVect> (name: "MyVector" ) (myallocator); |
100 | |
101 | //Test that vector can be found via name |
102 | if(shmem_vect != shmem.find<MyVect>(name: "MyVector" ).first) |
103 | return -1; |
104 | |
105 | //Destroy and check it is not present |
106 | shmem.destroy<MyVect> (name: "MyVector" ); |
107 | if(0 != shmem.find<MyVect>(name: "MyVector" ).first) |
108 | return -1; |
109 | |
110 | //Construct a vector in the memory-mapped shmem |
111 | shmem_vect = shmem.construct<MyVect> (name: "MyVector" ) (myallocator); |
112 | } |
113 | { |
114 | //Map preexisting shmem again in memory |
115 | managed_shared_memory shmem(open_only, ShmemName); |
116 | |
117 | //Check vector is still there |
118 | MyVect *shmem_vect = shmem.find<MyVect>(name: "MyVector" ).first; |
119 | if(!shmem_vect) |
120 | return -1; |
121 | } |
122 | { |
123 | { |
124 | //Map preexisting shmem again in copy-on-write |
125 | managed_shared_memory shmem(open_copy_on_write, ShmemName); |
126 | |
127 | //Check vector is still there |
128 | MyVect *shmem_vect = shmem.find<MyVect>(name: "MyVector" ).first; |
129 | if(!shmem_vect) |
130 | return -1; |
131 | |
132 | //Erase vector |
133 | shmem.destroy_ptr(ptr: shmem_vect); |
134 | |
135 | //Make sure vector is erased |
136 | shmem_vect = shmem.find<MyVect>(name: "MyVector" ).first; |
137 | if(shmem_vect) |
138 | return -1; |
139 | } |
140 | //Now check vector is still in the shmem |
141 | { |
142 | //Map preexisting shmem again in copy-on-write |
143 | managed_shared_memory shmem(open_copy_on_write, ShmemName); |
144 | |
145 | //Check vector is still there |
146 | MyVect *shmem_vect = shmem.find<MyVect>(name: "MyVector" ).first; |
147 | if(!shmem_vect) |
148 | return -1; |
149 | } |
150 | { |
151 | //Map preexisting shmem again in memory |
152 | managed_shared_memory shmem(open_or_create, ShmemName, ShmemSize); |
153 | |
154 | //Check vector is still there |
155 | MyVect *shmem_vect = shmem.find<MyVect>(name: "MyVector" ).first; |
156 | if(!shmem_vect) |
157 | return -1; |
158 | } |
159 | } |
160 | { |
161 | //Map preexisting shmem again in read-only |
162 | managed_shared_memory shmem(open_read_only, ShmemName); |
163 | |
164 | //Check vector is still there |
165 | MyVect *shmem_vect = shmem.find<MyVect>(name: "MyVector" ).first; |
166 | if(!shmem_vect) |
167 | return -1; |
168 | } |
169 | #ifndef BOOST_INTERPROCESS_POSIX_SHARED_MEMORY_OBJECTS_NO_GROW |
170 | { |
171 | managed_shared_memory::size_type old_free_memory; |
172 | { |
173 | //Map preexisting shmem again in memory |
174 | managed_shared_memory shmem(open_only, ShmemName); |
175 | old_free_memory = shmem.get_free_memory(); |
176 | } |
177 | |
178 | //Now grow the shmem |
179 | managed_shared_memory::grow(shmname: ShmemName, extra_bytes: ShmemSize); |
180 | |
181 | //Map preexisting shmem again in memory |
182 | managed_shared_memory shmem(open_only, ShmemName); |
183 | |
184 | //Check vector is still there |
185 | MyVect *shmem_vect = shmem.find<MyVect>(name: "MyVector" ).first; |
186 | if(!shmem_vect) |
187 | return -1; |
188 | |
189 | if(shmem.get_size() != (ShmemSize*2)) |
190 | return -1; |
191 | if(shmem.get_free_memory() <= old_free_memory) |
192 | return -1; |
193 | } |
194 | { |
195 | managed_shared_memory::size_type old_free_memory, next_free_memory, |
196 | old_shmem_size, next_shmem_size, final_shmem_size; |
197 | { |
198 | //Map preexisting shmem again in memory |
199 | managed_shared_memory shmem(open_only, ShmemName); |
200 | old_free_memory = shmem.get_free_memory(); |
201 | old_shmem_size = shmem.get_size(); |
202 | } |
203 | |
204 | //Now shrink the shmem |
205 | managed_shared_memory::shrink_to_fit(shmname: ShmemName); |
206 | |
207 | { |
208 | //Map preexisting shmem again in memory |
209 | managed_shared_memory shmem(open_only, ShmemName); |
210 | next_shmem_size = shmem.get_size(); |
211 | |
212 | //Check vector is still there |
213 | MyVect *shmem_vect = shmem.find<MyVect>(name: "MyVector" ).first; |
214 | if(!shmem_vect) |
215 | return -1; |
216 | |
217 | next_free_memory = shmem.get_free_memory(); |
218 | if(next_free_memory >= old_free_memory) |
219 | return -1; |
220 | if(old_shmem_size <= next_shmem_size) |
221 | return -1; |
222 | } |
223 | |
224 | //Now destroy the vector |
225 | { |
226 | //Map preexisting shmem again in memory |
227 | managed_shared_memory shmem(open_only, ShmemName); |
228 | |
229 | //Destroy and check it is not present |
230 | shmem.destroy<MyVect>(name: "MyVector" ); |
231 | if(0 != shmem.find<MyVect>(name: "MyVector" ).first) |
232 | return -1; |
233 | } |
234 | |
235 | //Now shrink the shmem |
236 | managed_shared_memory::shrink_to_fit(shmname: ShmemName); |
237 | { |
238 | //Map preexisting shmem again in memory |
239 | managed_shared_memory shmem(open_only, ShmemName); |
240 | final_shmem_size = shmem.get_size(); |
241 | if(next_shmem_size <= final_shmem_size) |
242 | return -1; |
243 | } |
244 | } |
245 | #endif //ifndef BOOST_INTERPROCESS_POSIX_SHARED_MEMORY_OBJECTS_NO_GROW |
246 | |
247 | { |
248 | //Now test move semantics |
249 | managed_shared_memory original(open_only, ShmemName); |
250 | managed_shared_memory move_ctor(boost::move(t&: original)); |
251 | managed_shared_memory move_assign; |
252 | move_assign = boost::move(t&: move_ctor); |
253 | move_assign.swap(other&: original); |
254 | } |
255 | |
256 | shared_memory_object::remove(filename: ShmemName); |
257 | return 0; |
258 | } |
259 | |
260 | int main () |
261 | { |
262 | int r; |
263 | r = test_managed_shared_memory<char>(); |
264 | if(r) return r; |
265 | #ifdef BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES |
266 | r = test_managed_shared_memory<wchar_t>(); |
267 | if(r) return r; |
268 | #endif |
269 | return 0; |
270 | } |
271 | |