Make every port implement MainThreadSharedTimer instead of using global functions
[WebKit-https.git] / Source / WebCore / platform / cf / MainThreadSharedTimerCF.cpp
1 /*
2  * Copyright (C) 2006, 2010, 2015 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #import "config.h"
27 #import "MainThreadSharedTimer.h"
28
29 #include <wtf/AutodrainedPool.h>
30
31 #if PLATFORM(MAC)
32 #import "PowerObserverMac.h"
33 #elif PLATFORM(IOS)
34 #import "WebCoreThread.h"
35 #import "WebCoreThreadRun.h"
36 #endif
37
38 namespace WebCore {
39
40 static CFRunLoopTimerRef sharedTimer;
41 static void timerFired(CFRunLoopTimerRef, void*);
42 static void restartSharedTimer();
43
44 static const CFTimeInterval kCFTimeIntervalDistantFuture = std::numeric_limits<CFTimeInterval>::max();
45
46 #if PLATFORM(IOS)
47 static void applicationDidBecomeActive(CFNotificationCenterRef, void*, CFStringRef, const void*, CFDictionaryRef)
48 {
49     WebThreadRun(^{
50         restartSharedTimer();
51     });
52 }
53 #endif
54
55 static void setupPowerObserver()
56 {
57 #if PLATFORM(MAC)
58     static PowerObserver* powerObserver;
59     if (!powerObserver)
60         powerObserver = std::make_unique<PowerObserver>(restartSharedTimer).release();
61 #elif PLATFORM(IOS)
62     static bool registeredForApplicationNotification = false;
63     if (!registeredForApplicationNotification) {
64         registeredForApplicationNotification = true;
65         CFNotificationCenterRef notificationCenter = CFNotificationCenterGetLocalCenter();
66         CFNotificationCenterAddObserver(notificationCenter, nullptr, applicationDidBecomeActive, CFSTR("UIApplicationDidBecomeActiveNotification"), nullptr, CFNotificationSuspensionBehaviorCoalesce);
67     }
68 #endif
69 }
70
71 static void timerFired(CFRunLoopTimerRef, void*)
72 {
73     AutodrainedPool pool;
74     MainThreadSharedTimer::singleton().fired();
75 }
76
77 static void restartSharedTimer()
78 {
79     if (!sharedTimer)
80         return;
81
82     MainThreadSharedTimer::singleton().stop();
83     timerFired(0, 0);
84 }
85
86 void MainThreadSharedTimer::invalidate()
87 {
88     if (!sharedTimer)
89         return;
90
91     CFRunLoopTimerInvalidate(sharedTimer);
92     CFRelease(sharedTimer);
93     sharedTimer = nullptr;
94 }
95
96 void MainThreadSharedTimer::setFireInterval(double interval)
97 {
98     ASSERT(m_firedFunction);
99
100     CFAbsoluteTime fireDate = CFAbsoluteTimeGetCurrent() + interval;
101     if (!sharedTimer) {
102         sharedTimer = CFRunLoopTimerCreate(nullptr, fireDate, kCFTimeIntervalDistantFuture, 0, 0, timerFired, nullptr);
103 #if PLATFORM(IOS)
104         CFRunLoopAddTimer(WebThreadRunLoop(), sharedTimer, kCFRunLoopCommonModes);
105 #else
106         CFRunLoopAddTimer(CFRunLoopGetCurrent(), sharedTimer, kCFRunLoopCommonModes);
107 #endif
108
109         setupPowerObserver();
110
111         return;
112     }
113
114     CFRunLoopTimerSetNextFireDate(sharedTimer, fireDate);
115 }
116
117 void MainThreadSharedTimer::stop()
118 {
119     if (!sharedTimer)
120         return;
121
122     CFRunLoopTimerSetNextFireDate(sharedTimer, kCFTimeIntervalDistantFuture);
123 }
124
125 } // namespace WebCore