1/*
2 * Copyright (C) 2006, 2007, 2009 Apple Inc. All rights reserved.
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public License
15 * along with this library; see the file COPYING.LIB.  If not, write to
16 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
18 *
19 */
20
21#ifndef TreeShared_h
22#define TreeShared_h
23
24#include <wtf/Assertions.h>
25#include <wtf/Noncopyable.h>
26#ifndef NDEBUG
27#include <wtf/Threading.h>
28#endif
29
30namespace WebCore {
31
32template<class T> class TreeShared : public Noncopyable {
33public:
34    TreeShared(int initialRefCount = 1)
35        : m_refCount(initialRefCount)
36        , m_parent(0)
37    {
38        ASSERT(isMainThread());
39#ifndef NDEBUG
40        m_deletionHasBegun = false;
41        m_inRemovedLastRefFunction = false;
42#endif
43    }
44    virtual ~TreeShared()
45    {
46        ASSERT(isMainThread());
47        ASSERT(!m_refCount);
48        ASSERT(m_deletionHasBegun);
49    }
50
51    void ref()
52    {
53        ASSERT(isMainThread());
54        ASSERT(!m_deletionHasBegun);
55        ASSERT(!m_inRemovedLastRefFunction);
56        ++m_refCount;
57    }
58
59    void deref()
60    {
61        ASSERT(isMainThread());
62        ASSERT(m_refCount >= 0);
63        ASSERT(!m_deletionHasBegun);
64        ASSERT(!m_inRemovedLastRefFunction);
65        if (--m_refCount <= 0 && !m_parent) {
66#ifndef NDEBUG
67            m_inRemovedLastRefFunction = true;
68#endif
69            removedLastRef();
70        }
71    }
72
73    bool hasOneRef() const
74    {
75        ASSERT(!m_deletionHasBegun);
76        ASSERT(!m_inRemovedLastRefFunction);
77        return m_refCount == 1;
78    }
79
80    int refCount() const
81    {
82        return m_refCount;
83    }
84
85    void setParent(T* parent)
86    {
87        ASSERT(isMainThread());
88        m_parent = parent;
89    }
90
91    T* parent() const
92    {
93        ASSERT(isMainThread());
94        return m_parent;
95    }
96
97#ifndef NDEBUG
98    bool m_deletionHasBegun;
99    bool m_inRemovedLastRefFunction;
100#endif
101
102private:
103    virtual void removedLastRef()
104    {
105#ifndef NDEBUG
106        m_deletionHasBegun = true;
107#endif
108        delete this;
109    }
110
111    int m_refCount;
112    T* m_parent;
113};
114
115}
116
117#endif // TreeShared.h
118