1 /** 2 * Copyright (c) 2021-2024 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 ark::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; ConstProxyark::verifier::Synchronized::ConstProxy33 ConstProxy(ConstProxy &&other) 34 { 35 obj = other.obj; 36 other.obj = nullptr; 37 } 38 const Synchronized *obj; // NOLINT(misc-non-private-member-variables-in-classes) 39 explicit ConstProxy(const Synchronized *paramObj) ACQUIRE_SHARED(obj->rwLock_) : obj {paramObj} 40 { 41 obj->rwLock_.ReadLock(); 42 } operator ->() const43 const C *operator->() const 44 { 45 ASSERT(obj != nullptr); 46 return &obj->c_; 47 } 48 ~ConstProxy() RELEASE_SHARED(obj->rwLock_) 49 { 50 if (obj != nullptr) { 51 obj->rwLock_.Unlock(); 52 } 53 } 54 NO_COPY_OPERATOR(ConstProxy); 55 NO_MOVE_OPERATOR(ConstProxy); 56 }; 57 58 struct Proxy { 59 Proxy() = delete; 60 Proxy(const Proxy &) = delete; Proxyark::verifier::Proxy61 Proxy(Proxy &&other) 62 { 63 obj = other.obj; 64 other.obj = nullptr; 65 } 66 Synchronized *obj; // NOLINT(misc-non-private-member-variables-in-classes) 67 explicit Proxy(Synchronized *paramObj) ACQUIRE(obj->rwLock_) : obj {paramObj} 68 { 69 obj->rwLock_.WriteLock(); 70 } operator ->()71 C *operator->() 72 { 73 ASSERT(obj != nullptr); 74 return &obj->c_; 75 } 76 ~Proxy() RELEASE(obj->rwLock_) 77 { 78 if (obj != nullptr) { 79 obj->rwLock_.Unlock(); 80 } 81 } 82 NO_COPY_OPERATOR(Proxy); 83 NO_MOVE_OPERATOR(Proxy); 84 }; 85 86 C c_; 87 88 // GetObj() should be ideally annotated with REQUIRES/REQUIRES_SHARED and c with GUARDED_BY, but then the current 89 // design of LibCache::FastAPI can't be annotated correctly GetObj()90 C &GetObj() 91 { 92 return c_; 93 } 94 GetObj() const95 const C &GetObj() const 96 { 97 return c_; 98 } 99 ACQUIRE(rwLock_)100 void WriteLock() ACQUIRE(rwLock_) 101 { 102 rwLock_.WriteLock(); 103 } 104 ACQUIRE_SHARED(rwLock_)105 void ReadLock() ACQUIRE_SHARED(rwLock_) 106 { 107 rwLock_.ReadLock(); 108 } 109 RELEASE_GENERIC(rwLock_)110 void Unlock() RELEASE_GENERIC(rwLock_) 111 { 112 rwLock_.Unlock(); 113 } 114 115 friend Friend1; 116 friend Friend2; 117 118 public: 119 template <typename... Args> Synchronized(Args &&....args)120 explicit Synchronized(Args &&...args) : c_(std::forward<Args>(args)...) 121 { 122 } 123 operator ->() const124 ConstProxy operator->() const 125 { 126 return ConstProxy(this); 127 } 128 operator ->()129 Proxy operator->() 130 { 131 return Proxy(this); 132 } 133 134 template <typename Handler> Apply(Handler &&handler)135 auto Apply(Handler &&handler) 136 { 137 os::memory::WriteLockHolder lockHolder {rwLock_}; 138 return handler(c_); 139 } 140 141 template <typename Handler> Apply(Handler &&handler) const142 auto Apply(Handler &&handler) const 143 { 144 os::memory::ReadLockHolder lockHolder {rwLock_}; 145 return handler(c_); 146 } 147 148 private: 149 mutable ark::os::memory::RWLock rwLock_; 150 }; 151 } // namespace ark::verifier 152 153 #endif // !PANDA_VERIFIER_SYNCHRONIZED_HPP_ 154