Flutter Engine
The Flutter Engine
message_loop_darwin.mm
Go to the documentation of this file.
1// Copyright 2013 The Flutter Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "flutter/fml/platform/darwin/message_loop_darwin.h"
6
7#include <CoreFoundation/CFRunLoop.h>
8#include <Foundation/Foundation.h>
9
10#include "flutter/fml/logging.h"
11
12namespace fml {
13
14static constexpr CFTimeInterval kDistantFuture = 1.0e10;
15
16CFStringRef MessageLoopDarwin::kMessageLoopCFRunLoopMode = CFSTR("fmlMessageLoop");
17
18MessageLoopDarwin::MessageLoopDarwin()
19 : running_(false), loop_((CFRunLoopRef)CFRetain(CFRunLoopGetCurrent())) {
20 FML_DCHECK(loop_ != nullptr);
21
22 // Setup the delayed wake source.
23 CFRunLoopTimerContext timer_context = {
24 .info = this,
25 };
26 delayed_wake_timer_.Reset(
27 CFRunLoopTimerCreate(kCFAllocatorDefault, kDistantFuture /* fire date */,
28 HUGE_VAL /* interval */, 0 /* flags */, 0 /* order */,
29 reinterpret_cast<CFRunLoopTimerCallBack>(&MessageLoopDarwin::OnTimerFire)
30 /* callout */,
31 &timer_context /* context */));
32 FML_DCHECK(delayed_wake_timer_ != nullptr);
33 CFRunLoopAddTimer(loop_, delayed_wake_timer_, kCFRunLoopCommonModes);
34 // This mode will be used by FlutterKeyboardManager.
35 CFRunLoopAddTimer(loop_, delayed_wake_timer_, kMessageLoopCFRunLoopMode);
36}
37
38MessageLoopDarwin::~MessageLoopDarwin() {
39 CFRunLoopTimerInvalidate(delayed_wake_timer_);
40 CFRunLoopRemoveTimer(loop_, delayed_wake_timer_, kCFRunLoopCommonModes);
41 CFRunLoopRemoveTimer(loop_, delayed_wake_timer_, kMessageLoopCFRunLoopMode);
42}
43
45 FML_DCHECK(loop_ == CFRunLoopGetCurrent());
46
47 running_ = true;
48
49 while (running_) {
50 @autoreleasepool {
51 int result = CFRunLoopRunInMode(kCFRunLoopDefaultMode, kDistantFuture, YES);
52 if (result == kCFRunLoopRunStopped || result == kCFRunLoopRunFinished) {
53 // This handles the case where the loop is terminated using
54 // CoreFoundation APIs.
55 @autoreleasepool {
56 RunExpiredTasksNow();
57 }
58 running_ = false;
59 }
60 }
61 }
62}
63
64void MessageLoopDarwin::Terminate() {
65 running_ = false;
66
67 // Ensure that the CFRunLoop remains alive through the end of this function
68 // even if the loop's thread exits and drops its reference to the loop.
69 CFRef<CFRunLoopRef> local_loop(loop_);
70
71 CFRunLoopStop(local_loop);
72}
73
74void MessageLoopDarwin::WakeUp(fml::TimePoint time_point) {
75 // Rearm the timer. The time bases used by CoreFoundation and FXL are
76 // different and must be accounted for.
77 CFRunLoopTimerSetNextFireDate(
78 delayed_wake_timer_,
79 CFAbsoluteTimeGetCurrent() + (time_point - fml::TimePoint::Now()).ToSecondsF());
80}
81
82void MessageLoopDarwin::OnTimerFire(CFRunLoopTimerRef timer, MessageLoopDarwin* loop) {
83 @autoreleasepool {
84 // RunExpiredTasksNow rearms the timer as appropriate via a call to WakeUp.
85 loop->RunExpiredTasksNow();
86 }
87}
88
89} // namespace fml
static CFStringRef kMessageLoopCFRunLoopMode
static TimePoint Now()
Definition: time_point.cc:49
GAsyncResult * result
#define FML_DCHECK(condition)
Definition: logging.h:103
static FLUTTER_ASSERT_ARC constexpr CFTimeInterval kDistantFuture
Definition: ascii_trie.cc:9
static constexpr CFTimeInterval kDistantFuture