SharedCluster.h revision 314564
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
18namespace lldb_private {
19
20namespace imp {
21template <typename T>
22class shared_ptr_refcount : public lldb_private::imp::shared_count {
23public:
24  template <class Y>
25  shared_ptr_refcount(Y *in) : shared_count(0), manager(in) {}
26
27  shared_ptr_refcount() : shared_count(0) {}
28
29  ~shared_ptr_refcount() override {}
30
31  void on_zero_shared() override { manager->DecrementRefCount(); }
32
33private:
34  T *manager;
35};
36
37} // namespace imp
38
39template <class T> class ClusterManager {
40public:
41  ClusterManager() : m_objects(), m_external_ref(0), m_mutex() {}
42
43  ~ClusterManager() {
44    for (typename llvm::SmallPtrSet<T *, 16>::iterator pos = m_objects.begin(),
45                                                       end = m_objects.end();
46         pos != end; ++pos) {
47      T *object = *pos;
48      delete object;
49    }
50
51    // Decrement refcount should have been called on this ClusterManager,
52    // and it should have locked the mutex, now we will unlock it before
53    // we destroy it...
54    m_mutex.unlock();
55  }
56
57  void ManageObject(T *new_object) {
58    std::lock_guard<std::mutex> guard(m_mutex);
59    m_objects.insert(new_object);
60  }
61
62  typename lldb_private::SharingPtr<T> GetSharedPointer(T *desired_object) {
63    {
64      std::lock_guard<std::mutex> guard(m_mutex);
65      m_external_ref++;
66      if (0 == m_objects.count(desired_object)) {
67        lldbassert(false && "object not found in shared cluster when expected");
68        desired_object = nullptr;
69      }
70    }
71    return typename lldb_private::SharingPtr<T>(
72        desired_object, new imp::shared_ptr_refcount<ClusterManager>(this));
73  }
74
75private:
76  void DecrementRefCount() {
77    m_mutex.lock();
78    m_external_ref--;
79    if (m_external_ref == 0)
80      delete this;
81    else
82      m_mutex.unlock();
83  }
84
85  friend class imp::shared_ptr_refcount<ClusterManager>;
86
87  llvm::SmallPtrSet<T *, 16> m_objects;
88  int m_external_ref;
89  std::mutex m_mutex;
90};
91
92} // namespace lldb_private
93
94#endif // utility_SharedCluster_h_
95