1/*
2 * Copyright (C) 2006, 2007, 2009, 2010, 2012 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/MainThread.h>
26#include <wtf/Noncopyable.h>
27
28namespace WebCore {
29
30#ifndef NDEBUG
31template<typename NodeType> class TreeShared;
32template<typename NodeType> void adopted(TreeShared<NodeType>*);
33#endif
34
35template<typename NodeType> class TreeShared {
36    WTF_MAKE_NONCOPYABLE(TreeShared);
37protected:
38    TreeShared()
39        : m_refCount(1)
40#ifndef NDEBUG
41        , m_adoptionIsRequired(true)
42#endif
43    {
44        ASSERT(isMainThread());
45#ifndef NDEBUG
46        m_deletionHasBegun = false;
47        m_inRemovedLastRefFunction = false;
48#endif
49    }
50
51    ~TreeShared()
52    {
53        ASSERT(isMainThread());
54        ASSERT(!m_refCount);
55        ASSERT(m_deletionHasBegun);
56        ASSERT(!m_adoptionIsRequired);
57    }
58
59public:
60    void ref()
61    {
62        ASSERT(isMainThread());
63        ASSERT(!m_deletionHasBegun);
64        ASSERT(!m_inRemovedLastRefFunction);
65        ASSERT(!m_adoptionIsRequired);
66        ++m_refCount;
67    }
68
69    void deref()
70    {
71        ASSERT(isMainThread());
72        ASSERT(m_refCount >= 0);
73        ASSERT(!m_deletionHasBegun);
74        ASSERT(!m_inRemovedLastRefFunction);
75        ASSERT(!m_adoptionIsRequired);
76        NodeType* thisNode = static_cast<NodeType*>(this);
77        if (--m_refCount <= 0 && !thisNode->hasTreeSharedParent()) {
78#ifndef NDEBUG
79            m_inRemovedLastRefFunction = true;
80#endif
81            thisNode->removedLastRef();
82        }
83    }
84
85    bool hasOneRef() const
86    {
87        ASSERT(!m_deletionHasBegun);
88        ASSERT(!m_inRemovedLastRefFunction);
89        return m_refCount == 1;
90    }
91
92    int refCount() const
93    {
94        return m_refCount;
95    }
96
97#ifndef NDEBUG
98    bool m_deletionHasBegun;
99    bool m_inRemovedLastRefFunction;
100#endif
101
102private:
103#ifndef NDEBUG
104    friend void adopted<>(TreeShared<NodeType>*);
105#endif
106
107    int m_refCount;
108
109#ifndef NDEBUG
110    bool m_adoptionIsRequired;
111#endif
112};
113
114#ifndef NDEBUG
115
116template<typename NodeType> inline void adopted(TreeShared<NodeType>* object)
117{
118    if (!object)
119        return;
120    ASSERT(!object->m_deletionHasBegun);
121    ASSERT(!object->m_inRemovedLastRefFunction);
122    object->m_adoptionIsRequired = false;
123}
124
125#endif
126
127}
128
129#endif // TreeShared.h
130