Skip to content

Commit 65cb048

Browse files
committed
Refactor mutex implementation for Windows platform
1 parent f38d77b commit 65cb048

File tree

3 files changed

+149
-0
lines changed

3 files changed

+149
-0
lines changed

include/libipc/mutex.h

+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/**
2+
* \file libipc/mutex.h
3+
* \author mutouyun ([email protected])
4+
* \brief A synchronization primitive that can be used to protect shared data
5+
* from being simultaneously accessed by multiple processes.
6+
*/
7+
#pragma once
8+
9+
#include <string>
10+
#include <cstddef>
11+
#include <cstdint>
12+
13+
#include "libimp/export.h"
14+
#include "libimp/result.h"
15+
#include "libimp/span.h"
16+
#include "libimp/byte.h"
17+
18+
#include "libipc/def.h"
19+
20+
LIBIPC_NAMESPACE_BEG_
21+
22+
struct mutex_handle;
23+
using mutex_t = mutex_handle *;
24+
25+
/// \brief Create or open a mutex object based on memory.
26+
LIBIMP_EXPORT ::LIBIMP::result<mutex_t> mutex_open(::LIBIMP::span<::LIBIMP::byte>) noexcept;
27+
28+
/// \brief Close the mutex handle.
29+
/// \note The mutex object will be destroyed when the last handle is closed,
30+
/// and the lifetime of a mutex object needs to be shorter than
31+
/// the memory specified when it is created or opened.
32+
LIBIMP_EXPORT ::LIBIMP::result<void> mutex_close(mutex_t) noexcept;
33+
34+
/// \brief Gets the memory size of the specified mutex.
35+
LIBIMP_EXPORT ::LIBIMP::result<std::size_t> mutex_size(mutex_t) noexcept;
36+
37+
/// \brief Locks the mutex, blocks if the mutex is not available.
38+
LIBIMP_EXPORT ::LIBIMP::result<bool> mutex_lock(mutex_t, std::int64_t ms) noexcept;
39+
40+
/// \brief Tries to lock the mutex, returns if the mutex is not available.
41+
LIBIMP_EXPORT ::LIBIMP::result<bool> mutex_try_lock(mutex_t) noexcept;
42+
43+
/// \brief Unlocks the mutex.
44+
LIBIMP_EXPORT ::LIBIMP::result<bool> mutex_unlock(mutex_t) noexcept;
45+
46+
LIBIPC_NAMESPACE_END_

src/libipc/mutex.cpp

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
2+
#include "libimp/log.h"
3+
4+
#include "libimp/detect_plat.h"
5+
#if defined(LIBIMP_OS_WIN)
6+
# include "libipc/platform/win/mutex_impl.h"
7+
#else
8+
#endif
9+
10+
#if !defined(LIBIMP_OS_LINUX)
11+
LIBIPC_NAMESPACE_BEG_
12+
13+
/// \brief C style mutex access interface implementation.
14+
15+
/// \brief The mutex object.
16+
17+
LIBIPC_NAMESPACE_END_
18+
#endif

src/libipc/platform/win/mutex_impl.h

+85
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
/**
2+
* \file libipc/platform/win/mutex_impl.h
3+
* \author mutouyun ([email protected])
4+
*/
5+
#pragma once
6+
7+
#include "libimp/log.h"
8+
#include "libimp/system.h"
9+
#include "libipc/mutex.h"
10+
11+
#include "api.h"
12+
13+
LIBIPC_NAMESPACE_BEG_
14+
15+
using namespace ::LIBIMP;
16+
17+
struct mutex_handle {
18+
19+
};
20+
21+
namespace winapi {
22+
23+
/**
24+
* \brief Creates or opens a named or unnamed mutex object.
25+
* \see https://learn.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-createmutexa
26+
* \return Mutex object HANDLE, NULL on error.
27+
*/
28+
result<HANDLE> mutex_open_or_create(char const *name, bool initial_owner) noexcept {
29+
LIBIMP_LOG_();
30+
HANDLE h = ::CreateMutexA(winapi::get_sa(), initial_owner, name);
31+
if (h == NULL) {
32+
auto err = sys::error();
33+
log.error("failed: CreateMutexA(", initial_owner, ", ", name, "). error = ", err);
34+
return err;
35+
}
36+
return h;
37+
}
38+
39+
/**
40+
* \brief Releases ownership of the specified mutex object.
41+
* \see https://docs.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-releasemutex
42+
*/
43+
result<bool> mutex_release(HANDLE h) noexcept {
44+
LIBIMP_LOG_();
45+
if (::ReleaseMutex(h)) {
46+
return true;
47+
}
48+
auto err = sys::error();
49+
log.error("failed: ReleaseMutex. error = ", err);
50+
return err;
51+
}
52+
53+
/**
54+
* \brief Locks the mutex, blocks if the mutex is not available.
55+
* \see https://docs.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-waitforsingleobject
56+
*/
57+
result<bool> mutex_wait(HANDLE h, std::int64_t ms) noexcept {
58+
LIBIMP_LOG_();
59+
for (;;) {
60+
auto r = winapi::wait_for_single_object(h, ms);
61+
if (!r) {
62+
return r.error();
63+
}
64+
if (*r == winapi::wait_result::object_0) {
65+
return true;
66+
}
67+
if (*r == winapi::wait_result::abandoned) {
68+
log.info("failed: WaitForSingleObject(", ms, "). The mutex is abandoned, try again.");
69+
auto rr = mutex_release(h);
70+
if (rr) {
71+
continue;
72+
}
73+
return rr.error();
74+
}
75+
return false;
76+
}
77+
}
78+
79+
} // namespace winapi
80+
81+
result<mutex_t> mutex_open(span<::LIBIMP::byte> mem) noexcept {
82+
return {};
83+
}
84+
85+
LIBIPC_NAMESPACE_END_

0 commit comments

Comments
 (0)