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 <fstream> |
12 | #include <iostream> |
13 | #include <boost/interprocess/shared_memory_object.hpp> |
14 | #include <boost/interprocess/mapped_region.hpp> |
15 | #include <boost/interprocess/anonymous_shared_memory.hpp> |
16 | #include <string> |
17 | #include "get_process_id_name.hpp" |
18 | |
19 | using namespace boost::interprocess; |
20 | |
21 | shared_memory_object get_shared_memory_mapping() |
22 | { |
23 | shared_memory_object sh; |
24 | return shared_memory_object(boost::move(t&: sh)); |
25 | } |
26 | |
27 | int main () |
28 | { |
29 | std::string process_id = test::get_process_id_name(); |
30 | std::string process_id2(process_id); |
31 | process_id2 += "_2" ; |
32 | BOOST_TRY{ |
33 | const std::size_t FileSize = 99999*4; |
34 | { |
35 | //Remove shared memory |
36 | shared_memory_object::remove(filename: process_id.c_str()); |
37 | shared_memory_object::remove(filename: process_id2.c_str()); |
38 | |
39 | //Create shared memory and file mapping |
40 | shared_memory_object mapping(create_only, process_id.c_str(), read_write); |
41 | mapping.truncate(length: FileSize); |
42 | } |
43 | |
44 | { |
45 | //Create a file mapping |
46 | shared_memory_object mapping(open_only, process_id.c_str(), read_write); |
47 | |
48 | //Create two mapped regions, one half of the file each |
49 | mapped_region region (mapping |
50 | ,read_write |
51 | ,0 |
52 | ,FileSize/2 |
53 | ,0); |
54 | |
55 | mapped_region region2(mapping |
56 | ,read_write |
57 | ,FileSize/2 |
58 | ,FileSize - FileSize/2 |
59 | ,0); |
60 | |
61 | //Fill two regions with a pattern |
62 | unsigned char *filler = static_cast<unsigned char*>(region.get_address()); |
63 | for(std::size_t i = 0 |
64 | ;i < FileSize/2 |
65 | ;++i){ |
66 | *filler++ = static_cast<unsigned char>(i); |
67 | } |
68 | |
69 | filler = static_cast<unsigned char*>(region2.get_address()); |
70 | for(std::size_t i = FileSize/2 |
71 | ;i < FileSize |
72 | ;++i){ |
73 | *filler++ = static_cast<unsigned char>(i); |
74 | } |
75 | if(!region.flush(mapping_offset: 0, numbytes: 0, async: false)){ |
76 | return 1; |
77 | } |
78 | |
79 | if(!region2.flush(mapping_offset: 0, numbytes: 0, async: true)){ |
80 | return 1; |
81 | } |
82 | } |
83 | |
84 | //See if the pattern is correct in the file using two mapped regions |
85 | { |
86 | //Create a file mapping |
87 | shared_memory_object mapping(open_only, process_id.c_str(), read_write); |
88 | mapped_region region(mapping, read_write, 0, FileSize/2, 0); |
89 | mapped_region region2(mapping, read_write, FileSize/2, FileSize - FileSize/2, 0); |
90 | |
91 | unsigned char *checker = static_cast<unsigned char*>(region.get_address()); |
92 | //Check pattern |
93 | for(std::size_t i = 0 |
94 | ;i < FileSize/2 |
95 | ;++i){ |
96 | if(*checker++ != static_cast<unsigned char>(i)){ |
97 | return 1; |
98 | } |
99 | } |
100 | |
101 | //Check second half |
102 | checker = static_cast<unsigned char *>(region2.get_address()); |
103 | |
104 | //Check pattern |
105 | for(std::size_t i = FileSize/2 |
106 | ;i < FileSize |
107 | ;++i){ |
108 | if(*checker++ != static_cast<unsigned char>(i)){ |
109 | return 1; |
110 | } |
111 | } |
112 | } |
113 | #ifdef BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES |
114 | //Now check the pattern mapping a single read only mapped_region |
115 | { |
116 | //Create a file mapping |
117 | shared_memory_object mapping(open_only, test::get_process_id_wname(), read_only); |
118 | |
119 | //Create a single regions, mapping all the file |
120 | mapped_region region (mapping, read_only); |
121 | |
122 | //Check pattern |
123 | unsigned char *pattern = static_cast<unsigned char*>(region.get_address()); |
124 | for(std::size_t i = 0 |
125 | ;i < FileSize |
126 | ;++i, ++pattern){ |
127 | if(*pattern != static_cast<unsigned char>(i)){ |
128 | return 1; |
129 | } |
130 | } |
131 | } |
132 | #endif //BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES |
133 | //Now check the pattern mapping a single read only mapped_region |
134 | { |
135 | //Create a file mapping |
136 | shared_memory_object mapping(open_only, process_id.c_str(), read_only); |
137 | |
138 | //Create a single regions, mapping all the file |
139 | mapped_region region (mapping, read_only); |
140 | |
141 | //Check pattern |
142 | unsigned char *pattern = static_cast<unsigned char*>(region.get_address()); |
143 | for(std::size_t i = 0 |
144 | ;i < FileSize |
145 | ;++i, ++pattern){ |
146 | if(*pattern != static_cast<unsigned char>(i)){ |
147 | return 1; |
148 | } |
149 | } |
150 | //Now shrink |
151 | const std::size_t original_region_size = region.get_size(); |
152 | if(!region.shrink_by(bytes: region.get_size()/2, from_back: false) || region.get_size() != original_region_size/2){ |
153 | return 1; |
154 | } |
155 | const std::size_t shrunk_region_size = region.get_size(); |
156 | if(!region.shrink_by(bytes: region.get_size()/2, from_back: true) || region.get_size() != shrunk_region_size/2){ |
157 | return 1; |
158 | } |
159 | |
160 | //Now advise |
161 | #if defined(POSIX_MADV_NORMAL) || defined(MADV_NORMAL) |
162 | std::cout << "Advice normal" << std::endl; |
163 | if(!region.advise(advice: mapped_region::advice_normal)){ |
164 | return 1; |
165 | } |
166 | #endif |
167 | |
168 | #if defined(POSIX_MADV_SEQUENTIAL) || defined(MADV_SEQUENTIAL) |
169 | std::cout << "Advice sequential" << std::endl; |
170 | if(!region.advise(advice: mapped_region::advice_sequential)){ |
171 | return 1; |
172 | } |
173 | #endif |
174 | |
175 | #if defined(POSIX_MADV_RANDOM) || defined(MADV_RANDOM) |
176 | std::cout << "Advice random" << std::endl; |
177 | if(!region.advise(advice: mapped_region::advice_random)){ |
178 | return 1; |
179 | } |
180 | #endif |
181 | |
182 | #if defined(POSIX_MADV_WILLNEED) || defined(MADV_WILLNEED) |
183 | std::cout << "Advice 'will need'" << std::endl; |
184 | if(!region.advise(advice: mapped_region::advice_willneed)){ |
185 | return 1; |
186 | } |
187 | #endif |
188 | |
189 | #if defined(POSIX_MADV_DONTNEED) || (defined(MADV_DONTNEED) && defined(BOOST_INTERPROCESS_MADV_DONTNEED_HAS_NONDESTRUCTIVE_SEMANTICS)) |
190 | std::cout << "Advice 'dont't need'" << std::endl; |
191 | if(!region.advise(advice: mapped_region::advice_dontneed)){ |
192 | return 1; |
193 | } |
194 | #endif |
195 | |
196 | } |
197 | { |
198 | //Check for busy address space |
199 | shared_memory_object mapping(open_only, process_id.c_str(), read_only); |
200 | mapped_region region (mapping, read_only); |
201 | shared_memory_object mapping2(create_only, process_id2.c_str(), read_write); |
202 | mapping2.truncate(length: FileSize); |
203 | BOOST_TRY{ |
204 | mapped_region region2 (mapping2, read_only, 0, FileSize, region.get_address()); |
205 | } |
206 | BOOST_CATCH(interprocess_exception &e){ |
207 | shared_memory_object::remove(filename: process_id2.c_str()); |
208 | if(e.get_error_code() != busy_error){ |
209 | throw e; |
210 | } |
211 | } |
212 | BOOST_CATCH(std::exception &){ |
213 | shared_memory_object::remove(filename: process_id2.c_str()); |
214 | BOOST_RETHROW |
215 | } BOOST_CATCH_END |
216 | shared_memory_object::remove(filename: process_id2.c_str()); |
217 | } |
218 | { |
219 | //Now check anonymous mapping |
220 | mapped_region region(anonymous_shared_memory(size: FileSize)); |
221 | |
222 | //Write pattern |
223 | unsigned char *pattern = static_cast<unsigned char*>(region.get_address()); |
224 | for(std::size_t i = 0 |
225 | ;i < FileSize |
226 | ;++i, ++pattern){ |
227 | *pattern = static_cast<unsigned char>(i); |
228 | } |
229 | |
230 | //Check pattern |
231 | pattern = static_cast<unsigned char*>(region.get_address()); |
232 | for(std::size_t i = 0 |
233 | ;i < FileSize |
234 | ;++i, ++pattern){ |
235 | if(*pattern != static_cast<unsigned char>(i)){ |
236 | return 1; |
237 | } |
238 | } |
239 | } |
240 | { |
241 | //Now test move semantics |
242 | shared_memory_object mapping(open_only, process_id.c_str(), read_write); |
243 | shared_memory_object move_ctor(boost::move(t&: mapping)); |
244 | shared_memory_object move_assign; |
245 | move_assign = boost::move(t&: move_ctor); |
246 | shared_memory_object ret(get_shared_memory_mapping()); |
247 | } |
248 | } |
249 | BOOST_CATCH(std::exception &exc){ |
250 | shared_memory_object::remove(filename: process_id.c_str()); |
251 | shared_memory_object::remove(filename: process_id2.c_str()); |
252 | std::cout << "Unhandled exception: " << exc.what() << std::endl; |
253 | return 1; |
254 | } BOOST_CATCH_END |
255 | shared_memory_object::remove(filename: process_id.c_str()); |
256 | return 0; |
257 | } |
258 | |