mirror of
https://github.com/mutouyun/cpp-ipc.git
synced 2025-12-06 16:56: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