2 * Copyright (C) 2006, 2008 Apple Inc. All rights reserved.
3 * Copyright (C) 2009 Google Inc. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 #include "platform/Timer.h"
30 #include "platform/TraceEvent.h"
31 #include "public/platform/Platform.h"
32 #include "public/platform/WebScheduler.h"
33 #include "wtf/AddressSanitizer.h"
34 #include "wtf/Atomics.h"
35 #include "wtf/CurrentTime.h"
36 #include "wtf/HashSet.h"
44 TimerBase::TimerBase()
46 , m_unalignedNextFireTime(0)
48 , m_cancellableTimerTask(nullptr)
49 , m_webScheduler(Platform::current()->currentThread()->scheduler())
51 , m_thread(currentThread())
56 TimerBase::~TimerBase()
61 void TimerBase::start(double nextFireInterval
, double repeatInterval
, const WebTraceLocation
& caller
)
63 ASSERT(m_thread
== currentThread());
66 m_repeatInterval
= repeatInterval
;
67 setNextFireTime(monotonicallyIncreasingTime(), nextFireInterval
);
70 void TimerBase::stop()
72 ASSERT(m_thread
== currentThread());
76 if (m_cancellableTimerTask
)
77 m_cancellableTimerTask
->cancel();
78 m_cancellableTimerTask
= nullptr;
81 double TimerBase::nextFireInterval() const
84 double current
= monotonicallyIncreasingTime();
85 if (m_nextFireTime
< current
)
87 return m_nextFireTime
- current
;
90 void TimerBase::setNextFireTime(double now
, double delay
)
92 ASSERT(m_thread
== currentThread());
94 m_unalignedNextFireTime
= now
+ delay
;
96 double newTime
= alignedFireTime(m_unalignedNextFireTime
);
97 if (m_nextFireTime
!= newTime
) {
98 m_nextFireTime
= newTime
;
99 if (m_cancellableTimerTask
)
100 m_cancellableTimerTask
->cancel();
101 m_cancellableTimerTask
= new CancellableTimerTask(this);
102 if (newTime
!= m_unalignedNextFireTime
) {
103 // If the timer is being aligned, use postTimerTaskAt() to schedule it
104 // so that the relative order of aligned timers is preserved.
105 // TODO(skyostil): Move timer alignment into the scheduler.
106 m_webScheduler
->postTimerTaskAt(m_location
, m_cancellableTimerTask
, m_nextFireTime
);
108 // Round the delay up to the nearest millisecond to be consistant with the
109 // previous behavior of BlinkPlatformImpl::setSharedTimerFireInterval.
110 long long delayMs
= static_cast<long long>(ceil((newTime
- now
) * 1000.0));
113 m_webScheduler
->timerTaskRunner()->postDelayedTask(m_location
, m_cancellableTimerTask
, delayMs
);
118 NO_LAZY_SWEEP_SANITIZE_ADDRESS
119 void TimerBase::runInternal()
124 TRACE_EVENT0("blink", "TimerBase::run");
125 ASSERT_WITH_MESSAGE(m_thread
== currentThread(), "Timer posted by %s %s was run on a different thread", m_location
.functionName(), m_location
.fileName());
126 TRACE_EVENT_SET_SAMPLING_STATE("blink", "BlinkInternal");
129 // Note: repeating timers drift, but this is preserving the functionality of the old timer heap.
130 // See crbug.com/328700.
131 if (m_repeatInterval
)
132 setNextFireTime(monotonicallyIncreasingTime(), m_repeatInterval
);
134 TRACE_EVENT_SET_SAMPLING_STATE("blink", "Sleeping");
137 void TimerBase::didChangeAlignmentInterval(double now
)
139 setNextFireTime(now
, m_unalignedNextFireTime
- now
);
142 double TimerBase::nextUnalignedFireInterval() const
145 return std::max(m_unalignedNextFireTime
- monotonicallyIncreasingTime(), 0.0);
148 bool TimerBase::Comparator::operator()(const TimerBase
* a
, const TimerBase
* b
) const
150 return a
->m_unalignedNextFireTime
< b
->m_unalignedNextFireTime
;