15
15
#include " libimp/system.h"
16
16
#include " libimp/codecvt.h"
17
17
#include " libimp/span.h"
18
+ #include " libimp/detect_plat.h"
18
19
19
20
#include " libipc/def.h"
20
21
@@ -33,10 +34,10 @@ inline tstring to_tstring(std::string const &str) {
33
34
}
34
35
35
36
/* *
36
- * \brief Create a SECURITY_ATTRIBUTES structure singleton
37
+ * \brief Creates or opens a SECURITY_ATTRIBUTES structure singleton
37
38
* \see https://docs.microsoft.com/en-us/previous-versions/windows/desktop/legacy/aa379560(v=vs.85)
38
39
*/
39
- inline LPSECURITY_ATTRIBUTES get_sa () {
40
+ inline LPSECURITY_ATTRIBUTES get_security_descriptor () {
40
41
static struct initiator {
41
42
42
43
SECURITY_DESCRIPTOR sd_;
@@ -46,7 +47,7 @@ inline LPSECURITY_ATTRIBUTES get_sa() {
46
47
47
48
initiator () {
48
49
using namespace ::LIBIMP;
49
- LIBIMP_LOG_ (" get_sa " );
50
+ LIBIMP_LOG_ (" get_security_descriptor " );
50
51
if (!::InitializeSecurityDescriptor (&sd_, SECURITY_DESCRIPTOR_REVISION)) {
51
52
log .error (" failed: InitializeSecurityDescriptor(SECURITY_DESCRIPTOR_REVISION). "
52
53
" error = " , sys::error ());
@@ -96,7 +97,7 @@ inline result<void> close_handle(HANDLE h) noexcept {
96
97
*
97
98
* \return File mapping object HANDLE, NULL on error.
98
99
*/
99
- inline result<HANDLE> mmap_open (std::string const &file, std::size_t size, mode::type type) noexcept {
100
+ inline result<HANDLE> open_file_mapping (std::string const &file, std::size_t size, mode::type type) noexcept {
100
101
LIBIMP_LOG_ ();
101
102
if (file.empty ()) {
102
103
log .error (" file name is empty." );
@@ -121,7 +122,7 @@ inline result<HANDLE> mmap_open(std::string const &file, std::size_t size, mode:
121
122
122
123
// Creates or opens a named or unnamed file mapping object for a specified file.
123
124
auto try_create = [&]() -> result<HANDLE> {
124
- HANDLE h = ::CreateFileMapping (INVALID_HANDLE_VALUE, winapi::get_sa (), PAGE_READWRITE | SEC_COMMIT,
125
+ HANDLE h = ::CreateFileMapping (INVALID_HANDLE_VALUE, winapi::get_security_descriptor (), PAGE_READWRITE | SEC_COMMIT,
125
126
// / \remark dwMaximumSizeHigh always 0 here.
126
127
0 , static_cast <DWORD>(size), t_name.c_str ());
127
128
if (h == NULL ) {
@@ -159,7 +160,7 @@ inline result<HANDLE> mmap_open(std::string const &file, std::size_t size, mode:
159
160
* \brief Maps a view of a file mapping into the address space of a calling process.
160
161
* \see https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-mapviewoffile
161
162
*/
162
- inline result<LPVOID> mmap_memof (HANDLE h) {
163
+ inline result<LPVOID> address_of_file_mapping (HANDLE h) {
163
164
LIBIMP_LOG_ ();
164
165
if (h == NULL ) {
165
166
log .error (" handle is null." );
@@ -178,7 +179,7 @@ inline result<LPVOID> mmap_memof(HANDLE h) {
178
179
* \brief Retrieves the size about a range of pages in the virtual address space of the calling process.
179
180
* \see https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-virtualquery
180
181
*/
181
- inline result<SIZE_T> mmap_sizeof (LPCVOID mem) {
182
+ inline result<SIZE_T> region_size_of_address (LPCVOID mem) {
182
183
LIBIMP_LOG_ ();
183
184
if (mem == NULL ) {
184
185
log .error (" memory pointer is null." );
@@ -197,7 +198,7 @@ inline result<SIZE_T> mmap_sizeof(LPCVOID mem) {
197
198
* \brief Unmaps a mapped view of a file from the calling process's address space.
198
199
* \see https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-unmapviewoffile
199
200
*/
200
- inline result<void > mmap_release (HANDLE h, LPCVOID mem) {
201
+ inline result<void > close_file_mapping (HANDLE h, LPCVOID mem) {
201
202
LIBIMP_LOG_ ();
202
203
if (h == NULL ) {
203
204
log .error (" handle is null." );
@@ -219,6 +220,8 @@ enum class wait_result {
219
220
timeout
220
221
};
221
222
223
+ LIBIMP_INLINE_CONSTEXPR std::int64_t const infinite_time = -1 ;
224
+
222
225
/* *
223
226
* \brief Waits until the specified object is in the signaled state or the time-out interval elapses.
224
227
* \see https://learn.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-waitforsingleobject
@@ -263,5 +266,79 @@ inline result<wait_result> wait_for_multiple_objects(span<HANDLE const> handles,
263
266
return wait_result::timeout;
264
267
}
265
268
269
+ /* *
270
+ * \brief Retrieves the current value of the performance counter,
271
+ * which is a high resolution (<1us) time stamp that can be used for time-interval measurements.
272
+ * \see https://learn.microsoft.com/en-us/windows/win32/api/profileapi/nf-profileapi-queryperformancecounter
273
+ */
274
+ inline result<std::int64_t > query_performance_counter () noexcept {
275
+ LIBIMP_LOG_ ();
276
+ std::int64_t pc;
277
+ BOOL r = ::QueryPerformanceCounter (reinterpret_cast <LARGE_INTEGER *>(&pc));
278
+ if (!r) {
279
+ auto err = sys::error ();
280
+ log .error (" failed: QueryPerformanceCounter(). error = " , err);
281
+ return err;
282
+ }
283
+ return pc;
284
+ }
285
+
286
+ /* *
287
+ * \brief Creates or opens a named or unnamed mutex object.
288
+ * \see https://learn.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-createmutexa
289
+ * \return Mutex object HANDLE, NULL on error.
290
+ */
291
+ inline result<HANDLE> open_mutex (char const *name, bool initial_owner) noexcept {
292
+ LIBIMP_LOG_ ();
293
+ HANDLE h = ::CreateMutexA (winapi::get_security_descriptor (), initial_owner, name);
294
+ if (h == NULL ) {
295
+ auto err = sys::error ();
296
+ log .error (" failed: CreateMutexA(" , initial_owner, " , " , name, " ). error = " , err);
297
+ return err;
298
+ }
299
+ return h;
300
+ }
301
+
302
+ /* *
303
+ * \brief Releases ownership of the specified mutex object.
304
+ * \see https://docs.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-releasemutex
305
+ */
306
+ inline result<bool > release_mutex (HANDLE h) noexcept {
307
+ LIBIMP_LOG_ ();
308
+ if (::ReleaseMutex (h)) {
309
+ return true ;
310
+ }
311
+ auto err = sys::error ();
312
+ log .error (" failed: ReleaseMutex. error = " , err);
313
+ return err;
314
+ }
315
+
316
+ /* *
317
+ * \brief Locks the mutex, blocks if the mutex is not available.
318
+ * \see https://docs.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-waitforsingleobject
319
+ */
320
+ inline result<bool > wait_mutex (HANDLE h, std::int64_t ms) noexcept {
321
+ LIBIMP_LOG_ ();
322
+ // If the mutex is abandoned, we need to release it and try again.
323
+ for (;;) {
324
+ auto r = winapi::wait_for_single_object (h, ms);
325
+ if (!r) {
326
+ return r.error ();
327
+ }
328
+ if (*r == winapi::wait_result::object_0) {
329
+ return true ;
330
+ }
331
+ if (*r == winapi::wait_result::abandoned) {
332
+ log .info (" failed: WaitForSingleObject(" , ms, " ). The mutex is abandoned, try again." );
333
+ auto rr = release_mutex (h);
334
+ if (rr) {
335
+ continue ;
336
+ }
337
+ return rr.error ();
338
+ }
339
+ return false ;
340
+ }
341
+ }
342
+
266
343
} // namespace winapi
267
344
LIBIPC_NAMESPACE_END_
0 commit comments