SharedCluster.h revision 353358
138363Swpaul//===------------------SharedCluster.h --------------------------*- C++ -*-===// 238363Swpaul// 338363Swpaul// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 438363Swpaul// See https://llvm.org/LICENSE.txt for license information. 538363Swpaul// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 638363Swpaul// 738363Swpaul//===----------------------------------------------------------------------===// 838363Swpaul 938363Swpaul#ifndef utility_SharedCluster_h_ 1038363Swpaul#define utility_SharedCluster_h_ 1138363Swpaul 1238363Swpaul#include "lldb/Utility/LLDBAssert.h" 1338363Swpaul#include "lldb/Utility/SharingPtr.h" 1438363Swpaul 1538363Swpaul#include "llvm/ADT/SmallPtrSet.h" 1638363Swpaul 1738363Swpaul#include <mutex> 1838363Swpaul 1938363Swpaulnamespace lldb_private { 2038363Swpaul 2138363Swpaulnamespace imp { 2238363Swpaultemplate <typename T> 2338363Swpaulclass shared_ptr_refcount : public lldb_private::imp::shared_count { 2438363Swpaulpublic: 2538363Swpaul template <class Y> 2638363Swpaul shared_ptr_refcount(Y *in) : shared_count(0), manager(in) {} 2738363Swpaul 2838363Swpaul shared_ptr_refcount() : shared_count(0) {} 2938363Swpaul 3038363Swpaul ~shared_ptr_refcount() override {} 3138363Swpaul 3246514Swpaul void on_zero_shared() override { manager->DecrementRefCount(); } 3338363Swpaul 3438363Swpaulprivate: 3538363Swpaul T *manager; 3638363Swpaul}; 3738363Swpaul 3838363Swpaul} // namespace imp 3938363Swpaul 4038363Swpaultemplate <class T> class ClusterManager { 4138363Swpaulpublic: 4238363Swpaul ClusterManager() : m_objects(), m_external_ref(0), m_mutex() {} 4338363Swpaul 4438363Swpaul ~ClusterManager() { 4538363Swpaul for (typename llvm::SmallPtrSet<T *, 16>::iterator pos = m_objects.begin(), 4638363Swpaul end = m_objects.end(); 4738363Swpaul pos != end; ++pos) { 4838363Swpaul T *object = *pos; 4938363Swpaul delete object; 5038363Swpaul } 5138363Swpaul 5238363Swpaul // Decrement refcount should have been called on this ClusterManager, and 5338363Swpaul // it should have locked the mutex, now we will unlock it before we destroy 5438363Swpaul // it... 5538363Swpaul m_mutex.unlock(); 5638363Swpaul } 5738363Swpaul 5838363Swpaul void ManageObject(T *new_object) { 5938363Swpaul std::lock_guard<std::mutex> guard(m_mutex); 6038363Swpaul m_objects.insert(new_object); 6138363Swpaul } 6238363Swpaul 6338363Swpaul typename lldb_private::SharingPtr<T> GetSharedPointer(T *desired_object) { 6438363Swpaul { 6538363Swpaul std::lock_guard<std::mutex> guard(m_mutex); 6638363Swpaul m_external_ref++; 6738363Swpaul if (0 == m_objects.count(desired_object)) { 6838363Swpaul lldbassert(false && "object not found in shared cluster when expected"); 6938363Swpaul desired_object = nullptr; 7038363Swpaul } 7138363Swpaul } 7238363Swpaul return typename lldb_private::SharingPtr<T>( 7338363Swpaul desired_object, new imp::shared_ptr_refcount<ClusterManager>(this)); 7438363Swpaul } 7538363Swpaul 7638363Swpaulprivate: 7738363Swpaul void DecrementRefCount() { 7838363Swpaul m_mutex.lock(); 7938363Swpaul m_external_ref--; 8038363Swpaul if (m_external_ref == 0) 8138363Swpaul delete this; 8238363Swpaul else 8338363Swpaul m_mutex.unlock(); 8438363Swpaul } 8538363Swpaul 8638363Swpaul friend class imp::shared_ptr_refcount<ClusterManager>; 8738363Swpaul 8838363Swpaul llvm::SmallPtrSet<T *, 16> m_objects; 8938363Swpaul int m_external_ref; 9038363Swpaul std::mutex m_mutex; 9138363Swpaul}; 9238363Swpaul 9338363Swpaul} // namespace lldb_private 9438363Swpaul 9538363Swpaul#endif // utility_SharedCluster_h_ 9638363Swpaul