SharedCluster.h revision 296417
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/SharingPtr.h"
14#include "lldb/Host/Mutex.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 () :
50        m_objects(),
51        m_external_ref(0),
52        m_mutex(Mutex::eMutexTypeNormal) {}
53
54    ~ClusterManager ()
55    {
56        for (typename llvm::SmallPtrSet<T *, 16>::iterator pos = m_objects.begin(), end = m_objects.end(); pos != end; ++pos)
57        {
58            T *object = *pos;
59            delete object;
60        }
61
62        // Decrement refcount should have been called on this ClusterManager,
63        // and it should have locked the mutex, now we will unlock it before
64        // we destroy it...
65        m_mutex.Unlock();
66    }
67
68    void ManageObject (T *new_object)
69    {
70        Mutex::Locker locker (m_mutex);
71        m_objects.insert (new_object);
72    }
73
74    typename lldb_private::SharingPtr<T> GetSharedPointer(T *desired_object)
75    {
76        {
77            Mutex::Locker locker (m_mutex);
78            m_external_ref++;
79            assert (m_objects.count(desired_object));
80        }
81        return typename lldb_private::SharingPtr<T> (desired_object, new imp::shared_ptr_refcount<ClusterManager> (this));
82    }
83
84private:
85
86    void DecrementRefCount ()
87    {
88        m_mutex.Lock();
89        m_external_ref--;
90        if (m_external_ref == 0)
91            delete this;
92        else
93            m_mutex.Unlock();
94    }
95
96    friend class imp::shared_ptr_refcount<ClusterManager>;
97
98    llvm::SmallPtrSet<T *, 16> m_objects;
99    int m_external_ref;
100    Mutex m_mutex;
101};
102
103} // namespace lldb_private
104
105#endif // utility_SharedCluster_h_
106