YSTest: MemoryMapping.cpp 源文件

YSTest PreAlpha_b900_20201012 The YSLib Test Project

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