message_loop_darwin.mm 2.4 KB
Newer Older
C
Chinmay Garde 已提交
1 2 3 4 5 6
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "flutter/fml/platform/darwin/message_loop_darwin.h"

7
#include <CoreFoundation/CFRunLoop.h>
C
Chinmay Garde 已提交
8 9 10 11 12 13 14 15
#include <Foundation/Foundation.h>

namespace fml {

static constexpr CFTimeInterval kDistantFuture = 1.0e10;

MessageLoopDarwin::MessageLoopDarwin()
    : running_(false), loop_((CFRunLoopRef)CFRetain(CFRunLoopGetCurrent())) {
16
  FXL_DCHECK(loop_ != nullptr);
C
Chinmay Garde 已提交
17 18 19 20 21

  // Setup the delayed wake source.
  CFRunLoopTimerContext timer_context = {
      .info = this,
  };
22 23 24 25 26 27
  delayed_wake_timer_.Reset(
      CFRunLoopTimerCreate(kCFAllocatorDefault, kDistantFuture /* fire date */,
                           HUGE_VAL /* interval */, 0 /* flags */, 0 /* order */,
                           reinterpret_cast<CFRunLoopTimerCallBack>(&MessageLoopDarwin::OnTimerFire)
                           /* callout */,
                           &timer_context /* context */));
28
  FXL_DCHECK(delayed_wake_timer_ != nullptr);
C
Chinmay Garde 已提交
29 30 31 32 33 34 35 36 37
  CFRunLoopAddTimer(loop_, delayed_wake_timer_, kCFRunLoopCommonModes);
}

MessageLoopDarwin::~MessageLoopDarwin() {
  CFRunLoopTimerInvalidate(delayed_wake_timer_);
  CFRunLoopRemoveTimer(loop_, delayed_wake_timer_, kCFRunLoopCommonModes);
}

void MessageLoopDarwin::Run() {
38
  FXL_DCHECK(loop_ == CFRunLoopGetCurrent());
C
Chinmay Garde 已提交
39 40 41 42 43

  running_ = true;

  while (running_) {
    @autoreleasepool {
44
      int result = CFRunLoopRunInMode(kCFRunLoopDefaultMode, kDistantFuture, YES);
C
Chinmay Garde 已提交
45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
      if (result == kCFRunLoopRunStopped || result == kCFRunLoopRunFinished) {
        // This handles the case where the loop is terminated using
        // CoreFoundation APIs.
        @autoreleasepool {
          RunExpiredTasksNow();
        }
        running_ = false;
      }
    }
  }
}

void MessageLoopDarwin::Terminate() {
  running_ = false;
  CFRunLoopStop(loop_);
}

62 63
void MessageLoopDarwin::WakeUp(fxl::TimePoint time_point) {
  // Rearm the timer. The time bases used by CoreFoundation and FXL are
C
Chinmay Garde 已提交
64 65 66
  // different and must be accounted for.
  CFRunLoopTimerSetNextFireDate(
      delayed_wake_timer_,
67
      CFAbsoluteTimeGetCurrent() + (time_point - fxl::TimePoint::Now()).ToSecondsF());
C
Chinmay Garde 已提交
68 69
}

70
void MessageLoopDarwin::OnTimerFire(CFRunLoopTimerRef timer, MessageLoopDarwin* loop) {
C
Chinmay Garde 已提交
71 72 73 74 75 76 77
  @autoreleasepool {
    // RunExpiredTasksNow rearms the timer as appropriate via a call to WakeUp.
    loop->RunExpiredTasksNow();
  }
}

}  // namespace fml