1/*
2 * Copyright (C) 2011 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 Lesser 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 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 *
18 */
19
20#ifndef ListableHandler_h
21#define ListableHandler_h
22
23#include <stdint.h>
24#include <wtf/Lock.h>
25#include <wtf/Locker.h>
26#include <wtf/Noncopyable.h>
27#include <wtf/ThreadingPrimitives.h>
28
29namespace JSC {
30
31class Heap;
32class SlotVisitor;
33
34template<typename T>
35class ListableHandler {
36 WTF_MAKE_NONCOPYABLE(ListableHandler);
37
38protected:
39 ListableHandler()
40 : m_nextAndFlag(0)
41 {
42 }
43
44 virtual ~ListableHandler() { }
45
46 T* next() const
47 {
48 return reinterpret_cast<T*>(m_nextAndFlag & ~1);
49 }
50
51private:
52 // Allow these classes to use ListableHandler::List.
53 friend class Heap;
54 friend class SlotVisitor;
55
56 class List {
57 WTF_MAKE_NONCOPYABLE(List);
58 public:
59 List()
60 : m_first(0)
61 {
62 }
63
64 void addThreadSafe(T* handler)
65 {
66 LockHolder locker(&m_lock);
67 addNotThreadSafe(handler);
68 }
69
70 bool hasNext()
71 {
72 return !!m_first;
73 }
74
75 T* head()
76 {
77 return m_first;
78 }
79
80 T* removeNext()
81 {
82 T* current = m_first;
83 T* next = current->next();
84 current->m_nextAndFlag = 0;
85 m_first = next;
86 return current;
87 }
88
89 void removeAll()
90 {
91 while (hasNext())
92 removeNext();
93 }
94
95 private:
96 void addNotThreadSafe(T* handler)
97 {
98 if (handler->m_nextAndFlag & 1)
99 return;
100 handler->m_nextAndFlag = reinterpret_cast<uintptr_t>(m_first) | 1;
101 m_first = handler;
102 }
103
104 Lock m_lock;
105 T* m_first;
106 };
107
108 uintptr_t m_nextAndFlag;
109};
110
111} // namespace JSC
112
113#endif // ListableHandler_h
114