mirror of
https://github.com/mutouyun/cpp-ipc.git
synced 2026-02-08 10:46:42 +08:00
ipc::sync::mutex for linux
This commit is contained in:
parent
1dc0419865
commit
415be36477
@ -45,14 +45,17 @@ constexpr char const * pf(long double) { return "%Lf" ; }
|
|||||||
|
|
||||||
} // internal-linkage
|
} // internal-linkage
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct hash : public std::hash<T> {};
|
||||||
|
|
||||||
template <typename Key, typename T>
|
template <typename Key, typename T>
|
||||||
using unordered_map = std::unordered_map<
|
using unordered_map = std::unordered_map<
|
||||||
Key, T, std::hash<Key>, std::equal_to<Key>, ipc::mem::allocator<std::pair<const Key, T>>
|
Key, T, ipc::hash<Key>, std::equal_to<Key>, ipc::mem::allocator<std::pair<Key const, T>>
|
||||||
>;
|
>;
|
||||||
|
|
||||||
template <typename Key, typename T>
|
template <typename Key, typename T>
|
||||||
using map = std::map<
|
using map = std::map<
|
||||||
Key, T, std::less<Key>, ipc::mem::allocator<std::pair<const Key, T>>
|
Key, T, std::less<Key>, ipc::mem::allocator<std::pair<Key const, T>>
|
||||||
>;
|
>;
|
||||||
|
|
||||||
template <typename Char>
|
template <typename Char>
|
||||||
@ -63,6 +66,18 @@ using basic_string = std::basic_string<
|
|||||||
using string = basic_string<char>;
|
using string = basic_string<char>;
|
||||||
using wstring = basic_string<wchar_t>;
|
using wstring = basic_string<wchar_t>;
|
||||||
|
|
||||||
|
template <> struct hash<string> {
|
||||||
|
std::size_t operator()(string const &val) const noexcept {
|
||||||
|
return std::hash<char const *>{}(val.c_str());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <> struct hash<wstring> {
|
||||||
|
std::size_t operator()(wstring const &val) const noexcept {
|
||||||
|
return std::hash<wchar_t const *>{}(val.c_str());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
ipc::string to_string(T val) {
|
ipc::string to_string(T val) {
|
||||||
char buf[std::numeric_limits<T>::digits10 + 1] {};
|
char buf[std::numeric_limits<T>::digits10 + 1] {};
|
||||||
|
|||||||
@ -3,6 +3,7 @@
|
|||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <system_error>
|
#include <system_error>
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
|
|
||||||
@ -10,6 +11,7 @@
|
|||||||
#include "libipc/platform/detail.h"
|
#include "libipc/platform/detail.h"
|
||||||
#include "libipc/utility/log.h"
|
#include "libipc/utility/log.h"
|
||||||
#include "libipc/utility/scope_guard.h"
|
#include "libipc/utility/scope_guard.h"
|
||||||
|
#include "libipc/memory/resource.h"
|
||||||
#include "libipc/shm.h"
|
#include "libipc/shm.h"
|
||||||
|
|
||||||
namespace ipc {
|
namespace ipc {
|
||||||
@ -20,6 +22,32 @@ class mutex {
|
|||||||
ipc::shm::handle shm_;
|
ipc::shm::handle shm_;
|
||||||
pthread_mutex_t *mutex_ = nullptr;
|
pthread_mutex_t *mutex_ = nullptr;
|
||||||
|
|
||||||
|
pthread_mutex_t *acquire_mutex(char const *name) {
|
||||||
|
if (!shm_.acquire(name, sizeof(pthread_mutex_t))) {
|
||||||
|
ipc::error("fail shm.acquire: %s\n", name);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return static_cast<pthread_mutex_t *>(shm_.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_mutex_t *get_mutex(char const *name) {
|
||||||
|
if (name == nullptr) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
static ipc::map<ipc::string, pthread_mutex_t *> mutex_handles;
|
||||||
|
static std::mutex lock;
|
||||||
|
IPC_UNUSED_ std::lock_guard<std::mutex> guard {lock};
|
||||||
|
auto it = mutex_handles.find(name);
|
||||||
|
if (it == mutex_handles.end()) {
|
||||||
|
auto ptr = acquire_mutex(name);
|
||||||
|
if (ptr != nullptr) {
|
||||||
|
mutex_handles.emplace(name, ptr);
|
||||||
|
}
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
return it->second;
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
mutex() = default;
|
mutex() = default;
|
||||||
explicit mutex(char const *name) noexcept {
|
explicit mutex(char const *name) noexcept {
|
||||||
@ -38,45 +66,41 @@ public:
|
|||||||
|
|
||||||
bool valid() const noexcept {
|
bool valid() const noexcept {
|
||||||
static const char tmp[sizeof(pthread_mutex_t)] {};
|
static const char tmp[sizeof(pthread_mutex_t)] {};
|
||||||
return shm_.valid()
|
return (mutex_ != nullptr)
|
||||||
&& (mutex_ != nullptr)
|
|
||||||
&& (std::memcmp(tmp, mutex_, sizeof(pthread_mutex_t)) != 0);
|
&& (std::memcmp(tmp, mutex_, sizeof(pthread_mutex_t)) != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool open(char const *name) noexcept {
|
bool open(char const *name) noexcept {
|
||||||
close();
|
close();
|
||||||
if (!shm_.acquire(name, sizeof(pthread_mutex_t))) {
|
if ((mutex_ = get_mutex(name)) == nullptr) {
|
||||||
ipc::error("fail shm.acquire: %s\n", name);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
mutex_ = static_cast<pthread_mutex_t *>(shm_.get());
|
if (shm_.ref() == 1) {
|
||||||
assert(mutex_ != nullptr);
|
|
||||||
if ((shm_.ref() == 1) && valid()/*it means mutex has been inited*/) {
|
|
||||||
::pthread_mutex_destroy(mutex_);
|
::pthread_mutex_destroy(mutex_);
|
||||||
|
auto finally = ipc::guard([this] { close(); }); // close when failed
|
||||||
|
// init mutex
|
||||||
|
int eno;
|
||||||
|
pthread_mutexattr_t mutex_attr;
|
||||||
|
if ((eno = ::pthread_mutexattr_init(&mutex_attr)) != 0) {
|
||||||
|
ipc::error("fail pthread_mutexattr_init[%d]\n", eno);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
IPC_UNUSED_ auto guard_mutex_attr = unique_ptr(&mutex_attr, ::pthread_mutexattr_destroy);
|
||||||
|
if ((eno = ::pthread_mutexattr_setpshared(&mutex_attr, PTHREAD_PROCESS_SHARED)) != 0) {
|
||||||
|
ipc::error("fail pthread_mutexattr_setpshared[%d]\n", eno);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ((eno = ::pthread_mutexattr_setrobust(&mutex_attr, PTHREAD_MUTEX_ROBUST)) != 0) {
|
||||||
|
ipc::error("fail pthread_mutexattr_setrobust[%d]\n", eno);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*mutex_ = PTHREAD_MUTEX_INITIALIZER;
|
||||||
|
if ((eno = ::pthread_mutex_init(mutex_, &mutex_attr)) != 0) {
|
||||||
|
ipc::error("fail pthread_mutex_init[%d]\n", eno);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
finally.dismiss();
|
||||||
}
|
}
|
||||||
auto finally = ipc::guard([this] { close(); }); // close when failed
|
|
||||||
// init mutex
|
|
||||||
int eno;
|
|
||||||
pthread_mutexattr_t mutex_attr;
|
|
||||||
if ((eno = ::pthread_mutexattr_init(&mutex_attr)) != 0) {
|
|
||||||
ipc::error("fail pthread_mutexattr_init[%d]\n", eno);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
IPC_UNUSED_ auto guard_mutex_attr = unique_ptr(&mutex_attr, ::pthread_mutexattr_destroy);
|
|
||||||
if ((eno = ::pthread_mutexattr_setpshared(&mutex_attr, PTHREAD_PROCESS_SHARED)) != 0) {
|
|
||||||
ipc::error("fail pthread_mutexattr_setpshared[%d]\n", eno);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if ((eno = ::pthread_mutexattr_setrobust(&mutex_attr, PTHREAD_MUTEX_ROBUST)) != 0) {
|
|
||||||
ipc::error("fail pthread_mutexattr_setrobust[%d]\n", eno);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
*mutex_ = PTHREAD_MUTEX_INITIALIZER;
|
|
||||||
if ((eno = ::pthread_mutex_init(mutex_, &mutex_attr)) != 0) {
|
|
||||||
ipc::error("fail pthread_mutex_init[%d]\n", eno);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
finally.dismiss();
|
|
||||||
return valid();
|
return valid();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -14,6 +14,7 @@
|
|||||||
TEST(PThread, Robust) {
|
TEST(PThread, Robust) {
|
||||||
pthread_mutexattr_t ma;
|
pthread_mutexattr_t ma;
|
||||||
pthread_mutexattr_init(&ma);
|
pthread_mutexattr_init(&ma);
|
||||||
|
pthread_mutexattr_setpshared(&ma, PTHREAD_PROCESS_SHARED);
|
||||||
pthread_mutexattr_setrobust(&ma, PTHREAD_MUTEX_ROBUST);
|
pthread_mutexattr_setrobust(&ma, PTHREAD_MUTEX_ROBUST);
|
||||||
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
|
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||||
pthread_mutex_init(&mutex, &ma);
|
pthread_mutex_init(&mutex, &ma);
|
||||||
@ -55,7 +56,6 @@ TEST(PThread, Robust) {
|
|||||||
TEST(Sync, Mutex) {
|
TEST(Sync, Mutex) {
|
||||||
ipc::sync::mutex lock;
|
ipc::sync::mutex lock;
|
||||||
EXPECT_TRUE(lock.open("test-mutex-robust"));
|
EXPECT_TRUE(lock.open("test-mutex-robust"));
|
||||||
|
|
||||||
std::thread{[] {
|
std::thread{[] {
|
||||||
ipc::sync::mutex lock{"test-mutex-robust"};
|
ipc::sync::mutex lock{"test-mutex-robust"};
|
||||||
EXPECT_TRUE(lock.valid());
|
EXPECT_TRUE(lock.valid());
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user