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 KV_DB_REF_OBJECT_H
17 #define KV_DB_REF_OBJECT_H
18 
19 #include <atomic>
20 #include <condition_variable>
21 #include <functional>
22 #include <mutex>
23 #include <string>
24 
25 #include "macro_utils.h"
26 
27 namespace DistributedDB {
28 class RefObject {
29 public:
30     class AutoLock final {
31     public:
32         explicit AutoLock(const RefObject *obj, bool unlocked = true);
33         ~AutoLock();
34         void Lock();
35         void Unlock();
36 
37     private:
38         DISABLE_COPY_ASSIGN_MOVE(AutoLock);
39         const RefObject *refObj_;
40         bool isLocked_;
41     };
42 
43     RefObject();
44 
45     /* Invoked before this object deleted. */
46     void OnLastRef(const std::function<void(void)> &callback) const;
47 
48     /* Invoked when kill object, with lock held. */
49     void OnKill(const std::function<void(void)> &callback);
50 
51     bool IsKilled() const;
52     void KillObj();
53     void LockObj() const;
54     void UnlockObj() const;
55     bool WaitLockedUntil(std::condition_variable &cv,
56         const std::function<bool(void)> &condition, int seconds = 0);
57 
58     /* Work as static members, avoid to 'delete this' */
59     static void IncObjRef(const RefObject *obj);
60     static void DecObjRef(const RefObject *obj);
61     static void KillAndDecObjRef(RefObject *obj);
62 
63 protected:
64     virtual ~RefObject();
65     virtual std::string GetObjectTag() const;
66 
67 private:
68     constexpr static const char * const classTag = "Class-RefObject";
69 
70     DISABLE_COPY_ASSIGN_MOVE(RefObject);
71 
72     /* A const object can also be locked/unlocked/ref()/unref() */
73     mutable std::atomic<int> refCount_;
74     mutable std::mutex objLock_;
75     std::atomic<bool> isKilled_;
76     mutable std::function<void(void)> onLast_;
77     std::function<void(void)> onKill_;
78 };
79 } // namespace DistributedDB
80 
81 #endif // KV_DB_REF_OBJECT_H
82