Skip to content

Commit 415be36

Browse files
committed
ipc::sync::mutex for linux
1 parent 1dc0419 commit 415be36

File tree

3 files changed

+72
-33
lines changed

3 files changed

+72
-33
lines changed

src/libipc/memory/resource.h

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,14 +45,17 @@ constexpr char const * pf(long double) { return "%Lf" ; }
4545

4646
} // internal-linkage
4747

48+
template <typename T>
49+
struct hash : public std::hash<T> {};
50+
4851
template <typename Key, typename T>
4952
using unordered_map = std::unordered_map<
50-
Key, T, std::hash<Key>, std::equal_to<Key>, ipc::mem::allocator<std::pair<const Key, T>>
53+
Key, T, ipc::hash<Key>, std::equal_to<Key>, ipc::mem::allocator<std::pair<Key const, T>>
5154
>;
5255

5356
template <typename Key, typename T>
5457
using map = std::map<
55-
Key, T, std::less<Key>, ipc::mem::allocator<std::pair<const Key, T>>
58+
Key, T, std::less<Key>, ipc::mem::allocator<std::pair<Key const, T>>
5659
>;
5760

5861
template <typename Char>
@@ -63,6 +66,18 @@ using basic_string = std::basic_string<
6366
using string = basic_string<char>;
6467
using wstring = basic_string<wchar_t>;
6568

69+
template <> struct hash<string> {
70+
std::size_t operator()(string const &val) const noexcept {
71+
return std::hash<char const *>{}(val.c_str());
72+
}
73+
};
74+
75+
template <> struct hash<wstring> {
76+
std::size_t operator()(wstring const &val) const noexcept {
77+
return std::hash<wchar_t const *>{}(val.c_str());
78+
}
79+
};
80+
6681
template <typename T>
6782
ipc::string to_string(T val) {
6883
char buf[std::numeric_limits<T>::digits10 + 1] {};

src/libipc/platform/mutex_linux.h

Lines changed: 54 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,15 @@
33
#include <cstring>
44
#include <cassert>
55
#include <system_error>
6+
#include <mutex>
67

78
#include <pthread.h>
89

910
#include "libipc/platform/get_wait_time.h"
1011
#include "libipc/platform/detail.h"
1112
#include "libipc/utility/log.h"
1213
#include "libipc/utility/scope_guard.h"
14+
#include "libipc/memory/resource.h"
1315
#include "libipc/shm.h"
1416

1517
namespace ipc {
@@ -20,6 +22,32 @@ class mutex {
2022
ipc::shm::handle shm_;
2123
pthread_mutex_t *mutex_ = nullptr;
2224

25+
pthread_mutex_t *acquire_mutex(char const *name) {
26+
if (!shm_.acquire(name, sizeof(pthread_mutex_t))) {
27+
ipc::error("fail shm.acquire: %s\n", name);
28+
return nullptr;
29+
}
30+
return static_cast<pthread_mutex_t *>(shm_.get());
31+
}
32+
33+
pthread_mutex_t *get_mutex(char const *name) {
34+
if (name == nullptr) {
35+
return nullptr;
36+
}
37+
static ipc::map<ipc::string, pthread_mutex_t *> mutex_handles;
38+
static std::mutex lock;
39+
IPC_UNUSED_ std::lock_guard<std::mutex> guard {lock};
40+
auto it = mutex_handles.find(name);
41+
if (it == mutex_handles.end()) {
42+
auto ptr = acquire_mutex(name);
43+
if (ptr != nullptr) {
44+
mutex_handles.emplace(name, ptr);
45+
}
46+
return ptr;
47+
}
48+
return it->second;
49+
}
50+
2351
public:
2452
mutex() = default;
2553
explicit mutex(char const *name) noexcept {
@@ -38,45 +66,41 @@ class mutex {
3866

3967
bool valid() const noexcept {
4068
static const char tmp[sizeof(pthread_mutex_t)] {};
41-
return shm_.valid()
42-
&& (mutex_ != nullptr)
69+
return (mutex_ != nullptr)
4370
&& (std::memcmp(tmp, mutex_, sizeof(pthread_mutex_t)) != 0);
4471
}
4572

4673
bool open(char const *name) noexcept {
4774
close();
48-
if (!shm_.acquire(name, sizeof(pthread_mutex_t))) {
49-
ipc::error("fail shm.acquire: %s\n", name);
75+
if ((mutex_ = get_mutex(name)) == nullptr) {
5076
return false;
5177
}
52-
mutex_ = static_cast<pthread_mutex_t *>(shm_.get());
53-
assert(mutex_ != nullptr);
54-
if ((shm_.ref() == 1) && valid()/*it means mutex has been inited*/) {
78+
if (shm_.ref() == 1) {
5579
::pthread_mutex_destroy(mutex_);
80+
auto finally = ipc::guard([this] { close(); }); // close when failed
81+
// init mutex
82+
int eno;
83+
pthread_mutexattr_t mutex_attr;
84+
if ((eno = ::pthread_mutexattr_init(&mutex_attr)) != 0) {
85+
ipc::error("fail pthread_mutexattr_init[%d]\n", eno);
86+
return false;
87+
}
88+
IPC_UNUSED_ auto guard_mutex_attr = unique_ptr(&mutex_attr, ::pthread_mutexattr_destroy);
89+
if ((eno = ::pthread_mutexattr_setpshared(&mutex_attr, PTHREAD_PROCESS_SHARED)) != 0) {
90+
ipc::error("fail pthread_mutexattr_setpshared[%d]\n", eno);
91+
return false;
92+
}
93+
if ((eno = ::pthread_mutexattr_setrobust(&mutex_attr, PTHREAD_MUTEX_ROBUST)) != 0) {
94+
ipc::error("fail pthread_mutexattr_setrobust[%d]\n", eno);
95+
return false;
96+
}
97+
*mutex_ = PTHREAD_MUTEX_INITIALIZER;
98+
if ((eno = ::pthread_mutex_init(mutex_, &mutex_attr)) != 0) {
99+
ipc::error("fail pthread_mutex_init[%d]\n", eno);
100+
return false;
101+
}
102+
finally.dismiss();
56103
}
57-
auto finally = ipc::guard([this] { close(); }); // close when failed
58-
// init mutex
59-
int eno;
60-
pthread_mutexattr_t mutex_attr;
61-
if ((eno = ::pthread_mutexattr_init(&mutex_attr)) != 0) {
62-
ipc::error("fail pthread_mutexattr_init[%d]\n", eno);
63-
return false;
64-
}
65-
IPC_UNUSED_ auto guard_mutex_attr = unique_ptr(&mutex_attr, ::pthread_mutexattr_destroy);
66-
if ((eno = ::pthread_mutexattr_setpshared(&mutex_attr, PTHREAD_PROCESS_SHARED)) != 0) {
67-
ipc::error("fail pthread_mutexattr_setpshared[%d]\n", eno);
68-
return false;
69-
}
70-
if ((eno = ::pthread_mutexattr_setrobust(&mutex_attr, PTHREAD_MUTEX_ROBUST)) != 0) {
71-
ipc::error("fail pthread_mutexattr_setrobust[%d]\n", eno);
72-
return false;
73-
}
74-
*mutex_ = PTHREAD_MUTEX_INITIALIZER;
75-
if ((eno = ::pthread_mutex_init(mutex_, &mutex_attr)) != 0) {
76-
ipc::error("fail pthread_mutex_init[%d]\n", eno);
77-
return false;
78-
}
79-
finally.dismiss();
80104
return valid();
81105
}
82106

test/test_sync.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
TEST(PThread, Robust) {
1515
pthread_mutexattr_t ma;
1616
pthread_mutexattr_init(&ma);
17+
pthread_mutexattr_setpshared(&ma, PTHREAD_PROCESS_SHARED);
1718
pthread_mutexattr_setrobust(&ma, PTHREAD_MUTEX_ROBUST);
1819
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
1920
pthread_mutex_init(&mutex, &ma);
@@ -55,7 +56,6 @@ TEST(PThread, Robust) {
5556
TEST(Sync, Mutex) {
5657
ipc::sync::mutex lock;
5758
EXPECT_TRUE(lock.open("test-mutex-robust"));
58-
5959
std::thread{[] {
6060
ipc::sync::mutex lock{"test-mutex-robust"};
6161
EXPECT_TRUE(lock.valid());

0 commit comments

Comments
 (0)