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
|