Commit 8bcf27f1 authored by csharrison's avatar csharrison Committed by Commit bot

UserGestureIndicator: remove many unnecessary calls to isMainThread

Most code that calls the UserGestureIndicator knows which thread it is
executing in. Calling isMainThread involves doing a thread id syscall which
can be quite slow, and there are places in the loading code that do this
in a tight loop (e.g. preloading resources).

This patch adds an optional argument to the indicator's static methods which
optionally allow callers to get the gesture state in a thread-safe way.

BUG=348655

Review-Url: https://codereview.chromium.org/2555013004
Cr-Commit-Position: refs/heads/master@{#437941}
parent c592ff89
...@@ -102,7 +102,7 @@ bool RequestSender::StartRequest(Source* source, ...@@ -102,7 +102,7 @@ bool RequestSender::StartRequest(Source* source,
params.request_id = request_id; params.request_id = request_id;
params.has_callback = has_callback; params.has_callback = has_callback;
params.user_gesture = params.user_gesture =
blink::WebUserGestureIndicator::isProcessingUserGesture(); blink::WebUserGestureIndicator::isProcessingUserGestureThreadSafe();
// Set Service Worker specific params to default values. // Set Service Worker specific params to default values.
params.worker_thread_id = -1; params.worker_thread_id = -1;
......
...@@ -47,7 +47,7 @@ static const double oneMillisecond = 0.001; ...@@ -47,7 +47,7 @@ static const double oneMillisecond = 0.001;
static const double minimumInterval = 0.004; static const double minimumInterval = 0.004;
static inline bool shouldForwardUserGesture(int interval, int nestingLevel) { static inline bool shouldForwardUserGesture(int interval, int nestingLevel) {
return UserGestureIndicator::processingUserGesture() && return UserGestureIndicator::processingUserGestureThreadSafe() &&
interval <= maxIntervalForUserGestureForwarding && interval <= maxIntervalForUserGestureForwarding &&
nestingLevel == nestingLevel ==
1; // Gestures should not be forwarded to nested timers. 1; // Gestures should not be forwarded to nested timers.
...@@ -90,8 +90,11 @@ DOMTimer::DOMTimer(ExecutionContext* context, ...@@ -90,8 +90,11 @@ DOMTimer::DOMTimer(ExecutionContext* context,
m_nestingLevel(context->timers()->timerNestingLevel() + 1), m_nestingLevel(context->timers()->timerNestingLevel() + 1),
m_action(action) { m_action(action) {
ASSERT(timeoutID > 0); ASSERT(timeoutID > 0);
if (shouldForwardUserGesture(interval, m_nestingLevel)) if (shouldForwardUserGesture(interval, m_nestingLevel)) {
// Thread safe because shouldForwardUserGesture will only return true if
// execution is on the the main thread.
m_userGestureToken = UserGestureIndicator::currentToken(); m_userGestureToken = UserGestureIndicator::currentToken();
}
InspectorInstrumentation::asyncTaskScheduled( InspectorInstrumentation::asyncTaskScheduled(
context, singleShot ? "setTimeout" : "setInterval", this, !singleShot); context, singleShot ? "setTimeout" : "setInterval", this, !singleShot);
......
...@@ -156,7 +156,7 @@ ScriptPromise Permissions::request(ScriptState* scriptState, ...@@ -156,7 +156,7 @@ ScriptPromise Permissions::request(ScriptState* scriptState,
service->RequestPermission( service->RequestPermission(
std::move(descriptor), std::move(descriptor),
scriptState->getExecutionContext()->getSecurityOrigin(), scriptState->getExecutionContext()->getSecurityOrigin(),
UserGestureIndicator::processingUserGesture(), UserGestureIndicator::processingUserGestureThreadSafe(),
convertToBaseCallback(WTF::bind( convertToBaseCallback(WTF::bind(
&Permissions::taskComplete, wrapPersistent(this), &Permissions::taskComplete, wrapPersistent(this),
wrapPersistent(resolver), WTF::passed(std::move(descriptorCopy))))); wrapPersistent(resolver), WTF::passed(std::move(descriptorCopy)))));
...@@ -247,7 +247,7 @@ ScriptPromise Permissions::requestAll( ...@@ -247,7 +247,7 @@ ScriptPromise Permissions::requestAll(
service->RequestPermissions( service->RequestPermissions(
std::move(internalPermissions), std::move(internalPermissions),
scriptState->getExecutionContext()->getSecurityOrigin(), scriptState->getExecutionContext()->getSecurityOrigin(),
UserGestureIndicator::processingUserGesture(), UserGestureIndicator::processingUserGestureThreadSafe(),
convertToBaseCallback( convertToBaseCallback(
WTF::bind(&Permissions::batchTaskComplete, wrapPersistent(this), WTF::bind(&Permissions::batchTaskComplete, wrapPersistent(this),
wrapPersistent(resolver), wrapPersistent(resolver),
......
...@@ -42,7 +42,7 @@ UserGestureToken::UserGestureToken(Status status) ...@@ -42,7 +42,7 @@ UserGestureToken::UserGestureToken(Status status)
m_timestamp(WTF::currentTime()), m_timestamp(WTF::currentTime()),
m_timeoutPolicy(Default), m_timeoutPolicy(Default),
m_usageCallback(nullptr) { m_usageCallback(nullptr) {
if (status == NewGesture || !UserGestureIndicator::currentToken()) if (status == NewGesture || !UserGestureIndicator::currentTokenThreadSafe())
m_consumableGestures++; m_consumableGestures++;
} }
...@@ -151,18 +151,18 @@ bool UserGestureIndicator::utilizeUserGesture() { ...@@ -151,18 +151,18 @@ bool UserGestureIndicator::utilizeUserGesture() {
} }
bool UserGestureIndicator::processingUserGesture() { bool UserGestureIndicator::processingUserGesture() {
if (auto* token = currentToken()) { if (auto* token = currentToken())
ASSERT(isMainThread());
return token->hasGestures(); return token->hasGestures();
}
return false; return false;
} }
bool UserGestureIndicator::processingUserGestureThreadSafe() {
return isMainThread() && processingUserGesture();
}
// static // static
bool UserGestureIndicator::consumeUserGesture() { bool UserGestureIndicator::consumeUserGesture() {
if (auto* token = currentToken()) { if (auto* token = currentToken()) {
ASSERT(isMainThread());
if (token->consumeGesture()) { if (token->consumeGesture()) {
token->userGestureUtilized(); token->userGestureUtilized();
return true; return true;
...@@ -171,11 +171,17 @@ bool UserGestureIndicator::consumeUserGesture() { ...@@ -171,11 +171,17 @@ bool UserGestureIndicator::consumeUserGesture() {
return false; return false;
} }
// static bool UserGestureIndicator::consumeUserGestureThreadSafe() {
return isMainThread() && consumeUserGesture();
}
UserGestureToken* UserGestureIndicator::currentToken() { UserGestureToken* UserGestureIndicator::currentToken() {
if (!isMainThread() || !s_rootToken) DCHECK(isMainThread());
return nullptr;
return s_rootToken; return s_rootToken;
} }
UserGestureToken* UserGestureIndicator::currentTokenThreadSafe() {
return isMainThread() ? currentToken() : nullptr;
}
} // namespace blink } // namespace blink
...@@ -94,11 +94,17 @@ class PLATFORM_EXPORT UserGestureIndicator final { ...@@ -94,11 +94,17 @@ class PLATFORM_EXPORT UserGestureIndicator final {
WTF_MAKE_NONCOPYABLE(UserGestureIndicator); WTF_MAKE_NONCOPYABLE(UserGestureIndicator);
public: public:
// Note: All *ThreadSafe methods are safe to call from any thread. Their
// non-suffixed counterparts *must* be called on the main thread. Consider
// always using the non-suffixed one unless the code really
// needs to be thread-safe
// Returns whether a user gesture is currently in progress. // Returns whether a user gesture is currently in progress.
// Does not invoke the UserGestureUtilizedCallback. Consider calling // Does not invoke the UserGestureUtilizedCallback. Consider calling
// utilizeUserGesture instead if you know for sure that the return value // utilizeUserGesture instead if you know for sure that the return value
// will have an effect. // will have an effect.
static bool processingUserGesture(); static bool processingUserGesture();
static bool processingUserGestureThreadSafe();
// Indicates that a user gesture (if any) is being used, without preventing it // Indicates that a user gesture (if any) is being used, without preventing it
// from being used again. Returns whether a user gesture is currently in // from being used again. Returns whether a user gesture is currently in
...@@ -111,8 +117,10 @@ class PLATFORM_EXPORT UserGestureIndicator final { ...@@ -111,8 +117,10 @@ class PLATFORM_EXPORT UserGestureIndicator final {
// operations like creating a new process. // operations like creating a new process.
// Like utilizeUserGesture, may invoke/clear any UserGestureUtilizedCallback. // Like utilizeUserGesture, may invoke/clear any UserGestureUtilizedCallback.
static bool consumeUserGesture(); static bool consumeUserGesture();
static bool consumeUserGestureThreadSafe();
static UserGestureToken* currentToken(); static UserGestureToken* currentToken();
static UserGestureToken* currentTokenThreadSafe();
explicit UserGestureIndicator(PassRefPtr<UserGestureToken>); explicit UserGestureIndicator(PassRefPtr<UserGestureToken>);
~UserGestureIndicator(); ~UserGestureIndicator();
......
...@@ -40,8 +40,15 @@ bool WebUserGestureIndicator::isProcessingUserGesture() { ...@@ -40,8 +40,15 @@ bool WebUserGestureIndicator::isProcessingUserGesture() {
return UserGestureIndicator::processingUserGesture(); return UserGestureIndicator::processingUserGesture();
} }
bool WebUserGestureIndicator::isProcessingUserGestureThreadSafe() {
return UserGestureIndicator::processingUserGestureThreadSafe();
}
// TODO(csharrison): consumeUserGesture() and currentUserGestureToken() use
// the thread-safe API, which many callers probably do not need. Consider
// updating them if they are in any sort of critical path or called often.
bool WebUserGestureIndicator::consumeUserGesture() { bool WebUserGestureIndicator::consumeUserGesture() {
return UserGestureIndicator::consumeUserGesture(); return UserGestureIndicator::consumeUserGestureThreadSafe();
} }
bool WebUserGestureIndicator::processedUserGestureSinceLoad( bool WebUserGestureIndicator::processedUserGestureSinceLoad(
...@@ -51,7 +58,7 @@ bool WebUserGestureIndicator::processedUserGestureSinceLoad( ...@@ -51,7 +58,7 @@ bool WebUserGestureIndicator::processedUserGestureSinceLoad(
} }
WebUserGestureToken WebUserGestureIndicator::currentUserGestureToken() { WebUserGestureToken WebUserGestureIndicator::currentUserGestureToken() {
return WebUserGestureToken(UserGestureIndicator::currentToken()); return WebUserGestureToken(UserGestureIndicator::currentTokenThreadSafe());
} }
} // namespace blink } // namespace blink
...@@ -40,8 +40,13 @@ class WebUserGestureToken; ...@@ -40,8 +40,13 @@ class WebUserGestureToken;
class WebUserGestureIndicator { class WebUserGestureIndicator {
public: public:
// Returns true if a user gesture is currently being processed. // Returns true if a user gesture is currently being processed. Must be called
// on the main thread.
BLINK_EXPORT static bool isProcessingUserGesture(); BLINK_EXPORT static bool isProcessingUserGesture();
// Can be called from any thread. Note that this is slower than the non
// thread-safe version due to thread id lookups. Prefer the non thread-safe
// version for code that will only execute on the main thread.
BLINK_EXPORT static bool isProcessingUserGestureThreadSafe();
// Returns true if a consumable gesture exists and has been successfully // Returns true if a consumable gesture exists and has been successfully
// consumed. // consumed.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment