Commit 02a18624 authored by Martin Schultz's avatar Martin Schultz

* implemented FileMapping for windows using PIMPL Idiom

* next step: implement the posix version with mmap
parent 22c374d5
/***********************************************************************
* Copyright 2011-2014 Computer Graphics Group RWTH Aachen University. *
* All rights reserved. *
* Distributed under the terms of the MIT License (see LICENSE.TXT). *
**********************************************************************/
#pragma once
#include <ACGL/ACGL.hh>
/////////////////////////////////////////////////////////////
//
// forward declaration of platform specific implementation
//
/////////////////////////////////////////////////////////////
#ifdef _WIN32
class MemoryMappedFileWinImpl;
#else
class MemoryMappedFilePosixImpl;
#endif
namespace ACGL{
namespace Utils{
/**********************************************************************
* Provide a platform independant mechanism to map a large file into
* random access memory. This implementation only supports files, no
* images or anonymous mapping is supported.
*
* For more information about the concept of FileMapping see:
* http://msdn.microsoft.com/en-us/library/windows/desktop/aa366556(v=vs.85).aspx
* or
* http://en.wikipedia.org/wiki/Memory-mapped_file
*
* For the sake of compatibility, huge pages is not yet used.
* Also consider the plattform specific limitations (e.G. size of off_t)
**********************************************************************/
class MemoryMappedFile
{
private:
#ifdef _WIN32
MemoryMappedFileWinImpl* mpMMFileImpl = nullptr;
#else
MemoryMappedFilePosixImpl* mpMMFileImpl = nullptr;
#endif
public:
////////////////////////////////////////////////////////////////
//
// enum to determine if the mapped memory is available for
// other processes
//
////////////////////////////////////////////////////////////////
enum shareMode
{
MAP_PRIVATE,
MAP_SHARED
};
////////////////////////////////////////////////////////////////
//
// enum to determine how the mapped memory is accessed
//
////////////////////////////////////////////////////////////////
enum accessMode
{
READ_ONLY,
READ_WRITE
};
/********************************************************************
* opens the file specified by _filename and maps it into RAM.
* The file stays mapped and the handle opened, until the
* MemoryMappedFile instance is destroyed. Keep in mind, that other
* processes may not access the memory region after the file was
* unmapped.
*
* parameters:
*
* char* _filename - the file to be mapped
*
* _accessMode - determines if the memory has read or write
* access. readonly mappings cause a sigsegv
* when trying to write them.
*
* _shareMode - determine if other processes may access the
* mapped file the current process owns the
* mapping.
*
* size_t _length - the length of the file to be mapped use 0
* to map the entire file. if you want to map
* only a part of the file use
* _offset + desired length in bytes
*
* off_t _offset - use 0 if you want to map the entire file.
* otherwise use the byte offset. Keep in mind
* the mapping is page aligned.
********************************************************************/
MemoryMappedFile( const char* _fileName,
accessMode _accessMode = accessMode::READ_ONLY,
shareMode _shareMode = shareMode::MAP_PRIVATE,
size_t _length = 0,
off_t _offset = 0);
//pointer to the mapped data
char * data();
//const pointer to the mapped data
const char * data() const;
// use the error code to determine if mapping was successful
int errorCode();
int errorCode() const;
//the offset to page aligned memory (will be 0 if you map the entire file)
off_t pageOffset();
off_t pageOffset() const;
//length of the file mapping
off_t length();
off_t length() const;
//unmaps and closes file handle
~MemoryMappedFile();
};
}
}
\ No newline at end of file
/***********************************************************************
* Copyright 2011-2013 Computer Graphics Group RWTH Aachen University. *
* All rights reserved. *
* Distributed under the terms of the MIT License (see LICENSE.TXT). *
**********************************************************************/
#pragma once
#ifdef __unix
#include "MemoryMappedFile.hh"
class MemoryMappedFilePosixImpl
{
public:
MemoryMappedFilePosixImpl( const char* _fileName,
ACGL::Utils::MemoryMappedFile::accessMode _accessMode,
ACGL::Utils::MemoryMappedFile::shareMode _shareMode,
size_t _length = 0,
off_t _offset = 0);
char * data();
const char * data() const;
int errorCode();
int errorCode() const;
off_t pageOffset();
off_t pageOffset() const;
off_t length();
off_t length() const;
~MemoryMappedFilePosixImpl();
};
#endif
\ No newline at end of file
/***********************************************************************
* Copyright 2011-2014 Computer Graphics Group RWTH Aachen University. *
* All rights reserved. *
* Distributed under the terms of the MIT License (see LICENSE.TXT). *
**********************************************************************/
#pragma once
///////////////////////////////////////
//
// only compile on windows platform
//
///////////////////////////////////////
#ifdef _WIN32
#include "MemoryMappedFile.hh"
#include <Windows.h>
class MemoryMappedFileWinImpl
{
public:
/*******************************************************************************
* Windows implementation only allows path with length of 260 characters or less
* If you need more, use wchar instead and convert the path as described by msdn
* http://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx
*
* off_t is in windows a long integer so you can address 64 byte file mappings
* when creating a file map two dword are used.
*******************************************************************************/
MemoryMappedFileWinImpl(const char* _fileName,
ACGL::Utils::MemoryMappedFile::accessMode _accessMode,
ACGL::Utils::MemoryMappedFile::shareMode _shareMode,
size_t _length = 0,
off_t _offset = 0);
char * data();
const char * data() const;
int errorCode();
int errorCode() const;
off_t pageOffset();
off_t pageOffset() const;
off_t length();
off_t length() const;
~MemoryMappedFileWinImpl();
private:
DWORD mErrorCode;
char* mpData;
off_t mPageOffset;
off_t mLength;
HANDLE mFileHandle;
HANDLE mFileMappingHandle;
};
#endif
\ No newline at end of file
/***********************************************************************
* Copyright 2011-2013 Computer Graphics Group RWTH Aachen University. *
* All rights reserved. *
* Distributed under the terms of the MIT License (see LICENSE.TXT). *
**********************************************************************/
#pragma once
///////////////////////////////////////////////////////////////////////
//
// include os specific headers
//
///////////////////////////////////////////////////////////////////////
#include "ACGL/Utils/MemoryMappedFile.hh"
#ifdef _WIN32
class MemoryMappedFileWinImpl;
#include "ACGL/Utils/MemoryMappedFileWinImpl.hh"
#else
#include "ACGL/Utils/MemoryMappedFilePosixImpl.hh"
#endif
// call the os specific implementation
// PIMPL idiom
ACGL::Utils::MemoryMappedFile::MemoryMappedFile(
const char* _fileName,
accessMode _accessMode,
shareMode _shareMode,
size_t _length,
off_t _offset)
{
#ifdef _WIN32
mpMMFileImpl = new MemoryMappedFileWinImpl(_fileName, _accessMode, _shareMode, _length, _offset);
#else
mpMMFileImpl = new MemoryMappedFilePosixImpl(_fileName, _accessMode, _shareMode, _length, _offset);
#endif
}
char * ACGL::Utils::MemoryMappedFile::data(){ return mpMMFileImpl->data(); }
const char * ACGL::Utils::MemoryMappedFile::data() const{ return mpMMFileImpl->data(); }
int ACGL::Utils::MemoryMappedFile::errorCode() { return mpMMFileImpl->errorCode(); }
int ACGL::Utils::MemoryMappedFile::errorCode() const{ return mpMMFileImpl->errorCode(); }
off_t ACGL::Utils::MemoryMappedFile::pageOffset(){ return mpMMFileImpl->pageOffset(); }
off_t ACGL::Utils::MemoryMappedFile::pageOffset() const{ return mpMMFileImpl->pageOffset(); }
off_t ACGL::Utils::MemoryMappedFile::length(){ return mpMMFileImpl->length(); }
off_t ACGL::Utils::MemoryMappedFile::length() const{ return mpMMFileImpl->length(); }
ACGL::Utils::MemoryMappedFile::~MemoryMappedFile(){ if (mpMMFileImpl) delete mpMMFileImpl; }
/***********************************************************************
* Copyright 2011-2013 Computer Graphics Group RWTH Aachen University. *
* All rights reserved. *
* Distributed under the terms of the MIT License (see LICENSE.TXT). *
**********************************************************************/
#pragma once
#ifdef __unix
#include "ACGL/Utils/MemoryMappedFilePosixImpl.hh"
MemoryMappedFilePosixImpl::MemoryMappedFilePosixImpl(
const char* _fileName,
ACGL::Utils::MemoryMappedFile::accessMode _accessMode,
ACGL::Utils::MemoryMappedFile::shareMode _shareMode,
size_t _length,
off_t _offset)
{
}
char * MemoryMappedFilePosixImpl::data()
{
return 0;
}
const char * MemoryMappedFilePosixImpl::data() const
{
return 0;
}
int MemoryMappedFilePosixImpl::errorCode()
{
return 0;
}
int MemoryMappedFilePosixImpl::errorCode() const
{
return 0;
}
off_t MemoryMappedFilePosixImpl::pageOffset()
{
return 0;
}
off_t MemoryMappedFilePosixImpl::pageOffset() const
{
return 0;
}
off_t MemoryMappedFilePosixImpl::length()
{
return 0;
}
off_t MemoryMappedFilePosixImpl::length() const
{
return 0;
}
MemoryMappedFilePosixImpl::~MemoryMappedFilePosixImpl()
{
}
#endif
/***********************************************************************
* Copyright 2011-2014 Computer Graphics Group RWTH Aachen University. *
* All rights reserved. *
* Distributed under the terms of the MIT License (see LICENSE.TXT). *
**********************************************************************/
#pragma once
#ifdef _WIN32
#include "ACGL/Utils/MemoryMappedFileWinImpl.hh"
MemoryMappedFileWinImpl::MemoryMappedFileWinImpl(
const char* _fileName,
ACGL::Utils::MemoryMappedFile::accessMode _accessMode,
ACGL::Utils::MemoryMappedFile::shareMode _shareMode,
size_t _length,
off_t _offset) :
mErrorCode(0),
mPageOffset(0),
mFileHandle(nullptr),
mFileMappingHandle(NULL)
{
DWORD fileAccess = 0;
DWORD fileShare = 0;
DWORD fileSize = 0;
DWORD offsetLow = 0;
DWORD offsetHigh = 0;
DWORD mapAccess = 0;
DWORD mapViewAccess = 0;
DWORD mapSize = 0;
/////////////////////////////////////////////////////
//
// initialize flags
//
/////////////////////////////////////////////////////
if (_shareMode == ACGL::Utils::MemoryMappedFile::MAP_SHARED)
{
fileShare = FILE_SHARE_READ | FILE_SHARE_WRITE;
}
if (_accessMode == ACGL::Utils::MemoryMappedFile::READ_ONLY)
{
//msdn example says if we want to read the file we need to specify share_read
fileAccess = GENERIC_READ;
fileShare |= FILE_SHARE_READ;
mapAccess = PAGE_READONLY;
mapViewAccess = FILE_MAP_READ;
}
else
{
fileAccess = GENERIC_READ | GENERIC_WRITE;
mapAccess = PAGE_READWRITE;
mapViewAccess = FILE_MAP_READ | FILE_MAP_WRITE;
}
//////////////////////
//
// open the file
//
//////////////////////
mFileHandle = CreateFile(_fileName, fileAccess, fileShare,
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (mFileHandle == INVALID_HANDLE_VALUE)
{
std::cout << _fileName << std::endl;
mErrorCode = GetLastError();
return;
}
//determine the size of the mapped view
// fileSize = GetFileSize(mFileHandle, NULL);
mapSize = GetFileSize(mFileHandle, NULL);
if (_offset > 0)
{
offsetLow = _offset;
offsetHigh = ((_offset >> 16)>>16);
SYSTEM_INFO info;
GetSystemInfo(&info);
mPageOffset = _offset % info.dwAllocationGranularity;
mapSize -= (_offset - mPageOffset);
}
if (_length > 0 )
{
mapSize = _length;
}
//create the file mapping handle
mFileMappingHandle = CreateFileMapping(mFileHandle, NULL, mapAccess, 0, 0, NULL);
if (mFileMappingHandle == NULL)
{
mErrorCode = GetLastError();
return;
}
//create the file mapping view
mpData = reinterpret_cast<PCHAR>
(MapViewOfFile(mFileMappingHandle, mapViewAccess, offsetHigh, offsetLow - mPageOffset, mapSize));
if (!mpData)
{
mErrorCode = GetLastError();
return;
}
mLength = mapSize;
}
char * MemoryMappedFileWinImpl::data()
{
return mpData;
}
const char * MemoryMappedFileWinImpl::data() const
{
return mpData;
}
int MemoryMappedFileWinImpl::errorCode()
{
return mErrorCode;
}
int MemoryMappedFileWinImpl::errorCode() const
{
return mErrorCode;
}
off_t MemoryMappedFileWinImpl::pageOffset()
{
return mPageOffset;
}
off_t MemoryMappedFileWinImpl::pageOffset() const
{
return mPageOffset;
}
off_t MemoryMappedFileWinImpl::length()
{
return mLength;
}
off_t MemoryMappedFileWinImpl::length() const
{
return mLength;
}
MemoryMappedFileWinImpl::~MemoryMappedFileWinImpl()
{
if (mpData)
UnmapViewOfFile(mpData);
if (mFileMappingHandle)
CloseHandle(mFileMappingHandle);
if (mFileHandle != INVALID_HANDLE_VALUE)
CloseHandle(mFileHandle);
}
#endif
\ No newline at end of file
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment