109 lines
3.0 KiB
C++
109 lines
3.0 KiB
C++
// Copyright (c) 2016 The Chromium Embedded Framework 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 "tests/shared/browser/main_message_loop_external_pump.h"
|
|
|
|
#include <climits>
|
|
|
|
#include "include/cef_app.h"
|
|
#include "include/wrapper/cef_helpers.h"
|
|
#include "tests/shared/browser/main_message_loop.h"
|
|
|
|
namespace client {
|
|
|
|
namespace {
|
|
|
|
// Special timer delay placeholder value. Intentionally 32-bit for Windows and
|
|
// OS X platform API compatibility.
|
|
const int32_t kTimerDelayPlaceholder = INT_MAX;
|
|
|
|
// The maximum number of milliseconds we're willing to wait between calls to
|
|
// DoWork().
|
|
const int64_t kMaxTimerDelay = 1000 / 30; // 30fps
|
|
|
|
client::MainMessageLoopExternalPump* g_external_message_pump = nullptr;
|
|
|
|
} // namespace
|
|
|
|
MainMessageLoopExternalPump::MainMessageLoopExternalPump()
|
|
: is_active_(false), reentrancy_detected_(false) {
|
|
DCHECK(!g_external_message_pump);
|
|
g_external_message_pump = this;
|
|
}
|
|
|
|
MainMessageLoopExternalPump::~MainMessageLoopExternalPump() {
|
|
g_external_message_pump = nullptr;
|
|
}
|
|
|
|
MainMessageLoopExternalPump* MainMessageLoopExternalPump::Get() {
|
|
return g_external_message_pump;
|
|
}
|
|
|
|
void MainMessageLoopExternalPump::OnScheduleWork(int64_t delay_ms) {
|
|
REQUIRE_MAIN_THREAD();
|
|
|
|
if (delay_ms == kTimerDelayPlaceholder && IsTimerPending()) {
|
|
// Don't set the maximum timer requested from DoWork() if a timer event is
|
|
// currently pending.
|
|
return;
|
|
}
|
|
|
|
KillTimer();
|
|
|
|
if (delay_ms <= 0) {
|
|
// Execute the work immediately.
|
|
DoWork();
|
|
} else {
|
|
// Never wait longer than the maximum allowed time.
|
|
if (delay_ms > kMaxTimerDelay) {
|
|
delay_ms = kMaxTimerDelay;
|
|
}
|
|
|
|
// Results in call to OnTimerTimeout() after the specified delay.
|
|
SetTimer(delay_ms);
|
|
}
|
|
}
|
|
|
|
void MainMessageLoopExternalPump::OnTimerTimeout() {
|
|
REQUIRE_MAIN_THREAD();
|
|
|
|
KillTimer();
|
|
DoWork();
|
|
}
|
|
|
|
void MainMessageLoopExternalPump::DoWork() {
|
|
const bool was_reentrant = PerformMessageLoopWork();
|
|
if (was_reentrant) {
|
|
// Execute the remaining work as soon as possible.
|
|
OnScheduleMessagePumpWork(0);
|
|
} else if (!IsTimerPending()) {
|
|
// Schedule a timer event at the maximum allowed time. This may be dropped
|
|
// in OnScheduleWork() if another timer event is already in-flight.
|
|
OnScheduleMessagePumpWork(kTimerDelayPlaceholder);
|
|
}
|
|
}
|
|
|
|
bool MainMessageLoopExternalPump::PerformMessageLoopWork() {
|
|
if (is_active_) {
|
|
// When CefDoMessageLoopWork() is called there may be various callbacks
|
|
// (such as paint and IPC messages) that result in additional calls to this
|
|
// method. If re-entrancy is detected we must repost a request again to the
|
|
// owner thread to ensure that the discarded call is executed in the future.
|
|
reentrancy_detected_ = true;
|
|
return false;
|
|
}
|
|
|
|
reentrancy_detected_ = false;
|
|
|
|
is_active_ = true;
|
|
CefDoMessageLoopWork();
|
|
is_active_ = false;
|
|
|
|
// |reentrancy_detected_| may have changed due to re-entrant calls to this
|
|
// method.
|
|
return reentrancy_detected_;
|
|
}
|
|
|
|
} // namespace client
|