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 <ios> //std::streamoff
13 #include <fstream>   //std::ofstream, std::ifstream
14 #include <iostream>
15 #include <boost/interprocess/file_mapping.hpp>
16 #include <boost/interprocess/mapped_region.hpp>
17 #include <boost/container/vector.hpp>
18 #include <stdexcept> //std::exception
19 #include <cstddef>   //std::size_t
20 #include "get_process_id_name.hpp"
21 
22 using namespace boost::interprocess;
23 
get_filename()24 inline std::string get_filename()
25 {
26    std::string ret (ipcdetail::get_temporary_path());
27    ret += "/";
28    ret += test::get_process_id_name();
29    return ret;
30 }
31 
get_file_mapping()32 file_mapping get_file_mapping()
33 {
34    file_mapping f;
35    return file_mapping(boost::move(f));
36 }
37 
main()38 int main ()
39 {
40    try{
41       const std::size_t FileSize = 99999*2;
42       {
43          //Create file with given size
44          std::ofstream file(get_filename().c_str(), std::ios::binary | std::ios::trunc);
45          file.seekp(static_cast<std::streamoff>(FileSize-1));
46          file.write("", 1);
47       }
48 
49       {
50          //Create a file mapping
51          file_mapping mapping(get_filename().c_str(), read_write);
52          //Create two mapped regions, one half of the file each
53          mapped_region region (mapping
54                               ,read_write
55                               ,0
56                               ,FileSize/2
57                               );
58 
59          mapped_region region2(mapping
60                               ,read_write
61                               ,FileSize/2
62                               ,FileSize - FileSize/2
63                               );
64 
65          //Fill two regions with a pattern
66          unsigned char *filler = static_cast<unsigned char*>(region.get_address());
67          for(std::size_t i = 0
68             ;i < FileSize/2
69             ;++i){
70             *filler++ = static_cast<unsigned char>(i);
71          }
72 
73          filler = static_cast<unsigned char*>(region2.get_address());
74          for(std::size_t i = FileSize/2
75             ;i < FileSize
76             ;++i){
77             *filler++ = static_cast<unsigned char>(i);
78          }
79          if(!region.flush(0, 0, false)){
80             return 1;
81          }
82 
83          if(!region2.flush(0, 0, true)){
84             return 1;
85          }
86       }
87 
88       //See if the pattern is correct in the file
89       {
90          //Open the file
91          std::ifstream file(get_filename().c_str(), std::ios::binary);
92 
93          //Create a memory buffer
94          boost::container::vector<unsigned char> memory(FileSize/2 +1);
95 
96          //Fill buffer
97          file.read(static_cast<char*>(static_cast<void*>(memory.data()))
98                   , FileSize/2);
99 
100          unsigned char *checker = memory.data();
101          //Check pattern
102          for(std::size_t i = 0
103             ;i < FileSize/2
104             ;++i){
105             if(*checker++ != static_cast<unsigned char>(i)){
106                return 1;
107             }
108          }
109 
110          //Fill buffer
111          file.read(static_cast<char*>(static_cast<void*>(memory.data()))
112                   , FileSize - FileSize/2);
113 
114          checker = memory.data();
115          //Check pattern
116          for(std::size_t i = FileSize/2
117             ;i < FileSize
118             ;++i){
119             if(*checker++ != static_cast<unsigned char>(i)){
120                return 1;
121             }
122          }
123       }
124 
125       //Now check the pattern mapping a single read only mapped_region
126       {
127          //Create a file mapping
128          file_mapping mapping(get_filename().c_str(), read_only);
129 
130          //Create a single regions, mapping all the file
131          mapped_region region (mapping
132                               ,read_only
133                               );
134 
135          //Check pattern
136          unsigned char *pattern = static_cast<unsigned char*>(region.get_address());
137          for(std::size_t i = 0
138             ;i < FileSize
139             ;++i, ++pattern){
140             if(*pattern != static_cast<unsigned char>(i)){
141                return 1;
142             }
143          }
144       }
145       {
146          //Now test move semantics
147          file_mapping mapping(get_filename().c_str(), read_only);
148          file_mapping move_ctor(boost::move(mapping));
149          file_mapping move_assign;
150          move_assign = boost::move(move_ctor);
151          mapping.swap(move_assign);
152          file_mapping ret(get_file_mapping());
153       }
154    }
155    catch(std::exception &exc){
156       file_mapping::remove(get_filename().c_str());
157       std::cout << "Unhandled exception: " << exc.what() << std::endl;
158       throw;
159    }
160    file_mapping::remove(get_filename().c_str());
161    return 0;
162 }
163 
164 #include <boost/interprocess/detail/config_end.hpp>
165