1 //===------------------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 19 namespace lldb_private { 20 21 namespace imp { 22 template <typename T> 23 class shared_ptr_refcount : public lldb_private::imp::shared_count { 24 public: 25 template <class Y> shared_ptr_refcount(Y * in)26 shared_ptr_refcount(Y *in) : shared_count(0), manager(in) {} 27 shared_ptr_refcount()28 shared_ptr_refcount() : shared_count(0) {} 29 ~shared_ptr_refcount()30 ~shared_ptr_refcount() override {} 31 on_zero_shared()32 void on_zero_shared() override { manager->DecrementRefCount(); } 33 34 private: 35 T *manager; 36 }; 37 38 } // namespace imp 39 40 template <class T> class ClusterManager { 41 public: ClusterManager()42 ClusterManager() : m_objects(), m_external_ref(0), m_mutex() {} 43 ~ClusterManager()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 ManageObject(T * new_object)58 void ManageObject(T *new_object) { 59 std::lock_guard<std::mutex> guard(m_mutex); 60 m_objects.insert(new_object); 61 } 62 GetSharedPointer(T * desired_object)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 76 private: DecrementRefCount()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_ 96