vmmlib  1.7.0
 All Classes Namespaces Functions Pages
tensor_mmapper.hpp
1 /*
2  * Copyright (c) 2006-2014, Visualization and Multimedia Lab,
3  * University of Zurich <http://vmml.ifi.uzh.ch>,
4  * Eyescale Software GmbH,
5  * Blue Brain Project, EPFL
6  *
7  * This file is part of VMMLib <https://github.com/VMML/vmmlib/>
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions are met:
11  *
12  * Redistributions of source code must retain the above copyright notice, this
13  * list of conditions and the following disclaimer. Redistributions in binary
14  * form must reproduce the above copyright notice, this list of conditions and
15  * the following disclaimer in the documentation and/or other materials provided
16  * with the distribution. Neither the name of the Visualization and Multimedia
17  * Lab, University of Zurich nor the names of its contributors may be used to
18  * endorse or promote products derived from this software without specific prior
19  * written permission.
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30  * POSSIBILITY OF SUCH DAMAGE.
31  */
32 
33 /* @author Susanne Suter
34  * @author Jonas Boesch
35  * @author David Klaper
36  * @author Claudio Mura
37  *
38  * class to read/write and convert tensor4 files (from raw, to csv...)
39  *
40  */
41 #ifndef __VMML__TENSOR_MMAPPER__HPP__
42 #define __VMML__TENSOR_MMAPPER__HPP__
43 
44 #include "tensor4.hpp"
45 #include <sys/mman.h>
46 #ifndef _MSC_VER
47 # include <unistd.h>
48 #else
49 # include <windows.h>
50 #endif
51 
52 namespace vmml
53 {
54 
55  template< typename T, typename C > // a tensor 3 or 4 type as T and
56  // a corresponding converter as C with the method write_to_raw(tensor& t, string dir, string filename)
58  {
59  public:
60  //tensor_mapper( const std::string& dir_, const std::string& filename, size_t tensor_count = 1 );
61 
62  //allocate memory mapped file
63  tensor_mmapper( const std::string& dir_, const std::string& filename_, const bool prot_read_, const C& tx_converter );
64  ~tensor_mmapper();
65 
66  void get_tensor( T& tensor_ ) { tensor_ = *_tensor; }
67 
68  protected:
69  static std::string concat_path( const std::string& dir_, const std::string& filename_ );
70 
71  void* t3_allocate_rd_mmap( const std::string& dir_, const std::string& filename_ );
72  void* t3_allocate_wr_mmap( const std::string& dir_, const std::string& filename_, const C& tx_converter );
73 
74 #ifdef _WIN32
75  HANDLE _fd, _fd_mmapped;
76 #else
77  int _fd; // one mmap for all tensors
78 #endif
79  size_t _file_size; // sizeof tensors * tensor_count
80  size_t _tensor_size;
81  void* _data; // ptr to mmapped memory
82 
83  T* _tensor;
84 
85  //std::vector<T*> _tensors;
86 
87  }; //end tensor_mmapper
88 
89 
90 
91 #define VMML_TEMPLATE_STRING template< typename T, typename C >
92 #define VMML_TEMPLATE_CLASSNAME tensor_mmapper< T, C >
93 
94 
95  /*VMML_TEMPLATE_STRING
96  VMML_TEMPLATE_CLASSNAME::tensor_mmapper( const std::string& dir_, const std::string& filename, size_t tensor_count = 1 )
97  // : init all values
98  {
99  _file_size = ...
100  // open or create file and mmap it
101 
102  _data = ...
103  _tensor_size = ...
104 
105  void* d = _data;
106  for( size_t i = 0; i < tensor_count; ++i )
107  {
108  _tensors.push_back( new T(d));
109  d += _tensor_size;
110  }
111  }*/
112 
113 
114  VMML_TEMPLATE_STRING
115  VMML_TEMPLATE_CLASSNAME::~tensor_mmapper()
116  {
117  if (_tensor)
118  {
119  _tensor->clear_array_pointer();
120  delete _tensor;
121  }
122 
123  munmap( _data, _file_size ); //get error
124  ::close( _fd );
125  }
126 
127 
128  VMML_TEMPLATE_STRING
129  VMML_TEMPLATE_CLASSNAME::tensor_mmapper( const std::string& dir_, const std::string& filename_, const bool prot_read_, const C& tx_converter_ )
130  : _file_size(0), _data(0), _tensor(0)
131  {
132 
133  _file_size = T::get_array_size_in_bytes();
134 
135  if ( prot_read_ ) {
136  t3_allocate_rd_mmap( dir_, filename_ );
137  } else {
138  t3_allocate_wr_mmap( dir_, filename_, tx_converter_ );
139  }
140 
141  if (_data != 0)
142  {
143  _tensor = new T( _data );
144  }
145  }
146 
147 
148 
149  VMML_TEMPLATE_STRING
150  void*
151  VMML_TEMPLATE_CLASSNAME::
152  t3_allocate_rd_mmap( const std::string& dir_, const std::string& filename_ )
153  {
154  //void * mmap(void *addr, size_t len, int prot, int flags, int fd, off_t offset);
155  std::string path = concat_path( dir_, filename_ );
156 #ifdef _WIN32
157  _fd = CreateFile( path, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
158  if( _fd == INVALID_HANDLE_VALUE )
159  {
160  CloseHandle( _fd );
161  // FIXME shouldn't we return here?
162  }
163 
164  off_t offset = 0;
165 
166  _fd_mmapped = ( void* )CreateFileMapping( _fd, 0, PAGE_READONLY, 0, 0, NULL ); // FIXME check. The fifth should be either 0 or _file_size
167  if (_fd_mmapped == NULL )
168  {
169  std::cout << "CreateFileMapping failed" << std::endl;
170  return 0;
171  }
172 
173  _data = MapViewOfFile( _fd_mmapped, FILE_MAP_READ, 0, 0, 0 );
174  if( _data == NULL )
175  {
176  std::cout << "MapViewOfFile failed" << std::endl;
177  return 0;
178  }
179 
180  return _data;
181 #else
182  _fd = open( path.c_str(), O_RDONLY, 0 );
183  if ( _fd == -1 )
184  {
185  {
186  close(_fd);
187  std::cout << "no file open for memory mapping" << std::endl;
188  // FIXME shouldn't we return here?
189  }
190  }
191 
192 
193  off_t offset = 0;
194 
195  _data = (void*)mmap( 0, _file_size, PROT_READ, MAP_FILE | MAP_SHARED, _fd, offset );
196 
197  if( _data == MAP_FAILED)
198  {
199  std::cout << "mmap failed" << std::endl;
200  return 0;
201  }
202 
203  return _data;
204 #endif
205  }
206 
207  VMML_TEMPLATE_STRING
208  void*
209  VMML_TEMPLATE_CLASSNAME::
210  t3_allocate_wr_mmap( const std::string& dir_, const std::string& filename_, const C& tx_converter_ )
211  {
212  //void * mmap(void *addr, size_t len, int prot, int flags, int fd, off_t offset);
213 
214  std::string path = concat_path( dir_, filename_ );
215 #ifdef _WIN32
216  _fd = CreateFile( path, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
217  if( _fd == INVALID_HANDLE_VALUE )
218  {
219  // Call GetLastError for more information
220  if ( ! _tensor )
221  {
222  _tensor = new T();
223  }
224  _tensor->zero();
225  tx_converter_.write_to_raw( *_tensor, dir_, filename_ );
226 
227  _fd = CreateFile( path, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
228  if( _fd == INVALID_HANDLE_VALUE )
229  {
230  CloseHandle( _fd );
231  std::cout << "no file open for memory mapping" << std::endl;
232  // FIXME shouldn't we return here?
233  }
234  }
235 
236  off_t offset = 0;
237 
238  _fd_mmapped = ( void* )CreateFileMapping( _fd, 0, PAGE_READWRITE, 0, 0, NULL ); // FIXME check. The fifth should be either 0 or _file_size
239  if (_fd_mmapped == NULL )
240  {
241  std::cout << "CreateFileMapping failed" << std::endl;
242  return 0;
243  }
244 
245  _data = MapViewOfFile( _fd_mmapped, FILE_MAP_WRITE, 0, 0, 0 );
246  if( _data == NULL )
247  {
248  std::cout << "MapViewOfFile failed" << std::endl;
249  return 0;
250  }
251 
252  return _data;
253 
254 #else
255  _fd = open( path.c_str(), O_RDWR, 0 );
256  if ( _fd == -1 )
257  {
258  if ( ! _tensor )
259  {
260  _tensor = new T();
261  }
262  _tensor->zero();
263  tx_converter_.write_to_raw( *_tensor, dir_, filename_ );
264 
265  _fd = open( path.c_str(), O_RDWR, 0 );
266  if ( _fd == -1 )
267  {
268  close(_fd);
269  std::cout << "no file open for memory mapping" << std::endl;
270  // FIXME shouldn't we return here?
271  }
272  }
273 
274  off_t offset = 0;
275 
276  _data = (void*)mmap( 0, _file_size, PROT_WRITE, MAP_FILE | MAP_SHARED, _fd, offset );
277 
278  if( _data == MAP_FAILED)
279  {
280  std::cout << "mmap failed" << std::endl;
281  return 0;
282  }
283 
284  return _data;
285 #endif
286  }
287 
288  VMML_TEMPLATE_STRING
289  std::string
290  VMML_TEMPLATE_CLASSNAME::concat_path( const std::string& dir_, const std::string& filename_ )
291  {
292  std::string path = "";
293  int dir_length = dir_.size() -1;
294 #ifdef _WIN32
295  int last_separator = dir_.find_last_of( "\\");
296 #else
297  int last_separator = dir_.find_last_of( "/");
298 #endif
299  path = dir_;
300  if (last_separator < dir_length ) {
301 #ifdef _WIN32
302  path.append( "\\" );
303 #else
304  path.append( "/" );
305 #endif
306  }
307  path.append( filename_ );
308 
309  // check for format
310  if( filename_.find( "raw", filename_.size()-3 ) == std::string::npos )
311  {
312  path.append( ".");
313  path.append( "raw" );
314  }
315 
316  return path;
317  }
318 
319 
320 #undef VMML_TEMPLATE_STRING
321 #undef VMML_TEMPLATE_CLASSNAME
322 
323 
324 } //end vmml namespace
325 
326 #endif