00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 #include "platform/mapped_file.hpp"
00035 #include "data/exception.hpp"
00036 #include "data/string.hpp"
00037 #include "data/file.hpp"
00038
00039 #include "platform/lowlevel.hpp"
00040
00041
00042 namespace gsgl
00043 {
00044
00045 using namespace io;
00046
00047 namespace platform
00048 {
00049
00050 #ifdef WIN32
00051 static string get_windows_error()
00052 {
00053 void *buf;
00054 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, 0, GetLastError(), 0, (LPWSTR) &buf, 512, 0);
00055 string res(static_cast<wchar_t *>(buf));
00056 LocalFree(buf);
00057
00058 return res;
00059 }
00060 #endif
00061
00062
00063
00064 static int NUM_MAPPED_FILES = 0;
00065
00066
00067 mapped_file::mapped_file(const string & fname, unsigned int io_open_mode, unsigned int create_size)
00068 : file_handle(0), map_handle(0), map_pointer(0)
00069 {
00070 #ifdef WIN32
00071 string full_path = io::file::get_full_path(fname);
00072
00073
00074 unsigned int win_open_mode = GENERIC_READ;
00075
00076 if (io_open_mode & io::FILE_OPEN_WRITE)
00077 win_open_mode |= GENERIC_WRITE;
00078
00079 if (file::exists(full_path))
00080 {
00081 file_handle = CreateFileW(full_path.w_string(), win_open_mode, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
00082
00083 if (file_handle != INVALID_HANDLE_VALUE)
00084 create_size = GetFileSize(file_handle, 0);
00085 }
00086 else
00087 {
00088 if (create_size == 0)
00089 throw internal_exception(__FILE__, __LINE__, L"Must specify size for creating memory-mapped files.");
00090
00091 file_handle = CreateFileW(full_path.w_string(), win_open_mode, 0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
00092
00093 if (file_handle != INVALID_HANDLE_VALUE)
00094 {
00095 unsigned char buf = 0;
00096 unsigned int written;
00097 SetFilePointer(file_handle, create_size-1, 0, FILE_BEGIN);
00098 WriteFile(file_handle, &buf, 1, (LPDWORD) &written, 0);
00099 SetFilePointer(file_handle, 0, 0, FILE_BEGIN);
00100 }
00101 }
00102
00103 if (file_handle == INVALID_HANDLE_VALUE)
00104 throw io_exception(L"Unable to open %ls: %ls", full_path.w_string(), get_windows_error().w_string());
00105
00106
00107 string map_name = string::format(L"periapsis_mapped_file_%d", NUM_MAPPED_FILES++);
00108
00109 if (io_open_mode & io::FILE_OPEN_WRITE)
00110 win_open_mode = PAGE_READWRITE;
00111 else
00112 win_open_mode = PAGE_READONLY;
00113
00114 map_handle = CreateFileMappingW(file_handle, 0, win_open_mode, 0, create_size, map_name.w_string());
00115
00116 if (!map_handle)
00117 throw io_exception(L"Unable to create memory map for %ls: %ls", full_path.w_string(), get_windows_error().w_string());
00118
00119
00120 if (io_open_mode & io::FILE_OPEN_WRITE)
00121 win_open_mode = FILE_MAP_ALL_ACCESS;
00122 else
00123 win_open_mode = FILE_MAP_READ;
00124
00125 map_pointer = MapViewOfFile(map_handle, win_open_mode, 0, 0, 0);
00126
00127 if (!map_pointer)
00128 throw io_exception(L"Unable to create memory map for %ls: %ls", full_path.w_string(), get_windows_error().w_string());
00129
00130 map_size = create_size;
00131 #else
00132 #error Implement memory-mapped files!
00133 #endif
00134 }
00135
00136
00137 mapped_file::~mapped_file()
00138 {
00139 #ifdef WIN32
00140 if (map_pointer)
00141 {
00142 UnmapViewOfFile(map_pointer);
00143 map_pointer = 0;
00144 }
00145
00146 if (map_handle)
00147 {
00148 CloseHandle(map_handle);
00149 map_handle = 0;
00150 }
00151
00152 if (file_handle)
00153 {
00154 CloseHandle(file_handle);
00155 file_handle = 0;
00156 }
00157 #else
00158 #error Implement memory-mapped files!
00159 #endif
00160 }
00161
00162
00163 unsigned int mapped_file::get_size()
00164 {
00165 return map_size;
00166 }
00167
00168
00169 void *mapped_file::get_pointer()
00170 {
00171 return map_pointer;
00172 }
00173
00174
00175 }
00176
00177 }