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 
12 namespace fml {
13 
14 static constexpr CFTimeInterval kDistantFuture = 1.0e10;
15 
16 CFStringRef MessageLoopDarwin::kMessageLoopCFRunLoopMode = CFSTR("fmlMessageLoop");
17 
18 MessageLoopDarwin::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 
38 MessageLoopDarwin::~MessageLoopDarwin() {
39  CFRunLoopTimerInvalidate(delayed_wake_timer_);
40  CFRunLoopRemoveTimer(loop_, delayed_wake_timer_, kCFRunLoopCommonModes);
41  CFRunLoopRemoveTimer(loop_, delayed_wake_timer_, kMessageLoopCFRunLoopMode);
42 }
43 
44 void MessageLoopDarwin::Run() {
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 {
57  }
58  running_ = false;
59  }
60  }
61  }
62 }
63 
64 void MessageLoopDarwin::Terminate() {
65  running_ = false;
66  CFRunLoopStop(loop_);
67 }
68 
69 void MessageLoopDarwin::WakeUp(fml::TimePoint time_point) {
70  // Rearm the timer. The time bases used by CoreFoundation and FXL are
71  // different and must be accounted for.
72  CFRunLoopTimerSetNextFireDate(
73  delayed_wake_timer_,
74  CFAbsoluteTimeGetCurrent() + (time_point - fml::TimePoint::Now()).ToSecondsF());
75 }
76 
77 void MessageLoopDarwin::OnTimerFire(CFRunLoopTimerRef timer, MessageLoopDarwin* loop) {
78  @autoreleasepool {
79  // RunExpiredTasksNow rearms the timer as appropriate via a call to WakeUp.
80  loop->RunExpiredTasksNow();
81  }
82 }
83 
84 } // namespace fml
#define FML_DCHECK(condition)
Definition: logging.h:86
GAsyncResult * result
static CFStringRef kMessageLoopCFRunLoopMode
Definition: ascii_trie.cc:9
static constexpr CFTimeInterval kDistantFuture
static TimePoint Now()
Definition: time_point.cc:39