YSTest: MemoryMapping.cpp 源文件

YSTest PreAlpha_b800_20170810 The YSLib Test Project

- 首页
- 相关页面
- 模块
- 命名空间
- 类
- 文件

- 文件列表
- 文件成员

MemoryMapping.cpp
浏览该文件的文档.
1 /*
2 © 2012-2016 FrankHB.
3
4 This file is part of the YSLib project, and may only be used,
5 modified, and distributed under the terms of the YSLib project
6 license, LICENSE.TXT. By continuing to use, modify, or distribute
7 this file you indicate that you have read the license and
8 understand and accept it fully.
9 */
10
28 #include "YCLib/YModules.h"
29 #include YFM_YCLib_MemoryMapping // for wcast;
30 #include YFM_YCLib_FileIO // for uopen, YCL_Raise_SysE, YCL_CallF_CAPI,
31 // std::throw_with_nested, std::runtime_error, ystdex::throw_error,
32 // std::errc::bad_file_descriptor;
33 #include YFM_YCLib_NativeAPI // for ::UnmapViewOfFile, ::munmap,
34 // platform_ex::ToHandle, CreateFileMapping, PAGE_READONLY, PAGE_READWRITE,
35 // MapViewOfFile, FILE_MAP_READ, FILE_MAP_ALL_ACCESS, FILE_MAP_COPY, ::mmap,
36 // PROT_READ, PROT_WRITE, ::lseek, MAP_PRIVATE, MAP_SHARED, MAP_FAILED;
37 #include <ystdex/cast.hpp> // for ystdex::narrow;
38 #if YCL_Win32
39 # include YFM_YCLib_Host // for platform_ex::UniqueHandle;
40 # include YFM_Win32_YCLib_MinGW32 // for YCL_CallF_Win32;
41 #endif
42
43 namespace platform
44 {
45
46 #if !YCL_DS
47 void
48 UnmapDelete::operator()(pointer p) const ynothrow
49 {
50 // XXX: Error ignored.
51 #if YCL_Win32
52 ::UnmapViewOfFile(p);
53 #else
54 ::munmap(p, size);
55 #endif
56 }
57 #endif
58
59
60 MappedFile::MappedFile(std::uint64_t off, size_t len, UniqueFile f,
61 FileMappingOption opt, FileMappingKey key)
62 : option(opt), file(std::move(f)), mapped(
63 #if YCL_DS
64 new byte[len]
65 #else
66 [=](){
67 try
68 {
69 if(len != 0)
70 {
71 # if YCL_Win32
72 const auto h(platform_ex::ToHandle(*file.get()));
73
74 if(h != INVALID_HANDLE_VALUE)
75 {
76 platform_ex::UniqueHandle fm(YCL_CallF_Win32(
77 CreateFileMapping, h, {},
78 opt != FileMappingOption::ReadWrite ? PAGE_READONLY
79 : PAGE_READWRITE, 0, 0, wcast(key)));
80
81 return static_cast< byte*>(YCL_CallF_Win32(MapViewOfFile,
82 fm.get(), opt != FileMappingOption::CopyOnWrite
83 ? (opt == FileMappingOption::ReadOnly ? FILE_MAP_READ
84 : FILE_MAP_ALL_ACCESS) : FILE_MAP_COPY,
85 static_cast<unsigned long>(off >> 32UL),
86 static_cast<unsigned long>(off), len));
87 }
88 YCL_Raise_SysE(, "::_get_osfhandle", yfsig);
89 # else
90 // NOTE: Since no %MAP_FIXED or extensions can be specified
91 // here, there is no need to convert %ENOMEM to throwing
92 // %std::bad_alloc or derived exceptions.
93 const auto
94 p(::mmap({}, len, opt != FileMappingOption::ReadWrite
95 ? PROT_READ : PROT_READ | PROT_WRITE, opt
96 == FileMappingOption::CopyOnWrite || key == FileMappingKey()
97 ? MAP_PRIVATE : MAP_SHARED, *file.get(), ::off_t(off)));
98
99 if(p != MAP_FAILED)
100 return static_cast< byte*>(p);
101 YCL_Raise_SysE(, "::mmap", yfsig);
102 # endif
103 }
104 throw std::invalid_argument("Empty file found.");
105 }
106 // TODO: Create specific exception type?
107 CatchExpr(...,
108 std::throw_with_nested(std::runtime_error("Mapping failed.")))
109 }()
110 #endif
111 // NOTE: For platform %Win32, relying on ::NtQuerySection is not allowed by
112 // current platform implmentation policy.
113 , len)
114 {
115 #if !YF_Hosted
116 yunused(key);
117 #endif
118 #if YCL_DS
119 yunused(opt);
120 try
121 {
122 if(off != 0)
123 YCL_CallF_CAPI(, ::lseek, *file.get(), ::off_t(off), SEEK_SET);
124 YCL_CallF_CAPI(, ::read, *file.get(), GetPtr(), len);
125 }
126 CatchExpr(...,
127 std::throw_with_nested(std::runtime_error("Mapping failed.")))
128 #endif
129 }
130 MappedFile::MappedFile(size_t len, UniqueFile f,
131 FileMappingOption opt, FileMappingKey key)
132 : MappedFile(std::uint64_t(0), len, std::move(f), opt, key)
133 {}
134 MappedFile::MappedFile(UniqueFile f, FileMappingOption opt, FileMappingKey key)
135 : MappedFile([&]{
136 if(f)
137 {
138 const auto s(ystdex::not_widen<size_t>(f->GetSize()));
139
140 return pair<size_t, UniqueFile>(s, std::move(f));
141 }
142 ystdex::throw_error(std::errc::bad_file_descriptor, yfsig);
143 }(), opt, key)
144 {}
145 MappedFile::MappedFile(const char* path, FileMappingOption opt,
146 FileMappingKey key)
147 : MappedFile([&]{
148 if(UniqueFile ufile{uopen(path, int((opt == FileMappingOption::ReadOnly
149 ? OpenMode::Read : OpenMode::ReadWrite) | OpenMode::Binary)
150 )})
151 return ufile;
152 YCL_Raise_SysE(, "Failed opening file", yfsig);
153 }(), opt, key)
154 {}
155 MappedFile::~MappedFile()
156 {
157 if(*this)
158 {
159 // NOTE: At least POSIX specifiy nothing about mandontory of flush on
160 // unmapping.
161 // NOTE: Windows will only flush when all shared mapping are closed, see
162 // https://msdn.microsoft.com/en-us/library/windows/desktop/aa366532(v=vs.85).aspx
163 // TODO: Simplified without exceptions?
164 TryExpr(Flush())
165 CatchExpr(std::exception& e, YTraceDe(Descriptions::Err,
166 "Failed flushing mapped file: %s.", e.what()))
167 CatchExpr(..., YTraceDe(Descriptions::Err,
168 "Failed flushing mapped file."));
169 }
170 }
171
172 void
173 MappedFile::FlushView()
174 {
175 YAssertNonnull(GetPtr());
176
177 #if YCL_DS
178 // NOTE: Nothing to do to flush the view.
179 #elif YCL_Win32
180 YCL_CallF_Win32(::FlushViewOfFile, GetPtr(), GetSize());
181 // NOTE: It should be noted %::FlushFileBuffers is required to flush file
182 // buffer, but this will be called in file descriptor flush below.
183 #else
184 // NOTE: It is unspecified that whether data in %MAP_PRIVATE mappings has
185 // any permanent storage locations, see http://pubs.opengroup.org/onlinepubs/9699919799/functions/msync.html.
186 // NOTE: To notify the system scheduling at first. See https://jira.mongodb.org/browse/SERVER-12733.
187 YCL_CallF_CAPI(, ::msync, GetPtr(), GetSize(), MS_ASYNC);
188 YCL_CallF_CAPI(, ::msync, GetPtr(), GetSize(), MS_SYNC);
189 #endif
190 }
191
192 void
193 MappedFile::FlushFile()
194 {
195 YAssertNonnull(file);
196
197 if(option != FileMappingOption::ReadOnly)
198 // XXX: In POSIX this is perhapers not required, but keeping uniformed
199 // behavior is better. See https://groups.google.com/forum/#!topic/comp.unix.programmer/pIiaQ6CUKjU
200 // XXX: This would cause bad performance for some versions of Windows
201 // supported by this project, see https://jira.mongodb.org/browse/SERVER-12401.
202 file->Flush();
203 }
204
205 } // namespace platform;
206
YTraceDe
#define YTraceDe(...)
YCLib 默认调试跟踪。
Definition: Debug.h:313
platform::path
_tString && path
Definition: YCLib/FileSystem.h:285
platform::MappedFile::UniqueFile
file option mapped const UniqueFile UniqueFile
Definition: MemoryMapping.h:211
platform::UnmapDelete::pointer
byte * pointer
Definition: MemoryMapping.h:77
platform::MappedFile::FlushFile
file option mapped const UniqueFile file FlushFile()) void FlushView()
刷新映射视图。
Definition: MemoryMapping.cpp:193
cast.hpp
C++ 转换模板。
platform
默认平台命名空间。
Definition: Container.h:47
platform::MappedFile::mapped
unique_ptr< byte[], UnmapDelete > mapped
Definition: MemoryMapping.h:119
yfsig
#define yfsig
展开为表示函数签名的预定义变量的宏。
Definition: ydef.h:728
platform::FileMappingOption::ReadOnly
CHRLib::f
f(d, s)
platform::MappedFile::file
UniqueFile file
Definition: MemoryMapping.h:117
platform::MappedFile::option
FileMappingOption option
Definition: MemoryMapping.h:115
YCL_DS
#define YCL_DS
Definition: Platform.h:332
YAssertNonnull
#define YAssertNonnull(_expr)
Definition: cassert.h:120
platform::UniqueFile
unique_ptr_from< FileDescriptor::Deleter > UniqueFile
Definition: FileIO.h:464
YCL_CallF_Win32
#define YCL_CallF_Win32(_fn,...)
Definition: MinGW32.h:190
YCL_Raise_SysE
#define YCL_Raise_SysE(_t, _msg, _sig)
按错误值和指定参数抛出第一参数指定类型的对象。
Definition: FileIO.h:1178
platform::MappedFile::MappedFile
MappedFile(pair< size_t, UniqueFile > pr, FileMappingOption opt, FileMappingKey key)
以指定的区域长度、文件、选项和键创建映射。
Definition: MemoryMapping.h:158
platform::uopen
int uopen(const char *filename, int oflag, mode_t pmode) ynothrowv
Definition: FileIO.cpp:873
TryExpr
#define TryExpr(...)
指定表达式在 try 块中求值。
Definition: YBaseMacro.h:120
mapped
MappedFile mapped
Definition: Initialization.cpp:224
ystdex::throw_error
void throw_error(std::error_code ec, _tParams &&...args)
抛出错误： std::system_error 或允许相同构造函数参数的异常。
Definition: ystdex/exception.h:206
platform::FileMappingOption
FileMappingOption
文件映射选项。
Definition: MemoryMapping.h:44
CatchExpr
#define CatchExpr(_ex,...)
指定表达式作为异常处理器。
Definition: YBaseMacro.h:129
CHRLib::s
_tDst const _tSrc * s
Definition: CharacterProcessing.h:140
platform::UnmapDelete::operator()
void operator()(pointer) const ynothrow
Definition: MemoryMapping.cpp:48
platform::if
if(!p) p
platform::FileMappingOption::ReadWrite
YModules.h
yunused
#define yunused(...)
标记未使用的表达式。
Definition: ydef.h:968
CHRLib::e
const char const char * e
Definition: CharacterProcessing.h:109
ystdex::pseudo_output
伪输出对象。
Definition: ref.hpp:307
std
Definition: memory.hpp:1183
platform::FileMappingKey
ystdex::pseudo_output FileMappingKey
文件映射键类型。
Definition: MemoryMapping.h:60
ystdex::byte
unsigned char byte
字节类型。
Definition: ydef.h:834
platform::Descriptions::Err
Definition: YCommon.h:166
platform::MappedFile
只读内存映射文件。
Definition: MemoryMapping.h:111
platform::FileMappingOption::CopyOnWrite
ystdex::size
auto size(const _tRange &c) -> decltype(c.size())
类容器访问。
Definition: range.hpp:233
YCL_CallF_CAPI
#define YCL_CallF_CAPI(_t, _fn,...)
Definition: FileIO.h:1237
CHRLib::p
const auto p(d)
platform::ynothrow
const _tString &path ynothrow
Definition: YCLib/FileSystem.h:274