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