OmniSciDB  72c90bc290
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
RWLocks.h
Go to the documentation of this file.
1 /*
2  * Copyright 2022 HEAVY.AI, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef RW_LOCKS_H
18 #define RW_LOCKS_H
19 
22 
23 #include <atomic>
24 #include <thread>
25 
26 namespace Catalog_Namespace {
27 
28 /*
29  * The locking sequence for the locks below is as follows:
30  *
31  * inter catalog / syscatalog it is always
32  *
33  * read or write lock, then the sqlite_lock (if required)
34  *
35  * intra catalog and syscatalog
36  *
37  * always syscatalog locks (if required), then catalog locks
38  */
39 
40 template <typename T>
41 class read_lock {
42  const T* catalog;
45  bool holds_lock;
46 
47  template <typename inner_type>
48  void lock_catalog(const inner_type* cat) {
49  std::thread::id tid = std::this_thread::get_id();
50 
51  if (cat->thread_holding_write_lock != tid && !inner_type::thread_holds_read_lock) {
52  if (!g_multi_instance) {
54  } else {
55  dlock =
57  }
58  inner_type::thread_holds_read_lock = true;
59  holds_lock = true;
60  }
61  }
62 
63  public:
64  read_lock(const T* cat) : catalog(cat), holds_lock(false) { lock_catalog(cat); }
65 
66  ~read_lock() { unlock(); }
67 
68  void unlock() {
69  if (holds_lock) {
70  T::thread_holds_read_lock = false;
71  if (!g_multi_instance) {
72  lock.unlock();
73  } else {
74  dlock.unlock();
75  }
76  holds_lock = false;
77  }
78  }
79 };
80 
81 template <typename T>
82 class sqlite_lock {
83  // always obtain a read lock on catalog first
84  // to ensure correct locking order
86  const T* catalog;
89  bool holds_lock;
90 
91  template <typename inner_type>
92  void lock_catalog(const inner_type* cat) {
93  std::thread::id tid = std::this_thread::get_id();
94 
95  if (cat->thread_holding_sqlite_lock != tid) {
96  if (!g_multi_instance) {
97  lock = heavyai::unique_lock<std::mutex>(cat->sqliteMutex_);
98  } else {
99  dlock =
101  }
102  cat->thread_holding_sqlite_lock = tid;
103  holds_lock = true;
104  }
105  }
106 
107  public:
109  lock_catalog(cat);
110  }
111 
113 
114  void unlock() {
115  if (holds_lock) {
116  std::thread::id no_thread;
117  catalog->thread_holding_sqlite_lock = no_thread;
118  if (!g_multi_instance) {
119  lock.unlock();
120  } else {
121  dlock.unlock();
122  }
124  holds_lock = false;
125  }
126  }
127 };
128 
129 template <typename T>
130 class write_lock {
131  const T* catalog;
135 
136  template <typename inner_type>
137  void lock_catalog(const inner_type* cat) {
138  std::thread::id tid = std::this_thread::get_id();
139 
140  if (cat->thread_holding_write_lock != tid) {
141  if (!g_multi_instance) {
143  } else {
144  dlock =
146  }
147  cat->thread_holding_write_lock = tid;
148  holds_lock = true;
149  }
150  }
151 
152  public:
153  write_lock(const T* cat) : catalog(cat), holds_lock(false) { lock_catalog(cat); }
154 
156 
157  void unlock() {
158  if (holds_lock) {
159  std::thread::id no_thread;
160  catalog->thread_holding_write_lock = no_thread;
161  if (!g_multi_instance) {
162  lock.unlock();
163  } else {
164  dlock.unlock();
165  }
166  holds_lock = false;
167  }
168  }
169 };
170 
171 } // namespace Catalog_Namespace
172 
173 #endif // RW_LOCKS_H
bool g_multi_instance
Definition: heavyai_locks.h:22
std::string cat(Ts &&...args)
void lock_catalog(const inner_type *cat)
Definition: RWLocks.h:137
std::shared_lock< T > shared_lock
write_lock(const T *cat)
Definition: RWLocks.h:153
heavyai::unique_lock< heavyai::DistributedSharedMutex > dlock
Definition: RWLocks.h:133
read_lock(const T *cat)
Definition: RWLocks.h:64
std::unique_lock< T > unique_lock
heavyai::shared_lock< heavyai::DistributedSharedMutex > dlock
Definition: RWLocks.h:44
heavyai::unique_lock< heavyai::shared_mutex > lock
Definition: RWLocks.h:132
read_lock< T > cat_read_lock
Definition: RWLocks.h:85
void lock_catalog(const inner_type *cat)
Definition: RWLocks.h:48
bool g_enable_watchdog false
Definition: Execute.cpp:80
heavyai::unique_lock< heavyai::DistributedSharedMutex > dlock
Definition: RWLocks.h:88
heavyai::shared_lock< heavyai::shared_mutex > lock
Definition: RWLocks.h:43
heavyai::unique_lock< std::mutex > lock
Definition: RWLocks.h:87
void lock_catalog(const inner_type *cat)
Definition: RWLocks.h:92