Ticket #40852: patch-src_3rdparty_webkit_Source_WebCore_platform_Timer.cpp.2.diff
File patch-src_3rdparty_webkit_Source_WebCore_platform_Timer.cpp.2.diff, 11.1 KB (added by BSeppke (Benjamin Seppke), 11 years ago) |
---|
-
src/3rdparty/webkit/Source/WebCore/platform/Timer.cpp
old new 41 41 42 42 namespace WebCore { 43 43 44 class TimerHeapReference; 45 44 46 // Timers are stored in a heap data structure, used to implement a priority queue. 45 47 // This allows us to efficiently determine which timer needs to fire the soonest. 46 48 // Then we set a single shared system timer to fire at that time. … … 53 55 return threadGlobalData().threadTimers().timerHeap(); 54 56 } 55 57 56 // Class to represent elements in the heap when calling the standard library heap algorithms. 57 // Maintains the m_heapIndex value in the timers themselves, which allows us to do efficient 58 // modification of the heap. 59 class TimerHeapElement { 60 public: 61 explicit TimerHeapElement(int i) 62 : m_index(i) 63 , m_timer(timerHeap()[m_index]) 64 { 65 checkConsistency(); 66 } 67 68 TimerHeapElement(const TimerHeapElement&); 69 TimerHeapElement& operator=(const TimerHeapElement&); 70 71 TimerBase* timer() const { return m_timer; } 72 73 void checkConsistency() const 74 { 75 ASSERT(m_index >= 0); 76 ASSERT(m_index < static_cast<int>(timerHeap().size())); 77 } 58 // ---------------- 78 59 60 class TimerHeapPointer { 61 public: 62 TimerHeapPointer(TimerBase** pointer) : m_pointer(pointer) { } 63 TimerHeapReference operator*() const; 64 TimerBase* operator->() const { return *m_pointer; } 79 65 private: 80 TimerHeapElement(); 66 TimerBase** m_pointer; 67 }; 81 68 82 int m_index; 83 TimerBase* m_timer; 69 class TimerHeapReference { 70 public: 71 TimerHeapReference(TimerBase*& reference) : m_reference(reference) { } 72 operator TimerBase*() const { return m_reference; } 73 TimerHeapPointer operator&() const { return &m_reference; } 74 TimerHeapReference& operator=(TimerBase*); 75 TimerHeapReference& operator=(TimerHeapReference); 76 private: 77 TimerBase*& m_reference; 84 78 }; 85 79 86 inline TimerHeapElement::TimerHeapElement(const TimerHeapElement& o) 87 : m_index(-1), m_timer(o.timer()) 80 inline TimerHeapReference TimerHeapPointer::operator*() const 88 81 { 82 return *m_pointer; 89 83 } 90 84 91 inline TimerHeap Element& TimerHeapElement::operator=(const TimerHeapElement& o)85 inline TimerHeapReference& TimerHeapReference::operator=(TimerBase* timer) 92 86 { 93 TimerBase* t = o.timer(); 94 m_timer = t; 95 if (m_index != -1) { 96 checkConsistency(); 97 timerHeap()[m_index] = t; 98 t->m_heapIndex = m_index; 99 } 87 m_reference = timer; 88 Vector<TimerBase*>& heap = timerHeap(); 89 if (&m_reference >= heap.data() && &m_reference < heap.data() + heap.size()) 90 timer->m_heapIndex = &m_reference - heap.data(); 100 91 return *this; 101 92 } 102 93 103 inline bool operator<(const TimerHeapElement& a, const TimerHeapElement&b)94 inline TimerHeapReference& TimerHeapReference::operator=(TimerHeapReference b) 104 95 { 105 // The comparisons below are "backwards" because the heap puts the largest 106 // element first and we want the lowest time to be the first one in the heap. 107 double aFireTime = a.timer()->m_nextFireTime; 108 double bFireTime = b.timer()->m_nextFireTime; 109 if (bFireTime != aFireTime) 110 return bFireTime < aFireTime; 96 TimerBase* timer = b; 97 return *this = timer; 98 } 99 100 inline void swap(TimerHeapReference a, TimerHeapReference b) 101 { 102 TimerBase* timerA = a; 103 TimerBase* timerB = b; 111 104 112 // We need to look at the difference of the insertion orders instead of comparing the two 113 // outright in case of overflow. 114 unsigned difference = a.timer()->m_heapInsertionOrder - b.timer()->m_heapInsertionOrder; 115 return difference < UINT_MAX / 2; 105 // Invoke the assignment operator, since that takes care of updating m_heapIndex. 106 a = timerB; 107 b = timerA; 116 108 } 117 109 118 110 // ---------------- 119 111 120 112 // Class to represent iterators in the heap when calling the standard library heap algorithms. 121 // Returns TimerHeapElement for elements in the heap rather than the TimerBase pointers themselves.122 class TimerHeapIterator : public iterator<random_access_iterator_tag, Timer HeapElement, int> {113 // Uses a custom pointer and reference type that update indices for pointers in the heap. 114 class TimerHeapIterator : public iterator<random_access_iterator_tag, TimerBase*, ptrdiff_t, TimerHeapPointer, TimerHeapReference> { 123 115 public: 124 TimerHeapIterator() : m_index(-1) { } 125 TimerHeapIterator(int i) : m_index(i) { checkConsistency(); } 126 127 TimerHeapIterator& operator++() { checkConsistency(); ++m_index; checkConsistency(); return *this; } 128 TimerHeapIterator operator++(int) { checkConsistency(); checkConsistency(1); return m_index++; } 129 130 TimerHeapIterator& operator--() { checkConsistency(); --m_index; checkConsistency(); return *this; } 131 TimerHeapIterator operator--(int) { checkConsistency(); checkConsistency(-1); return m_index--; } 116 explicit TimerHeapIterator(TimerBase** pointer) : m_pointer(pointer) { checkConsistency(); } 117 118 TimerHeapIterator& operator++() { checkConsistency(); ++m_pointer; checkConsistency(); return *this; } 119 TimerHeapIterator operator++(int) { checkConsistency(1); return TimerHeapIterator(m_pointer++); } 120 121 TimerHeapIterator& operator--() { checkConsistency(); --m_pointer; checkConsistency(); return *this; } 122 TimerHeapIterator operator--(int) { checkConsistency(-1); return TimerHeapIterator(m_pointer--); } 123 124 TimerHeapIterator& operator+=(ptrdiff_t i) { checkConsistency(); m_pointer += i; checkConsistency(); return *this; } 125 TimerHeapIterator& operator-=(ptrdiff_t i) { checkConsistency(); m_pointer -= i; checkConsistency(); return *this; } 126 127 TimerHeapReference operator*() const { return TimerHeapReference(*m_pointer); } 128 TimerHeapReference operator[](ptrdiff_t i) const { return TimerHeapReference(m_pointer[i]); } 129 TimerBase* operator->() const { return *m_pointer; } 130 131 private: 132 void checkConsistency(ptrdiff_t offset = 0) const 133 { 134 ASSERT(m_pointer >= timerHeap().data()); 135 ASSERT(m_pointer <= timerHeap().data() + timerHeap().size()); 136 ASSERT_UNUSED(offset, m_pointer + offset >= timerHeap().data()); 137 ASSERT_UNUSED(offset, m_pointer + offset <= timerHeap().data() + timerHeap().size()); 138 } 139 140 friend bool operator==(TimerHeapIterator, TimerHeapIterator); 141 friend bool operator!=(TimerHeapIterator, TimerHeapIterator); 142 friend bool operator<(TimerHeapIterator, TimerHeapIterator); 143 friend bool operator>(TimerHeapIterator, TimerHeapIterator); 144 friend bool operator<=(TimerHeapIterator, TimerHeapIterator); 145 friend bool operator>=(TimerHeapIterator, TimerHeapIterator); 146 147 friend TimerHeapIterator operator+(TimerHeapIterator, size_t); 148 friend TimerHeapIterator operator+(size_t, TimerHeapIterator); 149 150 friend TimerHeapIterator operator-(TimerHeapIterator, size_t); 151 friend ptrdiff_t operator-(TimerHeapIterator, TimerHeapIterator); 152 153 TimerBase** m_pointer; 154 }; 132 155 133 TimerHeapIterator& operator+=(int i) { checkConsistency(); m_index += i; checkConsistency(); return *this; } 134 TimerHeapIterator& operator-=(int i) { checkConsistency(); m_index -= i; checkConsistency(); return *this; } 156 inline bool operator==(TimerHeapIterator a, TimerHeapIterator b) { return a.m_pointer == b.m_pointer; } 157 inline bool operator!=(TimerHeapIterator a, TimerHeapIterator b) { return a.m_pointer != b.m_pointer; } 158 inline bool operator<(TimerHeapIterator a, TimerHeapIterator b) { return a.m_pointer < b.m_pointer; } 159 inline bool operator>(TimerHeapIterator a, TimerHeapIterator b) { return a.m_pointer > b.m_pointer; } 160 inline bool operator<=(TimerHeapIterator a, TimerHeapIterator b) { return a.m_pointer <= b.m_pointer; } 161 inline bool operator>=(TimerHeapIterator a, TimerHeapIterator b) { return a.m_pointer >= b.m_pointer; } 135 162 136 TimerHeapElement operator*() const { return TimerHeapElement(m_index); }137 TimerHeapElement operator[](int i) const { return TimerHeapElement(m_index + i); }163 inline TimerHeapIterator operator+(TimerHeapIterator a, size_t b) { return TimerHeapIterator(a.m_pointer + b); } 164 inline TimerHeapIterator operator+(size_t a, TimerHeapIterator b) { return TimerHeapIterator(a + b.m_pointer); } 138 165 139 int index() const { return m_index; } 166 inline TimerHeapIterator operator-(TimerHeapIterator a, size_t b) { return TimerHeapIterator(a.m_pointer - b); } 167 inline ptrdiff_t operator-(TimerHeapIterator a, TimerHeapIterator b) { return a.m_pointer - b.m_pointer; } 140 168 141 void checkConsistency(int offset = 0) const 142 { 143 ASSERT_UNUSED(offset, m_index + offset >= 0); 144 ASSERT_UNUSED(offset, m_index + offset <= static_cast<int>(timerHeap().size())); 145 } 169 // ---------------- 146 170 147 private: 148 int m_index; 171 class TimerHeapLessThanFunction { 172 public: 173 bool operator()(TimerBase*, TimerBase*) const; 149 174 }; 150 175 151 inline bool operator==(TimerHeapIterator a, TimerHeapIterator b) { return a.index() == b.index(); } 152 inline bool operator!=(TimerHeapIterator a, TimerHeapIterator b) { return a.index() != b.index(); } 153 inline bool operator<(TimerHeapIterator a, TimerHeapIterator b) { return a.index() < b.index(); } 154 155 inline TimerHeapIterator operator+(TimerHeapIterator a, int b) { return a.index() + b; } 156 inline TimerHeapIterator operator+(int a, TimerHeapIterator b) { return a + b.index(); } 157 158 inline TimerHeapIterator operator-(TimerHeapIterator a, int b) { return a.index() - b; } 159 inline int operator-(TimerHeapIterator a, TimerHeapIterator b) { return a.index() - b.index(); } 176 inline bool TimerHeapLessThanFunction::operator()(TimerBase* a, TimerBase* b) const 177 { 178 // The comparisons below are "backwards" because the heap puts the largest 179 // element first and we want the lowest time to be the first one in the heap. 180 double aFireTime = a->m_nextFireTime; 181 double bFireTime = b->m_nextFireTime; 182 if (bFireTime != aFireTime) 183 return bFireTime < aFireTime; 184 185 // We need to look at the difference of the insertion orders instead of comparing the two 186 // outright in case of overflow. 187 unsigned difference = a->m_heapInsertionOrder - b->m_heapInsertionOrder; 188 return difference < numeric_limits<unsigned>::max() / 2; 189 } 160 190 161 191 // ---------------- 162 192 163 193 TimerBase::TimerBase() 164 165 166 194 : m_nextFireTime(0) 195 , m_repeatInterval(0) 196 , m_heapIndex(-1) 167 197 #ifndef NDEBUG 168 198 , m_thread(currentThread()) 169 199 #endif 170 200 { 171 201 } … … 225 255 { 226 256 ASSERT(m_nextFireTime != 0); 227 257 checkHeapIndex(); 228 push_heap(TimerHeapIterator(0), TimerHeapIterator(m_heapIndex + 1)); 258 TimerBase** heapData = timerHeap().data(); 259 push_heap(TimerHeapIterator(heapData), TimerHeapIterator(heapData + m_heapIndex + 1), TimerHeapLessThanFunction()); 229 260 checkHeapIndex(); 230 261 } 231 262 … … 274 305 { 275 306 ASSERT(this == timerHeap().first()); 276 307 checkHeapIndex(); 277 pop_heap(TimerHeapIterator(0), TimerHeapIterator(timerHeap().size())); 308 Vector<TimerBase*>& heap = timerHeap(); 309 TimerBase** heapData = heap.data(); 310 pop_heap(TimerHeapIterator(heapData), TimerHeapIterator(heapData + heap.size()), TimerHeapLessThanFunction()); 278 311 checkHeapIndex(); 279 312 ASSERT(this == timerHeap().last()); 280 313 }