SharedCluster.h revision 353358
1219019Sgabor//===------------------SharedCluster.h --------------------------*- C++ -*-===// 2264497Stijl// 3219019Sgabor// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4219019Sgabor// See https://llvm.org/LICENSE.txt for license information. 5219019Sgabor// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6219019Sgabor// 7219019Sgabor//===----------------------------------------------------------------------===// 8219019Sgabor 9219019Sgabor#ifndef utility_SharedCluster_h_ 10219019Sgabor#define utility_SharedCluster_h_ 11219019Sgabor 12219019Sgabor#include "lldb/Utility/LLDBAssert.h" 13219019Sgabor#include "lldb/Utility/SharingPtr.h" 14219019Sgabor 15219019Sgabor#include "llvm/ADT/SmallPtrSet.h" 16219019Sgabor 17219019Sgabor#include <mutex> 18219019Sgabor 19219019Sgabornamespace lldb_private { 20219019Sgabor 21219019Sgabornamespace imp { 22219019Sgabortemplate <typename T> 23219019Sgaborclass shared_ptr_refcount : public lldb_private::imp::shared_count { 24219019Sgaborpublic: 25219019Sgabor template <class Y> 26219019Sgabor shared_ptr_refcount(Y *in) : shared_count(0), manager(in) {} 27219019Sgabor 28219019Sgabor shared_ptr_refcount() : shared_count(0) {} 29219019Sgabor 30219019Sgabor ~shared_ptr_refcount() override {} 31219019Sgabor 32219019Sgabor void on_zero_shared() override { manager->DecrementRefCount(); } 33219019Sgabor 34219019Sgaborprivate: 35219019Sgabor T *manager; 36219019Sgabor}; 37219019Sgabor 38219019Sgabor} // namespace imp 39219019Sgabor 40219019Sgabortemplate <class T> class ClusterManager { 41219019Sgaborpublic: 42219019Sgabor ClusterManager() : m_objects(), m_external_ref(0), m_mutex() {} 43219019Sgabor 44219019Sgabor ~ClusterManager() { 45219019Sgabor for (typename llvm::SmallPtrSet<T *, 16>::iterator pos = m_objects.begin(), 46219019Sgabor end = m_objects.end(); 47219019Sgabor pos != end; ++pos) { 48219019Sgabor T *object = *pos; 49219019Sgabor delete object; 50219019Sgabor } 51219019Sgabor 52219019Sgabor // Decrement refcount should have been called on this ClusterManager, and 53219019Sgabor // it should have locked the mutex, now we will unlock it before we destroy 54219019Sgabor // it... 55219019Sgabor m_mutex.unlock(); 56219019Sgabor } 57219019Sgabor 58219019Sgabor void ManageObject(T *new_object) { 59219019Sgabor std::lock_guard<std::mutex> guard(m_mutex); 60219019Sgabor m_objects.insert(new_object); 61219019Sgabor } 62219019Sgabor 63219019Sgabor typename lldb_private::SharingPtr<T> GetSharedPointer(T *desired_object) { 64219019Sgabor { 65219019Sgabor std::lock_guard<std::mutex> guard(m_mutex); 66219019Sgabor m_external_ref++; 67219019Sgabor if (0 == m_objects.count(desired_object)) { 68219019Sgabor lldbassert(false && "object not found in shared cluster when expected"); 69219019Sgabor desired_object = nullptr; 70219019Sgabor } 71219019Sgabor } 72219019Sgabor return typename lldb_private::SharingPtr<T>( 73219019Sgabor desired_object, new imp::shared_ptr_refcount<ClusterManager>(this)); 74219019Sgabor } 75219019Sgabor 76219019Sgaborprivate: 77219019Sgabor void DecrementRefCount() { 78219019Sgabor m_mutex.lock(); 79219019Sgabor m_external_ref--; 80219019Sgabor if (m_external_ref == 0) 81219019Sgabor delete this; 82219019Sgabor else 83219019Sgabor m_mutex.unlock(); 84219019Sgabor } 85219019Sgabor 86219019Sgabor friend class imp::shared_ptr_refcount<ClusterManager>; 87219019Sgabor 88219019Sgabor llvm::SmallPtrSet<T *, 16> m_objects; 89219019Sgabor int m_external_ref; 90219019Sgabor std::mutex m_mutex; 91219019Sgabor}; 92219019Sgabor 93219019Sgabor} // namespace lldb_private 94219019Sgabor 95219019Sgabor#endif // utility_SharedCluster_h_ 96219019Sgabor