Bug 930939 - Move thread assertion code into APZThreadUtils and add more assertions. r=botond

This commit is contained in:
Kartikaya Gupta 2015-02-10 08:24:23 -05:00
parent d8f09bcf8d
commit b3954b6850
11 changed files with 143 additions and 85 deletions

View File

@ -12,6 +12,7 @@
#include "Layers.h" // for Layer, etc
#include "mozilla/dom/Touch.h" // for Touch
#include "mozilla/gfx/Point.h" // for Point
#include "mozilla/layers/APZThreadUtils.h" // for AssertOnCompositorThread, etc
#include "mozilla/layers/AsyncCompositionManager.h" // for ViewTransform
#include "mozilla/layers/CompositorParent.h" // for CompositorParent, etc
#include "mozilla/layers/LayerMetricsWrapper.h"
@ -159,9 +160,7 @@ APZCTreeManager::UpdateHitTestingTree(CompositorParent* aCompositor,
uint64_t aOriginatingLayersId,
uint32_t aPaintSequenceNumber)
{
if (AsyncPanZoomController::GetThreadAssertionsEnabled()) {
Compositor::AssertOnCompositorThread();
}
APZThreadUtils::AssertOnCompositorThread();
MonitorAutoLock lock(mTreeLock);
@ -556,6 +555,8 @@ APZCTreeManager::ReceiveInputEvent(InputData& aEvent,
ScrollableLayerGuid* aOutTargetGuid,
uint64_t* aOutInputBlockId)
{
APZThreadUtils::AssertOnControllerThread();
// Initialize aOutInputBlockId to a sane value, and then later we overwrite
// it if the input event goes into a block.
if (aOutInputBlockId) {
@ -862,11 +863,13 @@ APZCTreeManager::ReceiveInputEvent(WidgetInputEvent& aEvent,
ScrollableLayerGuid* aOutTargetGuid,
uint64_t* aOutInputBlockId)
{
// This function will be removed as part of bug 930939.
// This function will be removed once metro code is modified to use the
// InputData version of ReceiveInputEvent.
// In general it is preferable to use the version of ReceiveInputEvent
// that takes an InputData, as that is usable from off-main-thread.
MOZ_ASSERT(NS_IsMainThread());
APZThreadUtils::AssertOnControllerThread();
// Initialize aOutInputBlockId to a sane value, and then later we overwrite
// it if the input event goes into a block.
@ -920,6 +923,8 @@ APZCTreeManager::ZoomToRect(const ScrollableLayerGuid& aGuid,
void
APZCTreeManager::ContentReceivedInputBlock(uint64_t aInputBlockId, bool aPreventDefault)
{
APZThreadUtils::AssertOnControllerThread();
mInputQueue->ContentReceivedInputBlock(aInputBlockId, aPreventDefault);
}
@ -927,6 +932,8 @@ void
APZCTreeManager::SetTargetAPZC(uint64_t aInputBlockId,
const nsTArray<ScrollableLayerGuid>& aTargets)
{
APZThreadUtils::AssertOnControllerThread();
nsRefPtr<AsyncPanZoomController> target = nullptr;
if (aTargets.Length() > 0) {
target = GetTargetAPZC(aTargets[0]);
@ -941,6 +948,8 @@ APZCTreeManager::SetTargetAPZC(uint64_t aInputBlockId,
void
APZCTreeManager::SetTargetAPZC(uint64_t aInputBlockId, const ScrollableLayerGuid& aTarget)
{
APZThreadUtils::AssertOnControllerThread();
nsRefPtr<AsyncPanZoomController> apzc = GetTargetAPZC(aTarget);
mInputQueue->SetConfirmedTargetApzc(aInputBlockId, apzc);
}

View File

@ -137,7 +137,8 @@ public:
/**
* General handler for incoming input events. Manipulates the frame metrics
* based on what type of input it is. For example, a PinchGestureEvent will
* cause scaling. This should only be called externally to this class.
* cause scaling. This should only be called externally to this class, and
* must be called on the controller thread.
*
* This function transforms |aEvent| to have its coordinates in DOM space.
* This is so that the event can be passed through the DOM and content can
@ -182,7 +183,9 @@ public:
*
* NOTE: Be careful of invoking the WidgetInputEvent variant. This can only be
* called on the main thread. See widget/InputData.h for more information on
* why we have InputData and WidgetInputEvent separated.
* why we have InputData and WidgetInputEvent separated. If this function is
* used, the controller thread must be the main thread, or undefined behaviour
* may occur.
* NOTE: On unix, mouse events are treated as touch and are forwarded
* to the appropriate apz as such.
*
@ -213,7 +216,8 @@ public:
* If we have touch listeners, this should always be called when we know
* definitively whether or not content has preventDefaulted any touch events
* that have come in. If |aPreventDefault| is true, any touch events in the
* queue will be discarded.
* queue will be discarded. This function must be called on the controller
* thread.
*/
void ContentReceivedInputBlock(uint64_t aInputBlockId, bool aPreventDefault);
@ -300,6 +304,7 @@ public:
* corresponds to the different touch point that is currently active.
* Must be called after receiving the TOUCH_START event that starts the
* touch-session.
* This must be called on the controller thread.
*/
void SetAllowedTouchBehavior(uint64_t aInputBlockId,
const nsTArray<TouchBehaviorFlags>& aValues);

View File

@ -42,6 +42,7 @@
#include "mozilla/gfx/Rect.h" // for RoundedIn
#include "mozilla/gfx/ScaleFactor.h" // for ScaleFactor
#include "mozilla/layers/APZCTreeManager.h" // for ScrollableLayerGuid
#include "mozilla/layers/APZThreadUtils.h" // for AssertOnControllerThread, etc
#include "mozilla/layers/AsyncCompositionManager.h" // for ViewTransform
#include "mozilla/layers/AxisPhysicsModel.h" // for AxisPhysicsModel
#include "mozilla/layers/AxisPhysicsMSDModel.h" // for AxisPhysicsMSDModel
@ -433,8 +434,6 @@ static inline void LogRendertraceRect(const ScrollableLayerGuid& aGuid, const ch
}
static TimeStamp sFrameTime;
static bool sThreadAssertionsEnabled = true;
static PRThread* sControllerThread;
// Counter used to give each APZC a unique id
static uint32_t sAsyncPanZoomControllerCount = 0;
@ -824,42 +823,6 @@ AsyncPanZoomController::SetFrameTime(const TimeStamp& aTime) {
sFrameTime = aTime;
}
void
AsyncPanZoomController::SetThreadAssertionsEnabled(bool aEnabled) {
sThreadAssertionsEnabled = aEnabled;
}
bool
AsyncPanZoomController::GetThreadAssertionsEnabled() {
return sThreadAssertionsEnabled;
}
void
AsyncPanZoomController::AssertOnControllerThread() {
if (!GetThreadAssertionsEnabled()) {
return;
}
static bool sControllerThreadDetermined = false;
if (!sControllerThreadDetermined) {
// Technically this may not actually pick up the correct controller thread,
// if the first call to this method happens from a non-controller thread.
// If the assertion below fires, it is possible that it is because
// sControllerThread is not actually the controller thread.
sControllerThread = PR_GetCurrentThread();
sControllerThreadDetermined = true;
}
MOZ_ASSERT(sControllerThread == PR_GetCurrentThread());
}
void
AsyncPanZoomController::AssertOnCompositorThread()
{
if (GetThreadAssertionsEnabled()) {
Compositor::AssertOnCompositorThread();
}
}
/*static*/ void
AsyncPanZoomController::InitializeGlobalState()
{
@ -924,7 +887,7 @@ AsyncPanZoomController::~AsyncPanZoomController()
PCompositorParent*
AsyncPanZoomController::GetSharedFrameMetricsCompositor()
{
AssertOnCompositorThread();
APZThreadUtils::AssertOnCompositorThread();
if (mSharingFrameMetricsAcrossProcesses) {
const CompositorParent::LayerTreeState* state = CompositorParent::GetIndirectShadowTree(mLayersId);
@ -956,7 +919,7 @@ AsyncPanZoomController::GetInputQueue() const {
void
AsyncPanZoomController::Destroy()
{
AssertOnCompositorThread();
APZThreadUtils::AssertOnCompositorThread();
CancelAnimation();
@ -1031,7 +994,7 @@ AsyncPanZoomController::ArePointerEventsConsumable(TouchBlockState* aBlock, uint
nsEventStatus AsyncPanZoomController::HandleInputEvent(const InputData& aEvent,
const Matrix4x4& aTransformToApzc) {
AssertOnControllerThread();
APZThreadUtils::AssertOnControllerThread();
nsEventStatus rv = nsEventStatus_eIgnore;
@ -1103,7 +1066,7 @@ nsEventStatus AsyncPanZoomController::HandleInputEvent(const InputData& aEvent,
nsEventStatus AsyncPanZoomController::HandleGestureEvent(const InputData& aEvent)
{
AssertOnControllerThread();
APZThreadUtils::AssertOnControllerThread();
nsEventStatus rv = nsEventStatus_eIgnore;
@ -2466,7 +2429,7 @@ AsyncPanZoomController::FireAsyncScrollOnTimeout()
bool AsyncPanZoomController::UpdateAnimation(const TimeStamp& aSampleTime,
Vector<Task*>* aOutDeferredTasks)
{
AssertOnCompositorThread();
APZThreadUtils::AssertOnCompositorThread();
// This function may get called multiple with the same sample time, because
// there may be multiple layers with this APZC, and each layer invokes this
@ -2544,7 +2507,7 @@ Matrix4x4 AsyncPanZoomController::GetOverscrollTransform() const {
bool AsyncPanZoomController::AdvanceAnimations(const TimeStamp& aSampleTime)
{
AssertOnCompositorThread();
APZThreadUtils::AssertOnCompositorThread();
// Don't send any state-change notifications until the end of the function,
// because we may go through some intermediate states while we finish
@ -2691,7 +2654,7 @@ bool AsyncPanZoomController::IsCurrentlyCheckerboarding() const {
}
void AsyncPanZoomController::NotifyLayersUpdated(const FrameMetrics& aLayerMetrics, bool aIsFirstPaint) {
AssertOnCompositorThread();
APZThreadUtils::AssertOnCompositorThread();
ReentrantMonitorAutoEnter lock(mMonitor);
bool isDefault = mFrameMetrics.IsDefault();
@ -3067,7 +3030,7 @@ AsyncPanZoomController::GetZoomConstraints() const
void AsyncPanZoomController::PostDelayedTask(Task* aTask, int aDelayMs) {
AssertOnControllerThread();
APZThreadUtils::AssertOnControllerThread();
nsRefPtr<GeckoContentController> controller = GetGeckoContentController();
if (controller) {
controller->PostDelayedTask(aTask, aDelayMs);

View File

@ -1040,25 +1040,6 @@ public:
* animations to the same timestamp.
*/
static void SetFrameTime(const TimeStamp& aMilliseconds);
/**
* In the gtest environment everything runs on one thread, so we
* shouldn't assert that we're on a particular thread. This enables
* that behaviour.
*/
static void SetThreadAssertionsEnabled(bool aEnabled);
static bool GetThreadAssertionsEnabled();
/**
* This can be used to assert that the current thread is the
* controller/UI thread (on which input events are received).
* This does nothing if thread assertions are disabled.
*/
static void AssertOnControllerThread();
/**
* This can be used to assert that the current thread is the
* compositor thread (which applies the async transform).
* This does nothing if thread assertions are disabled.
*/
static void AssertOnCompositorThread();
/**
* Set an extra offset for testing async scrolling.
*/

View File

@ -10,6 +10,7 @@
#include "AsyncPanZoomController.h" // for AsyncPanZoomController
#include "mozilla/dom/AnimationPlayer.h" // for ComputedTimingFunction
#include "mozilla/layers/APZCTreeManager.h" // for APZCTreeManager
#include "mozilla/layers/APZThreadUtils.h" // for AssertOnControllerThread
#include "FrameMetrics.h" // for FrameMetrics
#include "mozilla/Attributes.h" // for MOZ_FINAL
#include "mozilla/Preferences.h" // for Preferences
@ -58,7 +59,7 @@ float Axis::ToLocalVelocity(float aVelocityInchesPerMs) const {
void Axis::UpdateWithTouchAtDevicePoint(ParentLayerCoord aPos, uint32_t aTimestampMs) {
// mVelocityQueue is controller-thread only
AsyncPanZoomController::AssertOnControllerThread();
APZThreadUtils::AssertOnControllerThread();
if (aTimestampMs == mPosTimeMs) {
// This could be a duplicate event, or it could be a legitimate event
@ -331,7 +332,7 @@ ParentLayerCoord Axis::PanDistance(ParentLayerCoord aPos) const {
void Axis::EndTouch(uint32_t aTimestampMs) {
// mVelocityQueue is controller-thread only
AsyncPanZoomController::AssertOnControllerThread();
APZThreadUtils::AssertOnControllerThread();
mVelocity = 0;
int count = 0;
@ -352,7 +353,7 @@ void Axis::EndTouch(uint32_t aTimestampMs) {
void Axis::CancelTouch() {
// mVelocityQueue is controller-thread only
AsyncPanZoomController::AssertOnControllerThread();
APZThreadUtils::AssertOnControllerThread();
AXIS_LOG("%p|%s cancelling touch, clearing velocity queue\n",
mAsyncPanZoomController, Name());

View File

@ -9,6 +9,7 @@
#include "AsyncPanZoomController.h" // for AsyncPanZoomController
#include "LayersLogging.h" // for Stringify
#include "mozilla/gfx/Point.h" // for Point4D
#include "mozilla/layers/APZThreadUtils.h" // for AssertOnCompositorThread
#include "mozilla/layers/AsyncCompositionManager.h" // for ViewTransform::operator Matrix4x4()
#include "nsPrintfCString.h" // for nsPrintfCString
#include "UnitTransforms.h" // for ViewAs
@ -43,7 +44,7 @@ HitTestingTreeNode::~HitTestingTreeNode()
void
HitTestingTreeNode::Destroy()
{
AsyncPanZoomController::AssertOnCompositorThread();
APZThreadUtils::AssertOnCompositorThread();
mPrevSibling = nullptr;
mLastChild = nullptr;

View File

@ -10,6 +10,7 @@
#include "gfxPrefs.h"
#include "InputBlockState.h"
#include "LayersLogging.h"
#include "mozilla/layers/APZThreadUtils.h"
#include "OverscrollHandoffState.h"
#define INPQ_LOG(...)
@ -31,7 +32,7 @@ InputQueue::ReceiveInputEvent(const nsRefPtr<AsyncPanZoomController>& aTarget,
bool aTargetConfirmed,
const InputData& aEvent,
uint64_t* aOutInputBlockId) {
AsyncPanZoomController::AssertOnControllerThread();
APZThreadUtils::AssertOnControllerThread();
switch (aEvent.mInputType) {
case MULTITOUCH_INPUT: {
@ -266,7 +267,7 @@ InputQueue::StartNewTouchBlock(const nsRefPtr<AsyncPanZoomController>& aTarget,
CancelableBlockState*
InputQueue::CurrentBlock() const
{
AsyncPanZoomController::AssertOnControllerThread();
APZThreadUtils::AssertOnControllerThread();
MOZ_ASSERT(!mInputBlockQueue.IsEmpty());
return mInputBlockQueue[0].get();
@ -298,7 +299,7 @@ InputQueue::ScheduleMainThreadTimeout(const nsRefPtr<AsyncPanZoomController>& aT
void
InputQueue::MainThreadTimeout(const uint64_t& aInputBlockId) {
AsyncPanZoomController::AssertOnControllerThread();
APZThreadUtils::AssertOnControllerThread();
INPQ_LOG("got a main thread timeout; block=%" PRIu64 "\n", aInputBlockId);
bool success = false;
@ -319,7 +320,7 @@ InputQueue::MainThreadTimeout(const uint64_t& aInputBlockId) {
void
InputQueue::ContentReceivedInputBlock(uint64_t aInputBlockId, bool aPreventDefault) {
AsyncPanZoomController::AssertOnControllerThread();
APZThreadUtils::AssertOnControllerThread();
INPQ_LOG("got a content response; block=%" PRIu64 "\n", aInputBlockId);
bool success = false;
@ -337,7 +338,7 @@ InputQueue::ContentReceivedInputBlock(uint64_t aInputBlockId, bool aPreventDefau
void
InputQueue::SetConfirmedTargetApzc(uint64_t aInputBlockId, const nsRefPtr<AsyncPanZoomController>& aTargetApzc) {
AsyncPanZoomController::AssertOnControllerThread();
APZThreadUtils::AssertOnControllerThread();
INPQ_LOG("got a target apzc; block=%" PRIu64 " guid=%s\n",
aInputBlockId, aTargetApzc ? Stringify(aTargetApzc->GetGuid()).c_str() : "");
@ -357,7 +358,7 @@ InputQueue::SetConfirmedTargetApzc(uint64_t aInputBlockId, const nsRefPtr<AsyncP
void
InputQueue::SetAllowedTouchBehavior(uint64_t aInputBlockId, const nsTArray<TouchBehaviorFlags>& aBehaviors) {
AsyncPanZoomController::AssertOnControllerThread();
APZThreadUtils::AssertOnControllerThread();
INPQ_LOG("got allowed touch behaviours; block=%" PRIu64 "\n", aInputBlockId);
bool success = false;
@ -381,7 +382,7 @@ InputQueue::SetAllowedTouchBehavior(uint64_t aInputBlockId, const nsTArray<Touch
void
InputQueue::ProcessInputBlocks() {
AsyncPanZoomController::AssertOnControllerThread();
APZThreadUtils::AssertOnControllerThread();
do {
CancelableBlockState* curBlock = CurrentBlock();

View File

@ -0,0 +1,53 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/layers/APZThreadUtils.h"
#include "mozilla/layers/Compositor.h"
namespace mozilla {
namespace layers {
static bool sThreadAssertionsEnabled = true;
static PRThread* sControllerThread;
/*static*/ void
APZThreadUtils::SetThreadAssertionsEnabled(bool aEnabled) {
sThreadAssertionsEnabled = aEnabled;
}
/*static*/ bool
APZThreadUtils::GetThreadAssertionsEnabled() {
return sThreadAssertionsEnabled;
}
/*static*/ void
APZThreadUtils::AssertOnControllerThread() {
if (!GetThreadAssertionsEnabled()) {
return;
}
static bool sControllerThreadDetermined = false;
if (!sControllerThreadDetermined) {
// Technically this may not actually pick up the correct controller thread,
// if the first call to this method happens from a non-controller thread.
// If the assertion below fires, it is possible that it is because
// sControllerThread is not actually the controller thread.
sControllerThread = PR_GetCurrentThread();
sControllerThreadDetermined = true;
}
MOZ_ASSERT(sControllerThread == PR_GetCurrentThread());
}
/*static*/ void
APZThreadUtils::AssertOnCompositorThread()
{
if (GetThreadAssertionsEnabled()) {
Compositor::AssertOnCompositorThread();
}
}
} // namespace layers
} // namespace mozilla

View File

@ -0,0 +1,41 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_layers_APZThreadUtils_h
#define mozilla_layers_APZThreadUtils_h
namespace mozilla {
namespace layers {
class APZThreadUtils
{
public:
/**
* In the gtest environment everything runs on one thread, so we
* shouldn't assert that we're on a particular thread. This enables
* that behaviour.
*/
static void SetThreadAssertionsEnabled(bool aEnabled);
static bool GetThreadAssertionsEnabled();
/**
* This can be used to assert that the current thread is the
* controller/UI thread (on which input events are received).
* This does nothing if thread assertions are disabled.
*/
static void AssertOnControllerThread();
/**
* This can be used to assert that the current thread is the
* compositor thread (which applies the async transform).
* This does nothing if thread assertions are disabled.
*/
static void AssertOnCompositorThread();
};
} // namespace layers
} // namespace mozilla
#endif /* mozilla_layers_APZThreadUtils_h */

View File

@ -92,6 +92,7 @@ EXPORTS.mozilla.layers += [
'apz/testutil/APZTestData.h',
'apz/util/ActiveElementManager.h',
'apz/util/APZCCallbackHelper.h',
'apz/util/APZThreadUtils.h',
'apz/util/ChromeProcessController.h',
'apz/util/InputAPZContext.h',
'AtomicRefCountedWithFinalize.h',
@ -226,6 +227,7 @@ UNIFIED_SOURCES += [
'apz/testutil/APZTestData.cpp',
'apz/util/ActiveElementManager.cpp',
'apz/util/APZCCallbackHelper.cpp',
'apz/util/APZThreadUtils.cpp',
'apz/util/ChromeProcessController.cpp',
'apz/util/InputAPZContext.cpp',
'AxisPhysicsModel.cpp',

View File

@ -12,6 +12,7 @@
#include "mozilla/layers/CompositorParent.h"
#include "mozilla/layers/APZCTreeManager.h"
#include "mozilla/layers/LayerMetricsWrapper.h"
#include "mozilla/layers/APZThreadUtils.h"
#include "mozilla/UniquePtr.h"
#include "apz/src/AsyncPanZoomController.h"
#include "apz/src/HitTestingTreeNode.h"
@ -243,7 +244,7 @@ protected:
virtual void SetUp()
{
gfxPrefs::GetSingleton();
AsyncPanZoomController::SetThreadAssertionsEnabled(false);
APZThreadUtils::SetThreadAssertionsEnabled(false);
testStartTime = TimeStamp::Now();
AsyncPanZoomController::SetFrameTime(testStartTime);
@ -1655,7 +1656,7 @@ class APZCTreeManagerTester : public ::testing::Test {
protected:
virtual void SetUp() {
gfxPrefs::GetSingleton();
AsyncPanZoomController::SetThreadAssertionsEnabled(false);
APZThreadUtils::SetThreadAssertionsEnabled(false);
testStartTime = TimeStamp::Now();
AsyncPanZoomController::SetFrameTime(testStartTime);