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
16namespace lldb_private {
17
18namespace imp
19{
20    template <typename T>
21    class shared_ptr_refcount : public lldb_private::imp::shared_count
22    {
23    public:
24        template<class Y> shared_ptr_refcount (Y *in) : shared_count (0), manager(in) {}
25
26        shared_ptr_refcount() : shared_count (0) {}
27
28        virtual ~shared_ptr_refcount ()
29        {
30        }
31
32        virtual void on_zero_shared ()
33        {
34            manager->DecrementRefCount();
35        }
36    private:
37        T *manager;
38    };
39
40} // namespace imp
41
42template <class T>
43class ClusterManager
44{
45public:
46    ClusterManager () :
47        m_objects(),
48        m_external_ref(0),
49        m_mutex(Mutex::eMutexTypeNormal) {}
50
51    ~ClusterManager ()
52    {
53        size_t n_items = m_objects.size();
54        for (size_t i = 0; i < n_items; i++)
55        {
56            delete m_objects[i];
57        }
58        // Decrement refcount should have been called on this ClusterManager,
59        // and it should have locked the mutex, now we will unlock it before
60        // we destroy it...
61        m_mutex.Unlock();
62    }
63
64    void ManageObject (T *new_object)
65    {
66        Mutex::Locker locker (m_mutex);
67        if (!ContainsObject(new_object))
68            m_objects.push_back (new_object);
69    }
70
71    typename lldb_private::SharingPtr<T> GetSharedPointer(T *desired_object)
72    {
73        {
74            Mutex::Locker locker (m_mutex);
75            m_external_ref++;
76            assert (ContainsObject(desired_object));
77        }
78        return typename lldb_private::SharingPtr<T> (desired_object, new imp::shared_ptr_refcount<ClusterManager> (this));
79    }
80
81private:
82
83    bool ContainsObject (const T *desired_object)
84    {
85        typename std::vector<T *>::iterator pos, end = m_objects.end();
86        pos = std::find(m_objects.begin(), end, desired_object);
87        return pos != end;
88    }
89
90    void 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    std::vector<T *> m_objects;
103    int m_external_ref;
104    Mutex m_mutex;
105};
106
107} // namespace lldb_private
108#endif // utility_SharedCluster_h_
109