зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1612799 - FailureLatch - r=canaltinova
The FailureLatch interface, and some implementation helpers and classes, will be used to record the first failure (if any) during some long process. Differential Revision: https://phabricator.services.mozilla.com/D155647
This commit is contained in:
Родитель
33130e1db4
Коммит
de815dbad9
|
@ -93,6 +93,7 @@ EXPORTS.mozilla += [
|
|||
"public/BaseProfilerState.h",
|
||||
"public/BaseProfilerUtils.h",
|
||||
"public/BlocksRingBuffer.h",
|
||||
"public/FailureLatch.h",
|
||||
"public/leb128iterator.h",
|
||||
"public/ModuloBuffer.h",
|
||||
"public/PowerOfTwo.h",
|
||||
|
|
|
@ -0,0 +1,217 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* 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/. */
|
||||
|
||||
// This header contains an interface `FailureLatch`, and some implementation
|
||||
// helpers that may be used across a range of classes and functions to handle
|
||||
// failures at any point during a process, and share that failure state so that
|
||||
// the process may gracefully stop quickly and report the first error.
|
||||
//
|
||||
// It could be thought as a replacement for C++ exceptions, but it's less strong
|
||||
// (cancellations may be delayed).
|
||||
// Now, if possible, mozilla::Result may be a better option as C++ exceptions
|
||||
// replacement, as it is more visible in all affected functions.
|
||||
// Consider FailureLatch if failures may happen in different places, but where
|
||||
// `return`ing this potential failure from all functions would be too arduous.
|
||||
|
||||
#ifndef mozilla_FailureLatch_h
|
||||
#define mozilla_FailureLatch_h
|
||||
|
||||
#include <mozilla/Assertions.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Main interface
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// Interface handling a failure latch (starting in a successful state, the first
|
||||
// failure gets recorded, subsequent failures are ignored.)
|
||||
class FailureLatch {
|
||||
public:
|
||||
virtual ~FailureLatch() = default;
|
||||
|
||||
// Can this ever fail? (This may influence how some code deals with
|
||||
// failures, e.g., if infallible, OOMs should assert&crash.)
|
||||
[[nodiscard]] virtual bool Fallible() const = 0;
|
||||
|
||||
// Set latch in its failed state because of an external cause.
|
||||
// The first call sets the reason, subsequent calls are ignored.
|
||||
virtual void SetFailure(std::string aReason) = 0;
|
||||
|
||||
// Has there been any failure so far?
|
||||
[[nodiscard]] virtual bool Failed() const = 0;
|
||||
|
||||
// Return first failure string, may be null if not failed yet.
|
||||
[[nodiscard]] virtual const char* GetFailure() const = 0;
|
||||
|
||||
// Retrieve the one source FailureLatch. It could reference `*this`!
|
||||
// This may be used by dependent proxy FailureLatch'es to find where to
|
||||
// redirect calls.
|
||||
[[nodiscard]] virtual const FailureLatch& SourceFailureLatch() const = 0;
|
||||
[[nodiscard]] virtual FailureLatch& SourceFailureLatch() = 0;
|
||||
|
||||
// Non-virtual helpers.
|
||||
|
||||
// Transfer any failure from another FailureLatch.
|
||||
void SetFailureFrom(const FailureLatch& aOther) {
|
||||
if (Failed()) {
|
||||
return;
|
||||
}
|
||||
if (const char* otherFailure = aOther.GetFailure(); otherFailure) {
|
||||
SetFailure(otherFailure);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Concrete implementations
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// Concrete infallible FailureLatch class.
|
||||
// Any `SetFailure` leads to an assert-crash, so the final runtime result can
|
||||
// always be assumed to be succesful.
|
||||
class FailureLatchInfallibleSource final : public FailureLatch {
|
||||
public:
|
||||
[[nodiscard]] bool Fallible() const final { return false; }
|
||||
|
||||
void SetFailure(std::string aReason) final {
|
||||
MOZ_RELEASE_ASSERT(false,
|
||||
"SetFailure in infallible FailureLatchInfallibleSource");
|
||||
}
|
||||
|
||||
[[nodiscard]] bool Failed() const final { return false; }
|
||||
|
||||
[[nodiscard]] const char* GetFailure() const final { return nullptr; }
|
||||
|
||||
[[nodiscard]] const ::mozilla::FailureLatch& SourceFailureLatch()
|
||||
const final {
|
||||
return *this;
|
||||
}
|
||||
|
||||
[[nodiscard]] ::mozilla::FailureLatch& SourceFailureLatch() final {
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Singleton FailureLatchInfallibleSource that may be used as default
|
||||
// FailureLatch proxy.
|
||||
static FailureLatchInfallibleSource& Singleton() {
|
||||
static FailureLatchInfallibleSource singleton;
|
||||
return singleton;
|
||||
}
|
||||
};
|
||||
|
||||
// Concrete FailureLatch class, intended to be intantiated as an object shared
|
||||
// between classes and functions that are part of a long operation, so that
|
||||
// failures can happen anywhere and be visible everywhere.
|
||||
// Not thread-safe.
|
||||
class FailureLatchSource final : public FailureLatch {
|
||||
public:
|
||||
[[nodiscard]] bool Fallible() const final { return true; }
|
||||
|
||||
void SetFailure(std::string aReason) final {
|
||||
if (!mFailed) {
|
||||
mFailed = true;
|
||||
mReason = std::move(aReason);
|
||||
}
|
||||
}
|
||||
|
||||
[[nodiscard]] bool Failed() const final { return mFailed; }
|
||||
|
||||
[[nodiscard]] const char* GetFailure() const final {
|
||||
return mFailed ? mReason.c_str() : nullptr;
|
||||
}
|
||||
|
||||
[[nodiscard]] const FailureLatch& SourceFailureLatch() const final {
|
||||
return *this;
|
||||
}
|
||||
|
||||
[[nodiscard]] FailureLatch& SourceFailureLatch() final { return *this; }
|
||||
|
||||
private:
|
||||
bool mFailed = false;
|
||||
std::string mReason;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Helper macros, to be used in FailureLatch-derived classes
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// Classes deriving from FailureLatch can use this to forward virtual calls to
|
||||
// another FailureLatch.
|
||||
#define FAILURELATCH_IMPL_PROXY(FAILURELATCH_REF) \
|
||||
[[nodiscard]] bool Fallible() const final { \
|
||||
return static_cast<const ::mozilla::FailureLatch&>(FAILURELATCH_REF) \
|
||||
.Fallible(); \
|
||||
} \
|
||||
void SetFailure(std::string aReason) final { \
|
||||
static_cast<::mozilla::FailureLatch&>(FAILURELATCH_REF) \
|
||||
.SetFailure(std::move(aReason)); \
|
||||
} \
|
||||
[[nodiscard]] bool Failed() const final { \
|
||||
return static_cast<const ::mozilla::FailureLatch&>(FAILURELATCH_REF) \
|
||||
.Failed(); \
|
||||
} \
|
||||
[[nodiscard]] const char* GetFailure() const final { \
|
||||
return static_cast<const ::mozilla::FailureLatch&>(FAILURELATCH_REF) \
|
||||
.GetFailure(); \
|
||||
} \
|
||||
[[nodiscard]] const FailureLatch& SourceFailureLatch() const final { \
|
||||
return static_cast<const ::mozilla::FailureLatch&>(FAILURELATCH_REF) \
|
||||
.SourceFailureLatch(); \
|
||||
} \
|
||||
[[nodiscard]] FailureLatch& SourceFailureLatch() final { \
|
||||
return static_cast<::mozilla::FailureLatch&>(FAILURELATCH_REF) \
|
||||
.SourceFailureLatch(); \
|
||||
}
|
||||
|
||||
// Classes deriving from FailureLatch can use this to forward virtual calls to
|
||||
// another FailureLatch through a pointer, unless it's null in which case act
|
||||
// like an infallible FailureLatch.
|
||||
#define FAILURELATCH_IMPL_PROXY_OR_INFALLIBLE(FAILURELATCH_PTR, CLASS_NAME) \
|
||||
[[nodiscard]] bool Fallible() const final { \
|
||||
return FAILURELATCH_PTR \
|
||||
? static_cast<const ::mozilla::FailureLatch*>(FAILURELATCH_PTR) \
|
||||
->Fallible() \
|
||||
: false; \
|
||||
} \
|
||||
void SetFailure(std::string aReason) final { \
|
||||
if (FAILURELATCH_PTR) { \
|
||||
static_cast<::mozilla::FailureLatch*>(FAILURELATCH_PTR) \
|
||||
->SetFailure(std::move(aReason)); \
|
||||
} else { \
|
||||
MOZ_RELEASE_ASSERT(false, "SetFailure in infallible " #CLASS_NAME); \
|
||||
} \
|
||||
} \
|
||||
[[nodiscard]] bool Failed() const final { \
|
||||
return FAILURELATCH_PTR \
|
||||
? static_cast<const ::mozilla::FailureLatch*>(FAILURELATCH_PTR) \
|
||||
->Failed() \
|
||||
: false; \
|
||||
} \
|
||||
[[nodiscard]] const char* GetFailure() const final { \
|
||||
return FAILURELATCH_PTR \
|
||||
? static_cast<const ::mozilla::FailureLatch*>(FAILURELATCH_PTR) \
|
||||
->GetFailure() \
|
||||
: nullptr; \
|
||||
} \
|
||||
[[nodiscard]] const FailureLatch& SourceFailureLatch() const final { \
|
||||
return FAILURELATCH_PTR \
|
||||
? static_cast<const ::mozilla::FailureLatch*>(FAILURELATCH_PTR) \
|
||||
->SourceFailureLatch() \
|
||||
: ::mozilla::FailureLatchInfallibleSource::Singleton(); \
|
||||
} \
|
||||
[[nodiscard]] FailureLatch& SourceFailureLatch() final { \
|
||||
return FAILURELATCH_PTR \
|
||||
? static_cast<::mozilla::FailureLatch*>(FAILURELATCH_PTR) \
|
||||
->SourceFailureLatch() \
|
||||
: ::mozilla::FailureLatchInfallibleSource::Singleton(); \
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif /* mozilla_FailureLatch_h */
|
|
@ -10,7 +10,9 @@
|
|||
#include "mozilla/BaseAndGeckoProfilerDetail.h"
|
||||
#include "mozilla/BaseProfileJSONWriter.h"
|
||||
#include "mozilla/BaseProfilerDetail.h"
|
||||
#include "mozilla/FailureLatch.h"
|
||||
#include "mozilla/FloatingPoint.h"
|
||||
#include "mozilla/NotNull.h"
|
||||
#include "mozilla/ProgressLogger.h"
|
||||
#include "mozilla/ProportionValue.h"
|
||||
|
||||
|
@ -46,6 +48,278 @@
|
|||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
void TestFailureLatch() {
|
||||
printf("TestFailureLatch...\n");
|
||||
|
||||
// Test infallible latch.
|
||||
{
|
||||
mozilla::FailureLatchInfallibleSource& infallibleLatch =
|
||||
mozilla::FailureLatchInfallibleSource::Singleton();
|
||||
|
||||
MOZ_RELEASE_ASSERT(!infallibleLatch.Fallible());
|
||||
MOZ_RELEASE_ASSERT(!infallibleLatch.Failed());
|
||||
MOZ_RELEASE_ASSERT(!infallibleLatch.GetFailure());
|
||||
MOZ_RELEASE_ASSERT(&infallibleLatch.SourceFailureLatch() ==
|
||||
&mozilla::FailureLatchInfallibleSource::Singleton());
|
||||
MOZ_RELEASE_ASSERT(&std::as_const(infallibleLatch).SourceFailureLatch() ==
|
||||
&mozilla::FailureLatchInfallibleSource::Singleton());
|
||||
}
|
||||
|
||||
// Test failure latch basic functions.
|
||||
{
|
||||
mozilla::FailureLatchSource failureLatch;
|
||||
|
||||
MOZ_RELEASE_ASSERT(failureLatch.Fallible());
|
||||
MOZ_RELEASE_ASSERT(!failureLatch.Failed());
|
||||
MOZ_RELEASE_ASSERT(!failureLatch.GetFailure());
|
||||
MOZ_RELEASE_ASSERT(&failureLatch.SourceFailureLatch() == &failureLatch);
|
||||
MOZ_RELEASE_ASSERT(&std::as_const(failureLatch).SourceFailureLatch() ==
|
||||
&failureLatch);
|
||||
|
||||
failureLatch.SetFailure("error");
|
||||
|
||||
MOZ_RELEASE_ASSERT(failureLatch.Fallible());
|
||||
MOZ_RELEASE_ASSERT(failureLatch.Failed());
|
||||
MOZ_RELEASE_ASSERT(failureLatch.GetFailure());
|
||||
MOZ_RELEASE_ASSERT(strcmp(failureLatch.GetFailure(), "error") == 0);
|
||||
|
||||
failureLatch.SetFailure("later error");
|
||||
|
||||
MOZ_RELEASE_ASSERT(failureLatch.Fallible());
|
||||
MOZ_RELEASE_ASSERT(failureLatch.Failed());
|
||||
MOZ_RELEASE_ASSERT(failureLatch.GetFailure());
|
||||
MOZ_RELEASE_ASSERT(strcmp(failureLatch.GetFailure(), "error") == 0);
|
||||
}
|
||||
|
||||
// Test SetFailureFrom.
|
||||
{
|
||||
mozilla::FailureLatchSource failureLatch;
|
||||
|
||||
MOZ_RELEASE_ASSERT(!failureLatch.Failed());
|
||||
failureLatch.SetFailureFrom(failureLatch);
|
||||
MOZ_RELEASE_ASSERT(!failureLatch.Failed());
|
||||
MOZ_RELEASE_ASSERT(!failureLatch.GetFailure());
|
||||
|
||||
// SetFailureFrom with no error.
|
||||
{
|
||||
mozilla::FailureLatchSource failureLatchInnerOk;
|
||||
MOZ_RELEASE_ASSERT(!failureLatchInnerOk.Failed());
|
||||
MOZ_RELEASE_ASSERT(!failureLatchInnerOk.GetFailure());
|
||||
|
||||
MOZ_RELEASE_ASSERT(!failureLatch.Failed());
|
||||
failureLatch.SetFailureFrom(failureLatchInnerOk);
|
||||
MOZ_RELEASE_ASSERT(!failureLatch.Failed());
|
||||
|
||||
MOZ_RELEASE_ASSERT(!failureLatchInnerOk.Failed());
|
||||
MOZ_RELEASE_ASSERT(!failureLatchInnerOk.GetFailure());
|
||||
}
|
||||
MOZ_RELEASE_ASSERT(!failureLatch.Failed());
|
||||
MOZ_RELEASE_ASSERT(!failureLatch.GetFailure());
|
||||
|
||||
// SetFailureFrom with error.
|
||||
{
|
||||
mozilla::FailureLatchSource failureLatchInnerError;
|
||||
MOZ_RELEASE_ASSERT(!failureLatchInnerError.Failed());
|
||||
MOZ_RELEASE_ASSERT(!failureLatchInnerError.GetFailure());
|
||||
|
||||
failureLatchInnerError.SetFailure("inner error");
|
||||
MOZ_RELEASE_ASSERT(failureLatchInnerError.Failed());
|
||||
MOZ_RELEASE_ASSERT(
|
||||
strcmp(failureLatchInnerError.GetFailure(), "inner error") == 0);
|
||||
|
||||
MOZ_RELEASE_ASSERT(!failureLatch.Failed());
|
||||
failureLatch.SetFailureFrom(failureLatchInnerError);
|
||||
MOZ_RELEASE_ASSERT(failureLatch.Failed());
|
||||
|
||||
MOZ_RELEASE_ASSERT(failureLatchInnerError.Failed());
|
||||
MOZ_RELEASE_ASSERT(
|
||||
strcmp(failureLatchInnerError.GetFailure(), "inner error") == 0);
|
||||
}
|
||||
MOZ_RELEASE_ASSERT(failureLatch.Failed());
|
||||
MOZ_RELEASE_ASSERT(strcmp(failureLatch.GetFailure(), "inner error") == 0);
|
||||
|
||||
failureLatch.SetFailureFrom(failureLatch);
|
||||
MOZ_RELEASE_ASSERT(failureLatch.Failed());
|
||||
MOZ_RELEASE_ASSERT(strcmp(failureLatch.GetFailure(), "inner error") == 0);
|
||||
|
||||
// SetFailureFrom with error again, ignored.
|
||||
{
|
||||
mozilla::FailureLatchSource failureLatchInnerError;
|
||||
failureLatchInnerError.SetFailure("later inner error");
|
||||
MOZ_RELEASE_ASSERT(failureLatchInnerError.Failed());
|
||||
MOZ_RELEASE_ASSERT(strcmp(failureLatchInnerError.GetFailure(),
|
||||
"later inner error") == 0);
|
||||
|
||||
MOZ_RELEASE_ASSERT(failureLatch.Failed());
|
||||
failureLatch.SetFailureFrom(failureLatchInnerError);
|
||||
MOZ_RELEASE_ASSERT(failureLatch.Failed());
|
||||
|
||||
MOZ_RELEASE_ASSERT(failureLatchInnerError.Failed());
|
||||
MOZ_RELEASE_ASSERT(strcmp(failureLatchInnerError.GetFailure(),
|
||||
"later inner error") == 0);
|
||||
}
|
||||
MOZ_RELEASE_ASSERT(failureLatch.Failed());
|
||||
MOZ_RELEASE_ASSERT(strcmp(failureLatch.GetFailure(), "inner error") == 0);
|
||||
}
|
||||
|
||||
// Test FAILURELATCH_IMPL_PROXY
|
||||
{
|
||||
class Proxy final : public mozilla::FailureLatch {
|
||||
public:
|
||||
explicit Proxy(mozilla::FailureLatch& aFailureLatch)
|
||||
: mFailureLatch(WrapNotNull(&aFailureLatch)) {}
|
||||
|
||||
void Set(mozilla::FailureLatch& aFailureLatch) {
|
||||
mFailureLatch = WrapNotNull(&aFailureLatch);
|
||||
}
|
||||
|
||||
FAILURELATCH_IMPL_PROXY(*mFailureLatch)
|
||||
|
||||
private:
|
||||
mozilla::NotNull<mozilla::FailureLatch*> mFailureLatch;
|
||||
};
|
||||
|
||||
Proxy proxy{mozilla::FailureLatchInfallibleSource::Singleton()};
|
||||
|
||||
MOZ_RELEASE_ASSERT(!proxy.Fallible());
|
||||
MOZ_RELEASE_ASSERT(!proxy.Failed());
|
||||
MOZ_RELEASE_ASSERT(!proxy.GetFailure());
|
||||
MOZ_RELEASE_ASSERT(&proxy.SourceFailureLatch() ==
|
||||
&mozilla::FailureLatchInfallibleSource::Singleton());
|
||||
MOZ_RELEASE_ASSERT(&std::as_const(proxy).SourceFailureLatch() ==
|
||||
&mozilla::FailureLatchInfallibleSource::Singleton());
|
||||
|
||||
// Error from proxy.
|
||||
{
|
||||
mozilla::FailureLatchSource failureLatch;
|
||||
proxy.Set(failureLatch);
|
||||
MOZ_RELEASE_ASSERT(proxy.Fallible());
|
||||
MOZ_RELEASE_ASSERT(!proxy.Failed());
|
||||
MOZ_RELEASE_ASSERT(!proxy.GetFailure());
|
||||
MOZ_RELEASE_ASSERT(&proxy.SourceFailureLatch() == &failureLatch);
|
||||
MOZ_RELEASE_ASSERT(&std::as_const(proxy).SourceFailureLatch() ==
|
||||
&failureLatch);
|
||||
|
||||
proxy.SetFailure("error");
|
||||
MOZ_RELEASE_ASSERT(proxy.Failed());
|
||||
MOZ_RELEASE_ASSERT(strcmp(proxy.GetFailure(), "error") == 0);
|
||||
MOZ_RELEASE_ASSERT(failureLatch.Failed());
|
||||
MOZ_RELEASE_ASSERT(strcmp(failureLatch.GetFailure(), "error") == 0);
|
||||
|
||||
// Don't forget to stop pointing at soon-to-be-destroyed object.
|
||||
proxy.Set(mozilla::FailureLatchInfallibleSource::Singleton());
|
||||
}
|
||||
|
||||
// Error from proxy's origin.
|
||||
{
|
||||
mozilla::FailureLatchSource failureLatch;
|
||||
proxy.Set(failureLatch);
|
||||
MOZ_RELEASE_ASSERT(proxy.Fallible());
|
||||
MOZ_RELEASE_ASSERT(!proxy.Failed());
|
||||
MOZ_RELEASE_ASSERT(!proxy.GetFailure());
|
||||
MOZ_RELEASE_ASSERT(&proxy.SourceFailureLatch() == &failureLatch);
|
||||
MOZ_RELEASE_ASSERT(&std::as_const(proxy).SourceFailureLatch() ==
|
||||
&failureLatch);
|
||||
|
||||
failureLatch.SetFailure("error");
|
||||
MOZ_RELEASE_ASSERT(proxy.Failed());
|
||||
MOZ_RELEASE_ASSERT(strcmp(proxy.GetFailure(), "error") == 0);
|
||||
MOZ_RELEASE_ASSERT(failureLatch.Failed());
|
||||
MOZ_RELEASE_ASSERT(strcmp(failureLatch.GetFailure(), "error") == 0);
|
||||
|
||||
// Don't forget to stop pointing at soon-to-be-destroyed object.
|
||||
proxy.Set(mozilla::FailureLatchInfallibleSource::Singleton());
|
||||
}
|
||||
|
||||
MOZ_RELEASE_ASSERT(!proxy.Fallible());
|
||||
MOZ_RELEASE_ASSERT(!proxy.Failed());
|
||||
MOZ_RELEASE_ASSERT(!proxy.GetFailure());
|
||||
MOZ_RELEASE_ASSERT(&proxy.SourceFailureLatch() ==
|
||||
&mozilla::FailureLatchInfallibleSource::Singleton());
|
||||
MOZ_RELEASE_ASSERT(&std::as_const(proxy).SourceFailureLatch() ==
|
||||
&mozilla::FailureLatchInfallibleSource::Singleton());
|
||||
}
|
||||
|
||||
// Test FAILURELATCH_IMPL_PROXY_OR_INFALLIBLE
|
||||
{
|
||||
class ProxyOrNull final : public mozilla::FailureLatch {
|
||||
public:
|
||||
ProxyOrNull() = default;
|
||||
|
||||
void Set(mozilla::FailureLatch* aFailureLatchOrNull) {
|
||||
mFailureLatchOrNull = aFailureLatchOrNull;
|
||||
}
|
||||
|
||||
FAILURELATCH_IMPL_PROXY_OR_INFALLIBLE(mFailureLatchOrNull, ProxyOrNull)
|
||||
|
||||
private:
|
||||
mozilla::FailureLatch* mFailureLatchOrNull = nullptr;
|
||||
};
|
||||
|
||||
ProxyOrNull proxy;
|
||||
|
||||
MOZ_RELEASE_ASSERT(!proxy.Fallible());
|
||||
MOZ_RELEASE_ASSERT(!proxy.Failed());
|
||||
MOZ_RELEASE_ASSERT(!proxy.GetFailure());
|
||||
MOZ_RELEASE_ASSERT(&proxy.SourceFailureLatch() ==
|
||||
&mozilla::FailureLatchInfallibleSource::Singleton());
|
||||
MOZ_RELEASE_ASSERT(&std::as_const(proxy).SourceFailureLatch() ==
|
||||
&mozilla::FailureLatchInfallibleSource::Singleton());
|
||||
|
||||
// Error from proxy.
|
||||
{
|
||||
mozilla::FailureLatchSource failureLatch;
|
||||
proxy.Set(&failureLatch);
|
||||
MOZ_RELEASE_ASSERT(proxy.Fallible());
|
||||
MOZ_RELEASE_ASSERT(!proxy.Failed());
|
||||
MOZ_RELEASE_ASSERT(!proxy.GetFailure());
|
||||
MOZ_RELEASE_ASSERT(&proxy.SourceFailureLatch() == &failureLatch);
|
||||
MOZ_RELEASE_ASSERT(&std::as_const(proxy).SourceFailureLatch() ==
|
||||
&failureLatch);
|
||||
|
||||
proxy.SetFailure("error");
|
||||
MOZ_RELEASE_ASSERT(proxy.Failed());
|
||||
MOZ_RELEASE_ASSERT(strcmp(proxy.GetFailure(), "error") == 0);
|
||||
MOZ_RELEASE_ASSERT(failureLatch.Failed());
|
||||
MOZ_RELEASE_ASSERT(strcmp(failureLatch.GetFailure(), "error") == 0);
|
||||
|
||||
// Don't forget to stop pointing at soon-to-be-destroyed object.
|
||||
proxy.Set(nullptr);
|
||||
}
|
||||
|
||||
// Error from proxy's origin.
|
||||
{
|
||||
mozilla::FailureLatchSource failureLatch;
|
||||
proxy.Set(&failureLatch);
|
||||
MOZ_RELEASE_ASSERT(proxy.Fallible());
|
||||
MOZ_RELEASE_ASSERT(!proxy.Failed());
|
||||
MOZ_RELEASE_ASSERT(!proxy.GetFailure());
|
||||
MOZ_RELEASE_ASSERT(&proxy.SourceFailureLatch() == &failureLatch);
|
||||
MOZ_RELEASE_ASSERT(&std::as_const(proxy).SourceFailureLatch() ==
|
||||
&failureLatch);
|
||||
|
||||
failureLatch.SetFailure("error");
|
||||
MOZ_RELEASE_ASSERT(proxy.Failed());
|
||||
MOZ_RELEASE_ASSERT(strcmp(proxy.GetFailure(), "error") == 0);
|
||||
MOZ_RELEASE_ASSERT(failureLatch.Failed());
|
||||
MOZ_RELEASE_ASSERT(strcmp(failureLatch.GetFailure(), "error") == 0);
|
||||
|
||||
// Don't forget to stop pointing at soon-to-be-destroyed object.
|
||||
proxy.Set(nullptr);
|
||||
}
|
||||
|
||||
MOZ_RELEASE_ASSERT(!proxy.Fallible());
|
||||
MOZ_RELEASE_ASSERT(!proxy.Failed());
|
||||
MOZ_RELEASE_ASSERT(!proxy.GetFailure());
|
||||
MOZ_RELEASE_ASSERT(&proxy.SourceFailureLatch() ==
|
||||
&mozilla::FailureLatchInfallibleSource::Singleton());
|
||||
MOZ_RELEASE_ASSERT(&std::as_const(proxy).SourceFailureLatch() ==
|
||||
&mozilla::FailureLatchInfallibleSource::Singleton());
|
||||
}
|
||||
|
||||
printf("TestFailureLatch done\n");
|
||||
}
|
||||
|
||||
void TestProfilerUtils() {
|
||||
printf("TestProfilerUtils...\n");
|
||||
|
||||
|
@ -5390,6 +5664,7 @@ int main()
|
|||
// ::SleepMilli(10000);
|
||||
#endif // MOZ_GECKO_PROFILER
|
||||
|
||||
TestFailureLatch();
|
||||
TestProfilerUtils();
|
||||
TestBaseAndProfilerDetail();
|
||||
TestSharedMutex();
|
||||
|
|
Загрузка…
Ссылка в новой задаче