1254721Semaste//===------------------SharedCluster.h --------------------------*- C++ -*-===// 2254721Semaste// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6254721Semaste// 7254721Semaste//===----------------------------------------------------------------------===// 8254721Semaste 9254721Semaste#ifndef utility_SharedCluster_h_ 10254721Semaste#define utility_SharedCluster_h_ 11254721Semaste 12309124Sdim#include "lldb/Utility/LLDBAssert.h" 13254721Semaste#include "lldb/Utility/SharingPtr.h" 14254721Semaste 15276479Sdim#include "llvm/ADT/SmallPtrSet.h" 16276479Sdim 17341825Sdim#include <mutex> 18341825Sdim 19254721Semastenamespace lldb_private { 20254721Semaste 21314564Sdimnamespace imp { 22314564Sdimtemplate <typename T> 23314564Sdimclass shared_ptr_refcount : public lldb_private::imp::shared_count { 24314564Sdimpublic: 25314564Sdim template <class Y> 26314564Sdim shared_ptr_refcount(Y *in) : shared_count(0), manager(in) {} 27296417Sdim 28314564Sdim shared_ptr_refcount() : shared_count(0) {} 29254721Semaste 30314564Sdim ~shared_ptr_refcount() override {} 31314564Sdim 32314564Sdim void on_zero_shared() override { manager->DecrementRefCount(); } 33314564Sdim 34314564Sdimprivate: 35314564Sdim T *manager; 36314564Sdim}; 37314564Sdim 38254721Semaste} // namespace imp 39254721Semaste 40314564Sdimtemplate <class T> class ClusterManager { 41254721Semastepublic: 42314564Sdim ClusterManager() : m_objects(), m_external_ref(0), m_mutex() {} 43309124Sdim 44314564Sdim ~ClusterManager() { 45314564Sdim for (typename llvm::SmallPtrSet<T *, 16>::iterator pos = m_objects.begin(), 46314564Sdim end = m_objects.end(); 47314564Sdim pos != end; ++pos) { 48314564Sdim T *object = *pos; 49314564Sdim delete object; 50254721Semaste } 51309124Sdim 52341825Sdim // Decrement refcount should have been called on this ClusterManager, and 53341825Sdim // it should have locked the mutex, now we will unlock it before we destroy 54341825Sdim // it... 55314564Sdim m_mutex.unlock(); 56314564Sdim } 57309124Sdim 58314564Sdim void ManageObject(T *new_object) { 59314564Sdim std::lock_guard<std::mutex> guard(m_mutex); 60314564Sdim m_objects.insert(new_object); 61314564Sdim } 62314564Sdim 63314564Sdim typename lldb_private::SharingPtr<T> GetSharedPointer(T *desired_object) { 64254721Semaste { 65314564Sdim std::lock_guard<std::mutex> guard(m_mutex); 66314564Sdim m_external_ref++; 67314564Sdim if (0 == m_objects.count(desired_object)) { 68314564Sdim lldbassert(false && "object not found in shared cluster when expected"); 69314564Sdim desired_object = nullptr; 70314564Sdim } 71254721Semaste } 72314564Sdim return typename lldb_private::SharingPtr<T>( 73314564Sdim desired_object, new imp::shared_ptr_refcount<ClusterManager>(this)); 74314564Sdim } 75309124Sdim 76254721Semasteprivate: 77314564Sdim void DecrementRefCount() { 78314564Sdim m_mutex.lock(); 79314564Sdim m_external_ref--; 80314564Sdim if (m_external_ref == 0) 81314564Sdim delete this; 82314564Sdim else 83314564Sdim m_mutex.unlock(); 84314564Sdim } 85309124Sdim 86314564Sdim friend class imp::shared_ptr_refcount<ClusterManager>; 87309124Sdim 88314564Sdim llvm::SmallPtrSet<T *, 16> m_objects; 89314564Sdim int m_external_ref; 90314564Sdim std::mutex m_mutex; 91254721Semaste}; 92254721Semaste 93254721Semaste} // namespace lldb_private 94296417Sdim 95254721Semaste#endif // utility_SharedCluster_h_ 96