File: fileMap.cc

package info (click to toggle)
last-align 1651-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 14,688 kB
  • sloc: cpp: 44,419; python: 5,217; ansic: 1,938; sh: 710; makefile: 457
file content (65 lines) | stat: -rw-r--r-- 1,803 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
// Copyright 2010, 2013 Martin C. Frith

#include "fileMap.hh"

#include "stringify.hh"

#include <cstring>  // strerror
#include <cerrno>
#include <stdexcept>

// File mapping requires non-standard-C++ library functions.  I think
// this code will not work on all platforms, e.g. windows.  Hopefully,
// it's easy to rewrite this code for those platforms.

#include <fcntl.h>  // open
#include <unistd.h>  // close
#include <sys/mman.h>  // mmap, munmap

static void err( const std::string& s ) {
  throw std::runtime_error( s + ": " + std::strerror(errno) );
}

// This function tries to force the file-mapping to actually get
// loaded into memory, by reading it sequentially.  Without this,
// random access can be horribly slow (at least on two Linux 2.6
// systems).
static void primeMemory( void* begin, size_t bytes ){
  unsigned z = 0;
  size_t stepSize = 1024;
  const char* x = static_cast<char*>(begin);
  const char* y = x + (bytes / stepSize) * stepSize;
  while( x < y ){
    z += *x;
    x += stepSize;
  }
  volatile unsigned dontOptimizeMeAway = z;
  dontOptimizeMeAway = dontOptimizeMeAway;  // ??? prevents compiler warning
}

namespace cbrc{

void* openFileMap( const std::string& fileName, size_t bytes ){
  if( bytes == 0 ) return 0;

  int f = open( fileName.c_str(), O_RDONLY );
  if( f < 0 ) err( "can't open file " + fileName );

  void* m = mmap( 0, bytes, PROT_READ, MAP_SHARED, f, 0 );
  if( m == MAP_FAILED ) err( "can't map file " + fileName );

  int e = close(f);
  if( e < 0 ) err( "can't close file " + fileName );

  primeMemory( m, bytes );

  return m;
}

void closeFileMap( void* begin, size_t bytes ){
  if( bytes == 0 ) return;
  int e = munmap( begin, bytes );
  if( e < 0 ) err( "failed to \"munmap\" " + stringify(bytes) + " bytes" );
}

}  // end namespace