mirror of
https://github.com/mutouyun/cpp-ipc.git
synced 2025-12-07 01:06:45 +08:00
Refactor mutex implementation for Windows platform
This commit is contained in:
parent
f38d77beb9
commit
65cb048f59
46
include/libipc/mutex.h
Normal file
46
include/libipc/mutex.h
Normal file
@ -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_
|
||||||
18
src/libipc/mutex.cpp
Normal file
18
src/libipc/mutex.cpp
Normal file
@ -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
|
||||||
85
src/libipc/platform/win/mutex_impl.h
Normal file
85
src/libipc/platform/win/mutex_impl.h
Normal file
@ -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_
|
||||||
Loading…
x
Reference in New Issue
Block a user