10b57cec5SDimitry Andric //===------------------SharedCluster.h --------------------------*- C++ -*-===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 95ffd83dbSDimitry Andric #ifndef LLDB_UTILITY_SHAREDCLUSTER_H 105ffd83dbSDimitry Andric #define LLDB_UTILITY_SHAREDCLUSTER_H 110b57cec5SDimitry Andric 120b57cec5SDimitry Andric #include "lldb/Utility/LLDBAssert.h" 135ffd83dbSDimitry Andric #include "llvm/ADT/STLExtras.h" 14bdd1243dSDimitry Andric #include "llvm/ADT/SmallPtrSet.h" 150b57cec5SDimitry Andric 165ffd83dbSDimitry Andric #include <memory> 170b57cec5SDimitry Andric #include <mutex> 180b57cec5SDimitry Andric 190b57cec5SDimitry Andric namespace lldb_private { 200b57cec5SDimitry Andric 215ffd83dbSDimitry Andric template <class T> 225ffd83dbSDimitry Andric class ClusterManager : public std::enable_shared_from_this<ClusterManager<T>> { 230b57cec5SDimitry Andric public: Create()245ffd83dbSDimitry Andric static std::shared_ptr<ClusterManager> Create() { 255ffd83dbSDimitry Andric return std::shared_ptr<ClusterManager>(new ClusterManager()); 260b57cec5SDimitry Andric } 270b57cec5SDimitry Andric ~ClusterManager()285ffd83dbSDimitry Andric ~ClusterManager() { 295ffd83dbSDimitry Andric for (T *obj : m_objects) 305ffd83dbSDimitry Andric delete obj; 310b57cec5SDimitry Andric } 320b57cec5SDimitry Andric ManageObject(T * new_object)330b57cec5SDimitry Andric void ManageObject(T *new_object) { 340b57cec5SDimitry Andric std::lock_guard<std::mutex> guard(m_mutex); 35bdd1243dSDimitry Andric auto ret = m_objects.insert(new_object); 36bdd1243dSDimitry Andric assert(ret.second && "ManageObject called twice for the same object?"); 37bdd1243dSDimitry Andric (void)ret; 380b57cec5SDimitry Andric } 390b57cec5SDimitry Andric GetSharedPointer(T * desired_object)405ffd83dbSDimitry Andric std::shared_ptr<T> GetSharedPointer(T *desired_object) { 410b57cec5SDimitry Andric std::lock_guard<std::mutex> guard(m_mutex); 425ffd83dbSDimitry Andric auto this_sp = this->shared_from_this(); 43bdd1243dSDimitry Andric size_t count = m_objects.count(desired_object); 44bdd1243dSDimitry Andric if (count == 0) { 450b57cec5SDimitry Andric lldbassert(false && "object not found in shared cluster when expected"); 460b57cec5SDimitry Andric desired_object = nullptr; 470b57cec5SDimitry Andric } 485ffd83dbSDimitry Andric return {std::move(this_sp), desired_object}; 490b57cec5SDimitry Andric } 500b57cec5SDimitry Andric 510b57cec5SDimitry Andric private: ClusterManager()5204eeddc0SDimitry Andric ClusterManager() : m_objects() {} 53bdd1243dSDimitry Andric // The cluster manager is used primarily to manage the 54bdd1243dSDimitry Andric // children of root ValueObjects. So it will always have 55bdd1243dSDimitry Andric // one element - the root. Pointers will often have dynamic 56bdd1243dSDimitry Andric // values, so having 2 entries is pretty common. It's also 57bdd1243dSDimitry Andric // pretty common to have small (2,3) structs, so setting the 58bdd1243dSDimitry Andric // static size to 4 will cover those cases with no allocations 59bdd1243dSDimitry Andric // w/o wasting too much space. 60bdd1243dSDimitry Andric llvm::SmallPtrSet<T *, 4> m_objects; 610b57cec5SDimitry Andric std::mutex m_mutex; 620b57cec5SDimitry Andric }; 630b57cec5SDimitry Andric 640b57cec5SDimitry Andric } // namespace lldb_private 650b57cec5SDimitry Andric 665ffd83dbSDimitry Andric #endif // LLDB_UTILITY_SHAREDCLUSTER_H 67