-
Notifications
You must be signed in to change notification settings - Fork 352
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Refactor mutex implementation for Windows platform
- Loading branch information
Showing
3 changed files
with
149 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
/** | ||
* \file libipc/mutex.h | ||
* \author mutouyun (orz@orzz.org) | ||
* \brief A synchronization primitive that can be used to protect shared data | ||
* from being simultaneously accessed by multiple processes. | ||
*/ | ||
#pragma once | ||
|
||
#include <string> | ||
#include <cstddef> | ||
#include <cstdint> | ||
|
||
#include "libimp/export.h" | ||
#include "libimp/result.h" | ||
#include "libimp/span.h" | ||
#include "libimp/byte.h" | ||
|
||
#include "libipc/def.h" | ||
|
||
LIBIPC_NAMESPACE_BEG_ | ||
|
||
struct mutex_handle; | ||
using mutex_t = mutex_handle *; | ||
|
||
/// \brief Create or open a mutex object based on memory. | ||
LIBIMP_EXPORT ::LIBIMP::result<mutex_t> mutex_open(::LIBIMP::span<::LIBIMP::byte>) noexcept; | ||
|
||
/// \brief Close the mutex handle. | ||
/// \note The mutex object will be destroyed when the last handle is closed, | ||
/// and the lifetime of a mutex object needs to be shorter than | ||
/// the memory specified when it is created or opened. | ||
LIBIMP_EXPORT ::LIBIMP::result<void> mutex_close(mutex_t) noexcept; | ||
|
||
/// \brief Gets the memory size of the specified mutex. | ||
LIBIMP_EXPORT ::LIBIMP::result<std::size_t> mutex_size(mutex_t) noexcept; | ||
|
||
/// \brief Locks the mutex, blocks if the mutex is not available. | ||
LIBIMP_EXPORT ::LIBIMP::result<bool> mutex_lock(mutex_t, std::int64_t ms) noexcept; | ||
|
||
/// \brief Tries to lock the mutex, returns if the mutex is not available. | ||
LIBIMP_EXPORT ::LIBIMP::result<bool> mutex_try_lock(mutex_t) noexcept; | ||
|
||
/// \brief Unlocks the mutex. | ||
LIBIMP_EXPORT ::LIBIMP::result<bool> mutex_unlock(mutex_t) noexcept; | ||
|
||
LIBIPC_NAMESPACE_END_ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
|
||
#include "libimp/log.h" | ||
|
||
#include "libimp/detect_plat.h" | ||
#if defined(LIBIMP_OS_WIN) | ||
# include "libipc/platform/win/mutex_impl.h" | ||
#else | ||
#endif | ||
|
||
#if !defined(LIBIMP_OS_LINUX) | ||
LIBIPC_NAMESPACE_BEG_ | ||
|
||
/// \brief C style mutex access interface implementation. | ||
|
||
/// \brief The mutex object. | ||
|
||
LIBIPC_NAMESPACE_END_ | ||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
/** | ||
* \file libipc/platform/win/mutex_impl.h | ||
* \author mutouyun (orz@orzz.org) | ||
*/ | ||
#pragma once | ||
|
||
#include "libimp/log.h" | ||
#include "libimp/system.h" | ||
#include "libipc/mutex.h" | ||
|
||
#include "api.h" | ||
|
||
LIBIPC_NAMESPACE_BEG_ | ||
|
||
using namespace ::LIBIMP; | ||
|
||
struct mutex_handle { | ||
|
||
}; | ||
|
||
namespace winapi { | ||
|
||
/** | ||
* \brief Creates or opens a named or unnamed mutex object. | ||
* \see https://learn.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-createmutexa | ||
* \return Mutex object HANDLE, NULL on error. | ||
*/ | ||
result<HANDLE> mutex_open_or_create(char const *name, bool initial_owner) noexcept { | ||
LIBIMP_LOG_(); | ||
HANDLE h = ::CreateMutexA(winapi::get_sa(), initial_owner, name); | ||
if (h == NULL) { | ||
auto err = sys::error(); | ||
log.error("failed: CreateMutexA(", initial_owner, ", ", name, "). error = ", err); | ||
return err; | ||
} | ||
return h; | ||
} | ||
|
||
/** | ||
* \brief Releases ownership of the specified mutex object. | ||
* \see https://docs.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-releasemutex | ||
*/ | ||
result<bool> mutex_release(HANDLE h) noexcept { | ||
LIBIMP_LOG_(); | ||
if (::ReleaseMutex(h)) { | ||
return true; | ||
} | ||
auto err = sys::error(); | ||
log.error("failed: ReleaseMutex. error = ", err); | ||
return err; | ||
} | ||
|
||
/** | ||
* \brief Locks the mutex, blocks if the mutex is not available. | ||
* \see https://docs.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-waitforsingleobject | ||
*/ | ||
result<bool> mutex_wait(HANDLE h, std::int64_t ms) noexcept { | ||
LIBIMP_LOG_(); | ||
for (;;) { | ||
auto r = winapi::wait_for_single_object(h, ms); | ||
if (!r) { | ||
return r.error(); | ||
} | ||
if (*r == winapi::wait_result::object_0) { | ||
return true; | ||
} | ||
if (*r == winapi::wait_result::abandoned) { | ||
log.info("failed: WaitForSingleObject(", ms, "). The mutex is abandoned, try again."); | ||
auto rr = mutex_release(h); | ||
if (rr) { | ||
continue; | ||
} | ||
return rr.error(); | ||
} | ||
return false; | ||
} | ||
} | ||
|
||
} // namespace winapi | ||
|
||
result<mutex_t> mutex_open(span<::LIBIMP::byte> mem) noexcept { | ||
return {}; | ||
} | ||
|
||
LIBIPC_NAMESPACE_END_ |