flutter_flutter/third_party/tonic/dart_microtask_queue.cc
Chris Bracken 08dabe9601
Clean up C++ includes (#21127)
Cleans up header order/grouping for consistency: associated header, C/C++ system/standard library headers, library headers, platform-specific #includes.

Adds <cstring> where strlen, memcpy are being used: there are a bunch of places we use them transitively.

Applies linter-required cleanups. Disables linter on one file due to included RapidJson header. See https://github.com/flutter/flutter/issues/65676

This patch does not cover flutter/shell/platform/darwin. There's a separate, slightly more intensive cleanup for those in progress.
2020-09-11 21:18:35 -07:00

108 lines
2.6 KiB
C++

// Copyright 2013 The Flutter 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 "tonic/dart_microtask_queue.h"
#include "tonic/common/build_config.h"
#include "tonic/dart_state.h"
#include "tonic/logging/dart_invoke.h"
#ifdef OS_IOS
#include <pthread.h>
#endif // OS_IOS
namespace tonic {
namespace {
#ifdef OS_IOS
// iOS doesn't support the thread_local keyword.
pthread_key_t g_queue_key;
pthread_once_t g_queue_key_once = PTHREAD_ONCE_INIT;
void MakeKey() {
pthread_key_create(&g_queue_key, nullptr);
}
void SetQueue(DartMicrotaskQueue* queue) {
pthread_once(&g_queue_key_once, MakeKey);
pthread_setspecific(g_queue_key, queue);
}
DartMicrotaskQueue* GetQueue() {
return static_cast<tonic::DartMicrotaskQueue*>(
pthread_getspecific(g_queue_key));
}
#else
thread_local DartMicrotaskQueue* g_queue = nullptr;
void SetQueue(DartMicrotaskQueue* queue) {
g_queue = queue;
}
DartMicrotaskQueue* GetQueue() {
return g_queue;
}
#endif
} // namespace
DartMicrotaskQueue::DartMicrotaskQueue() : last_error_(kNoError) {}
DartMicrotaskQueue::~DartMicrotaskQueue() = default;
void DartMicrotaskQueue::StartForCurrentThread() {
SetQueue(new DartMicrotaskQueue());
}
DartMicrotaskQueue* DartMicrotaskQueue::GetForCurrentThread() {
return GetQueue();
}
void DartMicrotaskQueue::ScheduleMicrotask(Dart_Handle callback) {
queue_.emplace_back(DartState::Current(), callback);
}
void DartMicrotaskQueue::RunMicrotasks() {
while (!queue_.empty()) {
MicrotaskQueue local;
std::swap(queue_, local);
for (const auto& callback : local) {
if (auto dart_state = callback.dart_state().lock()) {
DartState::Scope dart_scope(dart_state.get());
Dart_Handle result = Dart_InvokeClosure(callback.value(), 0, nullptr);
// If the Dart program has set a return code, then it is intending to
// shut down by way of a fatal error, and so there is no need to emit a
// log message.
if (!dart_state->has_set_return_code() || !Dart_IsError(result) ||
!Dart_IsFatalError(result)) {
LogIfError(result);
}
DartErrorHandleType error = GetErrorHandleType(result);
if (error != kNoError) {
last_error_ = error;
}
dart_state->MessageEpilogue(result);
if (!Dart_CurrentIsolate())
return;
}
}
}
}
void DartMicrotaskQueue::Destroy() {
TONIC_DCHECK(this == GetForCurrentThread());
SetQueue(nullptr);
delete this;
}
DartErrorHandleType DartMicrotaskQueue::GetLastError() {
return last_error_;
}
} // namespace tonic