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/Locker.h> 25#include <wtf/Noncopyable.h> 26#include <wtf/ThreadingPrimitives.h> 27#include <wtf/TCSpinLock.h> 28 29namespace JSC { 30 31class MarkStack; 32class MarkStackThreadSharedData; 33class SlotVisitor; 34 35template<typename T> 36class ListableHandler { 37 WTF_MAKE_NONCOPYABLE(ListableHandler); 38 39protected: 40 ListableHandler() 41 : m_nextAndFlag(0) 42 { 43 } 44 45 virtual ~ListableHandler() { } 46 47 T* next() const 48 { 49 return reinterpret_cast<T*>(m_nextAndFlag & ~1); 50 } 51 52private: 53 // Allow these classes to use ListableHandler::List. 54 friend class MarkStack; 55 friend class GCThreadSharedData; 56 friend class SlotVisitor; 57 58 class List { 59 WTF_MAKE_NONCOPYABLE(List); 60 public: 61 List() 62 : m_first(0) 63 { 64 m_lock.Init(); 65 } 66 67 void addThreadSafe(T* handler) 68 { 69 SpinLockHolder locker(&m_lock); 70 addNotThreadSafe(handler); 71 } 72 73 bool hasNext() 74 { 75 return !!m_first; 76 } 77 78 T* head() 79 { 80 return m_first; 81 } 82 83 T* removeNext() 84 { 85 T* current = m_first; 86 T* next = current->next(); 87 current->m_nextAndFlag = 0; 88 m_first = next; 89 return current; 90 } 91 92 void removeAll() 93 { 94 while (hasNext()) 95 removeNext(); 96 } 97 98 private: 99 void addNotThreadSafe(T* handler) 100 { 101 if (handler->m_nextAndFlag & 1) 102 return; 103 handler->m_nextAndFlag = reinterpret_cast<uintptr_t>(m_first) | 1; 104 m_first = handler; 105 } 106 107 SpinLock m_lock; 108 T* m_first; 109 }; 110 111 uintptr_t m_nextAndFlag; 112}; 113 114} // namespace JSC 115 116#endif // ListableHandler_h 117