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