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