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