1 /** 2 * Copyright (c) 2021-2022 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_VERIFIER_SYNCHRONIZED_HPP_ 17 #define PANDA_VERIFIER_SYNCHRONIZED_HPP_ 18 19 #include "verification/util/callable.h" 20 21 #include "libpandabase/os/mutex.h" 22 23 #include "macros.h" 24 25 #include <utility> 26 27 namespace panda::verifier { 28 template <class C, class Friend1 = C, class Friend2 = C> 29 class Synchronized { 30 struct ConstProxy { 31 ConstProxy() = delete; 32 ConstProxy(const ConstProxy &) = delete; ConstProxyConstProxy33 ConstProxy(ConstProxy &&other) 34 { 35 obj = other.obj; 36 other.obj = nullptr; 37 } 38 const Synchronized *obj; 39 ConstProxy(const Synchronized *param_obj) ACQUIRE_SHARED(obj->rw_lock_) : obj {param_obj} 40 { 41 obj->rw_lock_.ReadLock(); 42 } 43 const C *operator->() const 44 { 45 ASSERT(obj != nullptr); 46 return &obj->c; 47 } 48 ~ConstProxy() RELEASE_SHARED(obj->rw_lock_) 49 { 50 if (obj != nullptr) { 51 obj->rw_lock_.Unlock(); 52 } 53 } 54 }; 55 56 struct Proxy { 57 Proxy() = delete; 58 Proxy(const Proxy &) = delete; ProxyProxy59 Proxy(Proxy &&other) 60 { 61 obj = other.obj; 62 other.obj = nullptr; 63 } 64 Synchronized *obj; 65 Proxy(Synchronized *param_obj) ACQUIRE(obj->rw_lock_) : obj {param_obj} 66 { 67 obj->rw_lock_.WriteLock(); 68 } 69 C *operator->() 70 { 71 ASSERT(obj != nullptr); 72 return &obj->c; 73 } 74 ~Proxy() RELEASE(obj->rw_lock_) 75 { 76 if (obj != nullptr) { 77 obj->rw_lock_.Unlock(); 78 } 79 } 80 }; 81 82 C c; 83 84 // GetObj() should be ideally annotated with REQUIRES/REQUIRES_SHARED and c with GUARDED_BY, but then the current 85 // design of LibCache::FastAPI can't be annotated correctly 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() ACQUIRE(rw_lock_) 97 { 98 rw_lock_.WriteLock(); 99 } 100 ReadLock()101 void ReadLock() ACQUIRE_SHARED(rw_lock_) 102 { 103 rw_lock_.ReadLock(); 104 } 105 Unlock()106 void Unlock() RELEASE_GENERIC(rw_lock_) 107 { 108 rw_lock_.Unlock(); 109 } 110 111 friend Friend1; 112 friend Friend2; 113 114 public: 115 template <typename... Args> Synchronized(Args &&...args)116 Synchronized(Args &&... args) : c(std::forward<Args>(args)...) 117 { 118 } 119 120 ConstProxy operator->() const 121 { 122 return {this}; 123 } 124 125 Proxy operator->() 126 { 127 return {this}; 128 } 129 130 template <typename Handler> Apply(Handler && handler)131 auto Apply(Handler &&handler) 132 { 133 os::memory::WriteLockHolder lock_holder {rw_lock_}; 134 return handler(c); 135 } 136 137 template <typename Handler> Apply(Handler && handler)138 auto Apply(Handler &&handler) const 139 { 140 os::memory::ReadLockHolder lock_holder {rw_lock_}; 141 return handler(c); 142 } 143 144 private: 145 mutable panda::os::memory::RWLock rw_lock_; 146 }; 147 } // namespace panda::verifier 148 149 #endif // !PANDA_VERIFIER_SYNCHRONIZED_HPP_ 150