blob: 4e1455732f34596130e12b7e6fd2bc767d857e20 [file] [log] [blame]
John Park33858a32018-09-28 23:05:48 -07001#ifndef AOS_STL_MUTEX_H_
2#define AOS_STL_MUTEX_H_
Brian Silvermanb073f242014-09-08 16:29:57 -04003
4#include <mutex>
5
John Park398c74a2018-10-20 21:17:39 -07006#include "aos/ipc_lib/aos_sync.h"
John Park33858a32018-09-28 23:05:48 -07007#include "aos/logging/logging.h"
8#include "aos/type_traits/type_traits.h"
9#include "aos/macros.h"
Brian Silvermanb073f242014-09-08 16:29:57 -040010
11namespace aos {
12
13// A mutex with the same API and semantics as ::std::mutex, with the addition of
14// methods for checking if the previous owner died and a constexpr default
15// constructor.
16// Definitely safe to put in SHM.
17// This uses the pthread_mutex semantics for owner-died: once somebody dies with
18// the lock held, anybody else who takes it will see true for owner_died() until
19// one of them calls consistent(). It is an error to call unlock() when
20// owner_died() returns true.
21class stl_mutex {
22 public:
23 constexpr stl_mutex() : native_handle_() {}
24
25 void lock() {
26 const int ret = mutex_grab(&native_handle_);
27 switch (ret) {
28 case 0:
29 break;
30 case 1:
31 owner_died_ = true;
32 break;
33 default:
Austin Schuhf257f3c2019-10-27 21:00:43 -070034 AOS_LOG(FATAL, "mutex_grab(%p) failed with %d\n", &native_handle_, ret);
Brian Silvermanb073f242014-09-08 16:29:57 -040035 }
36 }
37
38 bool try_lock() {
39 const int ret = mutex_trylock(&native_handle_);
40 switch (ret) {
41 case 0:
42 return true;
43 case 1:
44 owner_died_ = true;
45 return true;
46 case 4:
47 return false;
48 default:
Austin Schuhf257f3c2019-10-27 21:00:43 -070049 AOS_LOG(FATAL, "mutex_trylock(%p) failed with %d\n", &native_handle_,
50 ret);
Brian Silvermanb073f242014-09-08 16:29:57 -040051 }
52 }
53
54 void unlock() {
Austin Schuhf257f3c2019-10-27 21:00:43 -070055 AOS_CHECK(!owner_died_);
Brian Silvermanb073f242014-09-08 16:29:57 -040056 mutex_unlock(&native_handle_);
57 }
58
59 typedef aos_mutex *native_handle_type;
60 native_handle_type native_handle() { return &native_handle_; }
61
62 bool owner_died() const { return owner_died_; }
63 void consistent() { owner_died_ = false; }
64
65 private:
66 aos_mutex native_handle_;
67
68 bool owner_died_ = false;
69
70 DISALLOW_COPY_AND_ASSIGN(stl_mutex);
71};
72
73// A mutex with the same API and semantics as ::std::recursive_mutex, with the
74// addition of methods for checking if the previous owner died and a constexpr
75// default constructor.
76// Definitely safe to put in SHM.
77// This uses the pthread_mutex semantics for owner-died: once somebody dies with
78// the lock held, anybody else who takes it will see true for owner_died() until
79// one of them calls consistent(). It is an error to call unlock() or lock()
80// again when owner_died() returns true.
81class stl_recursive_mutex {
82 public:
83 constexpr stl_recursive_mutex() {}
84
85 void lock() {
86 if (mutex_islocked(mutex_.native_handle())) {
Austin Schuhf257f3c2019-10-27 21:00:43 -070087 AOS_CHECK(!owner_died());
Brian Silvermanb073f242014-09-08 16:29:57 -040088 ++recursive_locks_;
89 } else {
90 mutex_.lock();
91 if (mutex_.owner_died()) {
92 recursive_locks_ = 0;
93 } else {
Austin Schuhf257f3c2019-10-27 21:00:43 -070094 AOS_CHECK_EQ(0, recursive_locks_);
Brian Silvermanb073f242014-09-08 16:29:57 -040095 }
96 }
97 }
98 bool try_lock() {
99 if (mutex_islocked(mutex_.native_handle())) {
Austin Schuhf257f3c2019-10-27 21:00:43 -0700100 AOS_CHECK(!owner_died());
Brian Silvermanb073f242014-09-08 16:29:57 -0400101 ++recursive_locks_;
102 return true;
103 } else {
104 if (mutex_.try_lock()) {
105 if (mutex_.owner_died()) {
106 recursive_locks_ = 0;
107 } else {
Austin Schuhf257f3c2019-10-27 21:00:43 -0700108 AOS_CHECK_EQ(0, recursive_locks_);
Brian Silvermanb073f242014-09-08 16:29:57 -0400109 }
110 return true;
111 } else {
112 return false;
113 }
114 }
115 }
116 void unlock() {
117 if (recursive_locks_ == 0) {
118 mutex_.unlock();
119 } else {
120 --recursive_locks_;
121 }
122 }
123
124 typedef stl_mutex::native_handle_type native_handle_type;
125 native_handle_type native_handle() { return mutex_.native_handle(); }
126
127 bool owner_died() const { return mutex_.owner_died(); }
128 void consistent() { mutex_.consistent(); }
129
130 private:
131 stl_mutex mutex_;
132 int recursive_locks_ = 0;
133
134 DISALLOW_COPY_AND_ASSIGN(stl_recursive_mutex);
135};
136
137// Convenient typedefs for various types of locking objects.
138typedef ::std::lock_guard<stl_mutex> mutex_lock_guard;
139typedef ::std::lock_guard<stl_recursive_mutex> recursive_lock_guard;
140typedef ::std::unique_lock<stl_mutex> mutex_unique_lock;
141typedef ::std::unique_lock<stl_recursive_mutex> recursive_unique_lock;
142
143} // namespace aos
144
John Park33858a32018-09-28 23:05:48 -0700145#endif // AOS_STL_MUTEX_H_