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