3
3
#include < cstring>
4
4
#include < cassert>
5
5
#include < system_error>
6
+ #include < mutex>
6
7
7
8
#include < pthread.h>
8
9
9
10
#include " libipc/platform/get_wait_time.h"
10
11
#include " libipc/platform/detail.h"
11
12
#include " libipc/utility/log.h"
12
13
#include " libipc/utility/scope_guard.h"
14
+ #include " libipc/memory/resource.h"
13
15
#include " libipc/shm.h"
14
16
15
17
namespace ipc {
@@ -20,6 +22,32 @@ class mutex {
20
22
ipc::shm::handle shm_;
21
23
pthread_mutex_t *mutex_ = nullptr ;
22
24
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
+
23
51
public:
24
52
mutex () = default ;
25
53
explicit mutex (char const *name) noexcept {
@@ -38,45 +66,41 @@ class mutex {
38
66
39
67
bool valid () const noexcept {
40
68
static const char tmp[sizeof (pthread_mutex_t )] {};
41
- return shm_.valid ()
42
- && (mutex_ != nullptr )
69
+ return (mutex_ != nullptr )
43
70
&& (std::memcmp (tmp, mutex_, sizeof (pthread_mutex_t )) != 0 );
44
71
}
45
72
46
73
bool open (char const *name) noexcept {
47
74
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 ) {
50
76
return false ;
51
77
}
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 ) {
55
79
::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 ();
56
103
}
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 ();
80
104
return valid ();
81
105
}
82
106
0 commit comments