• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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