1 /* 2 * Copyright (c) 2021 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #ifndef PANDA_VERIFICATION_UTIL_SYNCHRONIZED_H_ 17 #define PANDA_VERIFICATION_UTIL_SYNCHRONIZED_H_ 18 19 #include <utility> 20 21 #include "verification/util/callable.h" 22 #include "libpandabase/os/mutex.h" 23 24 #include "macros.h" 25 26 namespace panda::verifier { 27 28 template <class C, class Friend1 = C, class Friend2 = C> 29 class Synchronized { 30 struct ConstProxy { 31 ConstProxy() = delete; 32 ConstProxy(const ConstProxy &) = delete; 33 ConstProxyConstProxy34 ConstProxy(ConstProxy &&other) 35 { 36 obj = other.obj; 37 other.obj = nullptr; 38 } 39 ConstProxyConstProxy40 ConstProxy(const Synchronized *param_obj) : obj {param_obj} {} 41 ~ConstProxyConstProxy42 ~ConstProxy() NO_THREAD_SAFETY_ANALYSIS 43 { 44 if (obj != nullptr) { 45 obj->rw_lock_.Unlock(); 46 } 47 } 48 49 const C *operator->() 50 { 51 ASSERT(obj != nullptr); 52 return &obj->c; 53 } 54 55 const Synchronized *obj; 56 }; 57 58 struct Proxy { 59 Proxy() = delete; 60 Proxy(const Proxy &) = delete; 61 ProxyProxy62 Proxy(Proxy &&other) 63 { 64 obj = other.obj; 65 other.obj = nullptr; 66 } 67 ProxyProxy68 Proxy(Synchronized *param_obj) : obj {param_obj} {} 69 ~ProxyProxy70 ~Proxy() NO_THREAD_SAFETY_ANALYSIS 71 { 72 if (obj != nullptr) { 73 obj->rw_lock_.Unlock(); 74 } 75 } 76 77 C *operator->() 78 { 79 ASSERT(obj != nullptr); 80 return &obj->c; 81 } 82 83 Synchronized *obj; 84 }; 85 GetObj()86 C &GetObj() 87 { 88 return c; 89 } 90 GetObj()91 const C &GetObj() const 92 { 93 return c; 94 } 95 WriteLock()96 void WriteLock() NO_THREAD_SAFETY_ANALYSIS 97 { 98 rw_lock_.WriteLock(); 99 } 100 ReadLock()101 void ReadLock() NO_THREAD_SAFETY_ANALYSIS 102 { 103 rw_lock_.WriteLock(); 104 } 105 Unlock()106 void Unlock() NO_THREAD_SAFETY_ANALYSIS 107 { 108 rw_lock_.Unlock(); 109 } 110 111 C c; 112 113 friend Friend1; 114 friend Friend2; 115 116 public: 117 template <typename... Args> Synchronized(Args &&...args)118 Synchronized(Args &&... args) : c(std::forward<Args>(args)...) 119 { 120 } 121 122 ~Synchronized() = default; 123 DEFAULT_MOVE_SEMANTIC(Synchronized); 124 DEFAULT_COPY_SEMANTIC(Synchronized); 125 126 auto operator-> () const NO_THREAD_SAFETY_ANALYSIS 127 { 128 rw_lock_.ReadLock(); 129 return ConstProxy {this}; 130 } 131 132 auto operator-> () NO_THREAD_SAFETY_ANALYSIS 133 { 134 rw_lock_.WriteLock(); 135 return Proxy {this}; 136 } 137 138 template <typename Handler> operator()139 void operator()(Handler &&handler) NO_THREAD_SAFETY_ANALYSIS 140 { 141 rw_lock_.WriteLock(); 142 handler(Proxy {this}); 143 } 144 145 template <typename Handler> operator()146 void operator()(Handler &&handler) const NO_THREAD_SAFETY_ANALYSIS 147 { 148 rw_lock_.ReadLock(); 149 handler(ConstProxy {this}); 150 } 151 152 private: 153 mutable panda::os::memory::RWLock rw_lock_; 154 }; 155 } // namespace panda::verifier 156 157 #endif // PANDA_VERIFICATION_UTIL_SYNCHRONIZED_H_ 158