blob: 71bbb334cff38c2fd7310fba9ac811c1c583ec89 [file] [log] [blame]
Andrew Walbran3d2c1972020-04-07 12:24:26 +01001//===------------------SharedCluster.h --------------------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#ifndef utility_SharedCluster_h_
10#define utility_SharedCluster_h_
11
12#include "lldb/Utility/LLDBAssert.h"
13#include "lldb/Utility/SharingPtr.h"
14
15#include "llvm/ADT/SmallPtrSet.h"
16
17#include <mutex>
18
19namespace lldb_private {
20
21namespace imp {
22template <typename T>
23class shared_ptr_refcount : public lldb_private::imp::shared_count {
24public:
25 template <class Y>
26 shared_ptr_refcount(Y *in) : shared_count(0), manager(in) {}
27
28 shared_ptr_refcount() : shared_count(0) {}
29
30 ~shared_ptr_refcount() override {}
31
32 void on_zero_shared() override { manager->DecrementRefCount(); }
33
34private:
35 T *manager;
36};
37
38} // namespace imp
39
40template <class T> class ClusterManager {
41public:
42 ClusterManager() : m_objects(), m_external_ref(0), m_mutex() {}
43
44 ~ClusterManager() {
45 for (typename llvm::SmallPtrSet<T *, 16>::iterator pos = m_objects.begin(),
46 end = m_objects.end();
47 pos != end; ++pos) {
48 T *object = *pos;
49 delete object;
50 }
51
52 // Decrement refcount should have been called on this ClusterManager, and
53 // it should have locked the mutex, now we will unlock it before we destroy
54 // it...
55 m_mutex.unlock();
56 }
57
58 void ManageObject(T *new_object) {
59 std::lock_guard<std::mutex> guard(m_mutex);
60 m_objects.insert(new_object);
61 }
62
63 typename lldb_private::SharingPtr<T> GetSharedPointer(T *desired_object) {
64 {
65 std::lock_guard<std::mutex> guard(m_mutex);
66 m_external_ref++;
67 if (0 == m_objects.count(desired_object)) {
68 lldbassert(false && "object not found in shared cluster when expected");
69 desired_object = nullptr;
70 }
71 }
72 return typename lldb_private::SharingPtr<T>(
73 desired_object, new imp::shared_ptr_refcount<ClusterManager>(this));
74 }
75
76private:
77 void DecrementRefCount() {
78 m_mutex.lock();
79 m_external_ref--;
80 if (m_external_ref == 0)
81 delete this;
82 else
83 m_mutex.unlock();
84 }
85
86 friend class imp::shared_ptr_refcount<ClusterManager>;
87
88 llvm::SmallPtrSet<T *, 16> m_objects;
89 int m_external_ref;
90 std::mutex m_mutex;
91};
92
93} // namespace lldb_private
94
95#endif // utility_SharedCluster_h_