aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYilong Li <liyl@google.com>2021-05-07 06:51:06 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2021-05-07 06:51:06 +0000
commitf4fa6a3bfbea1a79e57b4a06e89297eace1a1038 (patch)
treeaff1b4461812e734d2c708f17e99ae725ca1d39a
parentd79cf524db780279b22949b9e1458f096fa02a1d (diff)
parent14a93e9a8a583279d9366a4cc3e7a548378b10c4 (diff)
downloadgoldfish-opengl-f4fa6a3bfbea1a79e57b4a06e89297eace1a1038.tar.gz
Merge "base: Add "fit" library"
-rw-r--r--BUILD.gn7
-rw-r--r--android-emu/android/base/fit/Defer.h157
-rw-r--r--android-emu/android/base/fit/Function.h513
-rw-r--r--android-emu/android/base/fit/FunctionInternal.h456
-rw-r--r--android-emu/android/base/fit/Nullable.h265
-rw-r--r--android-emu/android/base/fit/README150
-rw-r--r--android-emu/android/base/fit/ThreadChecker.h87
-rw-r--r--android-emu/android/base/fit/ThreadSafety.h81
-rw-r--r--android-emu/android/base/fit/UtilityInternal.h146
9 files changed, 1862 insertions, 0 deletions
diff --git a/BUILD.gn b/BUILD.gn
index 40967daa..2e204a76 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -16,6 +16,13 @@ shared_library("libvulkan_goldfish") {
"android-emu/android/base/files/Stream.h",
"android-emu/android/base/files/StreamSerializing.cpp",
"android-emu/android/base/files/StreamSerializing.h",
+ "android-emu/android/base/fit/Defer.h",
+ "android-emu/android/base/fit/Function.h",
+ "android-emu/android/base/fit/FunctionInternal.h",
+ "android-emu/android/base/fit/Nullable.h",
+ "android-emu/android/base/fit/ThreadChecker.h",
+ "android-emu/android/base/fit/ThreadSafety.h",
+ "android-emu/android/base/fit/UtilityInternal.h",
"android-emu/android/base/ring_buffer.c",
"android-emu/android/base/synchronization/AndroidConditionVariable.h",
"android-emu/android/base/synchronization/AndroidLock.h",
diff --git a/android-emu/android/base/fit/Defer.h b/android-emu/android/base/fit/Defer.h
new file mode 100644
index 00000000..d120c322
--- /dev/null
+++ b/android-emu/android/base/fit/Defer.h
@@ -0,0 +1,157 @@
+// Copyright 2021 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#pragma once
+
+#include <utility>
+
+#include "Function.h"
+#include "Nullable.h"
+
+namespace android::base {
+namespace fit {
+
+// A move-only deferred action wrapper with RAII semantics.
+// This class is not thread safe.
+//
+// The wrapper holds a function-like callable target with no arguments
+// which it invokes when it goes out of scope unless canceled, called, or
+// moved to a wrapper in a different scope.
+//
+// See |fit::defer()| for idiomatic usage.
+template <typename T>
+class DeferredAction final {
+public:
+ // Creates a deferred action without a pending target.
+ DeferredAction() = default;
+ explicit DeferredAction(decltype(nullptr)) {}
+
+ // Creates a deferred action with a pending target.
+ explicit DeferredAction(T target) : mTarget(std::move(target)) {}
+
+ // Creates a deferred action with a pending target moved from another
+ // deferred action, leaving the other one without a pending target.
+ DeferredAction(DeferredAction&& other) : mTarget(std::move(other.mTarget)) {
+ other.mTarget.reset();
+ }
+
+ // Invokes and releases the deferred action's pending target (if any).
+ ~DeferredAction() { call(); }
+
+ // Returns true if the deferred action has a pending target.
+ explicit operator bool() const { return !!mTarget; }
+
+ // Invokes and releases the deferred action's pending target (if any),
+ // then move-assigns it from another deferred action, leaving the latter
+ // one without a pending target.
+ DeferredAction& operator=(DeferredAction&& other) {
+ if (&other == this)
+ return *this;
+ call();
+ mTarget = std::move(other.mTarget);
+ other.mTarget.reset();
+ return *this;
+ }
+
+ // Invokes and releases the deferred action's pending target (if any).
+ void call() {
+ if (mTarget) {
+ // Move to a local to guard against re-entrance.
+ T local_target = std::move(*mTarget);
+ mTarget.reset();
+ local_target();
+ }
+ }
+
+ // Releases the deferred action's pending target (if any) without
+ // invoking it.
+ void cancel() { mTarget.reset(); }
+ DeferredAction& operator=(decltype(nullptr)) {
+ cancel();
+ return *this;
+ }
+
+ // Assigns a new target to the deferred action.
+ DeferredAction& operator=(T target) {
+ mTarget = std::move(target);
+ return *this;
+ }
+
+ DeferredAction(const DeferredAction& other) = delete;
+ DeferredAction& operator=(const DeferredAction& other) = delete;
+
+private:
+ Nullable<T> mTarget;
+};
+
+template <typename T>
+bool operator==(const DeferredAction<T>& action, decltype(nullptr)) {
+ return !action;
+}
+template <typename T>
+bool operator==(decltype(nullptr), const DeferredAction<T>& action) {
+ return !action;
+}
+template <typename T>
+bool operator!=(const DeferredAction<T>& action, decltype(nullptr)) {
+ return !!action;
+}
+template <typename T>
+bool operator!=(decltype(nullptr), const DeferredAction<T>& action) {
+ return !!action;
+}
+
+// Defers execution of a function-like callable target with no arguments
+// until the value returned by this function goes out of scope unless canceled,
+// called, or moved to a wrapper in a different scope.
+//
+// // This example prints "Hello..." then "Goodbye!".
+// void test() {
+// auto d = fit::defer([]{ puts("Goodbye!"); });
+// puts("Hello...");
+// }
+//
+// // This example prints nothing because the deferred action is canceled.
+// void do_nothing() {
+// auto d = fit::defer([]{ puts("I'm not here."); });
+// d.cancel();
+// }
+//
+// // This example shows how the deferred action can be reassigned assuming
+// // the new target has the same type and the old one, in this case by
+// // representing the target as a |fit::Closure|.
+// void reassign() {
+// auto d = fit::defer<fit::Closure>([] { puts("This runs first."); });
+// d = fit::defer<fit::Closure>([] { puts("This runs afterwards."); });
+// }
+template <typename T>
+inline DeferredAction<T> defer(T target) {
+ return DeferredAction<T>(std::move(target));
+}
+
+// Alias for a deferred_action using a fit::Callback.
+using DeferredCallback = DeferredAction<fit::Callback<void()>>;
+
+// Defers execution of a fit::Callback with no arguments. See |fit::defer| for
+// details.
+inline DeferredCallback deferCallback(fit::Callback<void()> target) {
+ return DeferredCallback(std::move(target));
+}
+
+} // namespace fit
+} // namespace android::base
diff --git a/android-emu/android/base/fit/Function.h b/android-emu/android/base/fit/Function.h
new file mode 100644
index 00000000..4f4b17da
--- /dev/null
+++ b/android-emu/android/base/fit/Function.h
@@ -0,0 +1,513 @@
+// Copyright 2021 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Copyright 2017 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#pragma once
+
+#include "FunctionInternal.h"
+#include "UtilityInternal.h"
+
+namespace android::base {
+namespace fit {
+
+template <size_t inlineTargetSize, bool requireInline, typename Result, typename... Args>
+class FunctionImpl;
+
+template <size_t inlineTargetSize, bool requireInline, typename Result, typename... Args>
+class CallbackImpl;
+
+// The default size allowance for storing a target inline within a function
+// object, in bytes. This default allows for inline storage of targets
+// as big as two pointers, such as an object pointer and a pointer to a member
+// function.
+constexpr size_t kDefaultInlineTargetSize = sizeof(void*) * 2;
+
+// A |fit::Function| is a move-only polymorphic function wrapper.
+//
+// If you need a class with similar characteristics that also ensures
+// "run-once" semantics (such as callbacks shared with timeouts, or for
+// service requests with redundant, failover, or fallback service providers),
+// see |fit::Callback|.
+//
+// |fit::Function<T>| behaves like |std::function<T>| except that it is
+// move-only instead of copyable, so it can hold targets that cannot be copied,
+// such as mutable lambdas, and immutable lambdas that capture move-only
+// objects.
+//
+// Targets of up to |inlineTargetSize| bytes in size (rounded up for memory
+// alignment) are stored inline within the function object without incurring
+// any heap allocation. Larger callable objects will be moved to the heap as
+// required.
+//
+// See also |fit::InlineFunction<T, size>| for more control over allocation
+// behavior.
+//
+// SYNOPSIS
+//
+// |T| is the function's signature. e.g. void(int, std::string).
+//
+// |inlineTargetSize| is the minimum size of target that is guaranteed to
+// fit within a function without requiring heap allocation.
+// Defaults to |kDefaultInlineTargetSize|.
+//
+// Class members are documented in |fit::FunctionImpl|, below.
+//
+// EXAMPLES
+//
+// -
+// https://fuchsia.googlesource.com/fuchsia/+/HEAD/sdk/lib/fit/test/examples/function_example1.cc
+// -
+// https://fuchsia.googlesource.com/fuchsia/+/HEAD/sdk/lib/fit/test/examples/function_example2.cc
+//
+template <typename T, size_t inlineTargetSize = kDefaultInlineTargetSize>
+using function = FunctionImpl<inlineTargetSize, /*requireInline=*/false, T>;
+
+// A move-only callable object wrapper that forces callables to be stored inline
+// and never performs heap allocation.
+//
+// Behaves just like |fit::Function<T, inlineTargetSize>| except that
+// attempting to store a target larger than |inlineTargetSize| will fail to
+// compile.
+template <typename T, size_t inlineTargetSize = kDefaultInlineTargetSize>
+using InlineFunction = FunctionImpl<inlineTargetSize,
+ /*requireInline=*/true,
+ T>;
+
+// Synonym for a function which takes no arguments and produces no result.
+using closure = function<void()>;
+
+// A |fit::Callback| is a move-only polymorphic function wrapper that also
+// ensures "run-once" semantics (such as callbacks shared with timeouts, or for
+// service requests with redundant, failover, or fallback service providers).
+// A |fit::Callback| releases it's resources after the first call, and can be
+// inspected before calling, so a potential caller can know if it should call
+// the function, or skip the call because the target was already called.
+//
+// If you need a move-only function class with typical function characteristics,
+// that permits multiple invocations of the same function, see |fit::Function|.
+//
+// |fit::Callback<T>| behaves like |std::function<T>| except:
+//
+// 1. It is move-only instead of copyable, so it can hold targets that cannot
+// be copied, such as mutable lambdas, and immutable lambdas that capture
+// move-only objects.
+// 2. On the first call to invoke a |fit::Callback|, the target function held
+// by the |fit::Callback| cannot be called again.
+//
+// When a |fit::Callback| is invoked for the first time, the target function is
+// released and destructed, along with any resources owned by that function
+// (typically the objects captured by a lambda).
+//
+// A |fit::Callback| in the "already called" state has the same state as a
+// |fit::Callback| that has been assigned to |nullptr|. It can be compared to
+// |nullptr| (via "==" or "!=", and its "operator bool()" returns false, which
+// provides a convenient way to gate whether or not the |fit::Callback| should
+// be called. (Note that invoking an empty |fit::Callback| or |fit::Function|
+// will cause a program abort!)
+//
+// As an example, sharing |fit::Callback| between both a service and a timeout
+// might look something like this:
+//
+// void service_with_timeout(fit::Callback<void(bool)> cb, uint timeout_ms) {
+// service_request([cb = cb.share()]() mutable { if (cb) cb(false); });
+// timeout(timeout_ms, [cb = std::move(cb)]() mutable { if (cb) cb(true); });
+// }
+//
+// Since |fit::Callback| objects are move-only, and not copyable, duplicate
+// references to the same |fit::Callback| can be obtained via share(), as shown
+// in the example above. This method converts the |fit::Callback| into a
+// reference-counted version of the |fit::Callback| and returns a copy of the
+// reference as another |fit::Callback| with the same target function.
+//
+// What is notable about |fit::Callback<T>.share()| is that invoking any shared
+// copy will "nullify" all shared copies, as shown in the example.
+//
+// Note that |fit::Callback| is NOT thread-safe by default. If multi-threaded
+// support is required, you would need to implement your own mutex, or similar
+// guard, before checking and calling a |fit::Callback|.
+//
+// Targets of up to |inlineTargetSize| bytes in size (rounded up for memory
+// alignment) are stored inline within the callback object without incurring
+// any heap allocation. Larger callable objects will be moved to the heap as
+// required.
+//
+// See also |fit::inline_callback<T, size>| for more control over allocation
+// behavior.
+//
+// SYNOPSIS
+//
+// |T| is the callback's signature. e.g. void(int, std::string).
+//
+// |inlineTargetSize| is the minimum size of target that is guaranteed to
+// fit within a callback without requiring heap allocation.
+// Defaults to |kDefaultInlineTargetSize|.
+//
+// Class members are documented in |fit::CallbackImpl|, below.
+//
+template <typename T, size_t inlineTargetSize = kDefaultInlineTargetSize>
+using Callback = CallbackImpl<inlineTargetSize, /*requireInline=*/false, T>;
+
+// A move-only, run-once, callable object wrapper that forces callables to be
+// stored inline and never performs heap allocation.
+//
+// Behaves just like |fit::Callback<T, inlineTargetSize>| except that
+// attempting to store a target larger than |inlineTargetSize| will fail to
+// compile.
+template <typename T, size_t inlineTargetSize = kDefaultInlineTargetSize>
+using InlineCallback = CallbackImpl<inlineTargetSize,
+ /*requireInline=*/true,
+ T>;
+
+template <size_t inlineTargetSize, bool requireInline, typename Result, typename... Args>
+class FunctionImpl<inlineTargetSize, requireInline, Result(Args...)> final
+ : private ::android::base::fit::internal::
+ function_base<inlineTargetSize, requireInline, Result(Args...)> {
+ using Base = ::android::base::fit::internal::
+ function_base<inlineTargetSize, requireInline, Result(Args...)>;
+
+ // function_base requires private access during share()
+ friend class ::android::base::fit::internal::
+ function_base<inlineTargetSize, requireInline, Result(Args...)>;
+
+ // supports target() for shared functions
+ friend const void* ::android::base::fit::internal::get_target_type_id<>(
+ const FunctionImpl<inlineTargetSize, requireInline, Result(Args...)>&);
+
+ template <typename U>
+ using NotSelfType = ::android::base::fit::internal::NotSameType<FunctionImpl, U>;
+
+ template <typename... Conditions>
+ using RequiresConditions = ::android::base::fit::internal::RequiresConditions<Conditions...>;
+
+ template <typename... Conditions>
+ using AssignmentRequiresConditions =
+ ::android::base::fit::internal::AssignmentRequiresConditions<FunctionImpl&, Conditions...>;
+
+public:
+ // The function's result type.
+ using typename Base::result_type;
+
+ // Initializes an empty (null) function. Attempting to call an empty
+ // function will abort the program.
+ FunctionImpl() = default;
+
+ // Creates a function with an empty target (same outcome as the default
+ // constructor).
+ FunctionImpl(decltype(nullptr)) : Base(nullptr) {}
+
+ // Creates a function bound to the specified function pointer.
+ // If target == nullptr, assigns an empty target.
+ FunctionImpl(Result (*target)(Args...)) : Base(target) {}
+
+ // Creates a function bound to the specified callable object.
+ // If target == nullptr, assigns an empty target.
+ //
+ // For functors, we need to capture the raw type but also restrict on the
+ // existence of an appropriate operator () to resolve overloads and implicit
+ // casts properly.
+ //
+ // Note that specializations of this template method that take fit::Callback
+ // objects as the target Callable are deleted (see below).
+ template <typename Callable,
+ RequiresConditions<
+ std::is_convertible<decltype(std::declval<Callable&>()(std::declval<Args>()...)),
+ result_type>,
+ NotSelfType<Callable>> = true>
+ FunctionImpl(Callable&& target) : Base(std::forward<Callable>(target)) {}
+
+ // Deletes the specializations of FunctionImpl(Callable) that would allow
+ // a |fit::Function| to be constructed from a |fit::Callback|. This prevents
+ // unexpected behavior of a |fit::Function| that would otherwise fail after
+ // one call. To explicitly allow this, simply wrap the |fit::Callback| in a
+ // pass-through lambda before passing it to the |fit::Function|.
+ template <size_t otherInlineTargetSize, bool otherRequireInline>
+ FunctionImpl(::android::base::fit::CallbackImpl<otherInlineTargetSize,
+ otherRequireInline,
+ Result(Args...)>) = delete;
+
+ // Creates a function with a target moved from another function,
+ // leaving the other function with an empty target.
+ FunctionImpl(FunctionImpl&& other) : Base(static_cast<Base&&>(other)) {}
+
+ // Destroys the function, releasing its target.
+ ~FunctionImpl() = default;
+
+ // Assigns the function to an empty target. Attempting to invoke the
+ // function will abort the program.
+ FunctionImpl& operator=(decltype(nullptr)) {
+ Base::assign(nullptr);
+ return *this;
+ }
+
+ // Assigns the function to the specified callable object. If target ==
+ // nullptr, assigns an empty target.
+ //
+ // For functors, we need to capture the raw type but also restrict on the
+ // existence of an appropriate operator () to resolve overloads and implicit
+ // casts properly.
+ //
+ // Note that specializations of this template method that take fit::Callback
+ // objects as the target Callable are deleted (see below).
+ template <typename Callable>
+ AssignmentRequiresConditions<
+ std::is_convertible<decltype(std::declval<Callable&>()(std::declval<Args>()...)),
+ result_type>,
+ NotSelfType<Callable>>
+ operator=(Callable&& target) {
+ Base::assign(std::forward<Callable>(target));
+ return *this;
+ }
+
+ // Deletes the specializations of operator=(Callable) that would allow
+ // a |fit::Function| to be assigned from a |fit::Callback|. This
+ // prevents unexpected behavior of a |fit::Function| that would otherwise
+ // fail after one call. To explicitly allow this, simply wrap the
+ // |fit::Callback| in a pass-through lambda before assigning it to the
+ // |fit::Function|.
+ template <size_t otherInlineTargetSize, bool otherRequireInline>
+ FunctionImpl& operator=(::android::base::fit::CallbackImpl<otherInlineTargetSize,
+ otherRequireInline,
+ Result(Args...)>) = delete;
+
+ // Move assignment
+ FunctionImpl& operator=(FunctionImpl&& other) {
+ if (&other == this)
+ return *this;
+ Base::assign(static_cast<Base&&>(other));
+ return *this;
+ }
+
+ // Swaps the functions' targets.
+ void swap(FunctionImpl& other) { Base::swap(other); }
+
+ // Returns a pointer to the function's target.
+ using Base::target;
+
+ // Returns true if the function has a non-empty target.
+ using Base::operator bool;
+
+ // Invokes the function's target.
+ // Aborts if the function's target is empty.
+ Result operator()(Args... args) const { return Base::invoke(std::forward<Args>(args)...); }
+
+ // Returns a new function object that invokes the same target.
+ // The target itself is not copied; it is moved to the heap and its
+ // lifetime is extended until all references have been released.
+ //
+ // Note: This method is not supported on |fit::InlineFunction<>|
+ // because it may incur a heap allocation which is contrary to
+ // the stated purpose of |fit::InlineFunction<>|.
+ FunctionImpl share() {
+ FunctionImpl copy;
+ Base::template share_with<FunctionImpl>(copy);
+ return copy;
+ }
+};
+
+template <size_t inlineTargetSize, bool requireInline, typename Result, typename... Args>
+void swap(FunctionImpl<inlineTargetSize, requireInline, Result, Args...>& a,
+ FunctionImpl<inlineTargetSize, requireInline, Result, Args...>& b) {
+ a.swap(b);
+}
+
+template <size_t inlineTargetSize, bool requireInline, typename Result, typename... Args>
+bool operator==(const FunctionImpl<inlineTargetSize, requireInline, Result, Args...>& f,
+ decltype(nullptr)) {
+ return !f;
+}
+template <size_t inlineTargetSize, bool requireInline, typename Result, typename... Args>
+bool operator==(decltype(nullptr),
+ const FunctionImpl<inlineTargetSize, requireInline, Result, Args...>& f) {
+ return !f;
+}
+template <size_t inlineTargetSize, bool requireInline, typename Result, typename... Args>
+bool operator!=(const FunctionImpl<inlineTargetSize, requireInline, Result, Args...>& f,
+ decltype(nullptr)) {
+ return !!f;
+}
+template <size_t inlineTargetSize, bool requireInline, typename Result, typename... Args>
+bool operator!=(decltype(nullptr),
+ const FunctionImpl<inlineTargetSize, requireInline, Result, Args...>& f) {
+ return !!f;
+}
+
+template <size_t inlineTargetSize, bool requireInline, typename Result, typename... Args>
+class CallbackImpl<inlineTargetSize, requireInline, Result(Args...)> final
+ : private ::android::base::fit::internal::
+ function_base<inlineTargetSize, requireInline, Result(Args...)> {
+ using Base = ::android::base::fit::internal::
+ function_base<inlineTargetSize, requireInline, Result(Args...)>;
+
+ // function_base requires private access during share()
+ friend class ::android::base::fit::internal::
+ function_base<inlineTargetSize, requireInline, Result(Args...)>;
+
+ // supports target() for shared functions
+ friend const void* ::android::base::fit::internal::get_target_type_id<>(
+ const CallbackImpl<inlineTargetSize, requireInline, Result(Args...)>&);
+
+ template <typename U>
+ using NotSelfType = ::android::base::fit::internal::NotSameType<CallbackImpl, U>;
+
+ template <typename... Conditions>
+ using RequiresConditions = ::android::base::fit::internal::RequiresConditions<Conditions...>;
+
+ template <typename... Conditions>
+ using AssignmentRequiresConditions =
+ ::android::base::fit::internal::AssignmentRequiresConditions<CallbackImpl&, Conditions...>;
+
+public:
+ // The callback function's result type.
+ using typename Base::result_type;
+
+ // Initializes an empty (null) callback. Attempting to call an empty
+ // callback will abort the program.
+ CallbackImpl() = default;
+
+ // Creates a callback with an empty target (same outcome as the default
+ // constructor).
+ CallbackImpl(decltype(nullptr)) : Base(nullptr) {}
+
+ // Creates a callback bound to the specified function pointer.
+ // If target == nullptr, assigns an empty target.
+ CallbackImpl(Result (*target)(Args...)) : Base(target) {}
+
+ // Creates a callback bound to the specified callable object.
+ // If target == nullptr, assigns an empty target.
+ //
+ // For functors, we need to capture the raw type but also restrict on the
+ // existence of an appropriate operator () to resolve overloads and implicit
+ // casts properly.
+ template <typename Callable,
+ RequiresConditions<
+ std::is_convertible<decltype(std::declval<Callable&>()(std::declval<Args>()...)),
+ result_type>,
+ NotSelfType<Callable>> = true>
+ CallbackImpl(Callable&& target) : Base(std::forward<Callable>(target)) {}
+
+ // Creates a callback with a target moved from another callback,
+ // leaving the other callback with an empty target.
+ CallbackImpl(CallbackImpl&& other) : Base(static_cast<Base&&>(other)) {}
+
+ // Destroys the callback, releasing its target.
+ ~CallbackImpl() = default;
+
+ // Assigns the callback to an empty target. Attempting to invoke the
+ // callback will abort the program.
+ CallbackImpl& operator=(decltype(nullptr)) {
+ Base::assign(nullptr);
+ return *this;
+ }
+
+ // Assigns the callback to the specified callable object. If target ==
+ // nullptr, assigns an empty target.
+ //
+ // For functors, we need to capture the raw type but also restrict on the
+ // existence of an appropriate operator () to resolve overloads and implicit
+ // casts properly.
+ template <typename Callable>
+ AssignmentRequiresConditions<
+ std::is_convertible<decltype(std::declval<Callable&>()(std::declval<Args>()...)),
+ result_type>,
+ NotSelfType<Callable>>
+ operator=(Callable&& target) {
+ Base::assign(std::forward<Callable>(target));
+ return *this;
+ }
+
+ // Move assignment
+ CallbackImpl& operator=(CallbackImpl&& other) {
+ if (&other == this)
+ return *this;
+ Base::assign(static_cast<Base&&>(other));
+ return *this;
+ }
+
+ // Swaps the callbacks' targets.
+ void swap(CallbackImpl& other) { Base::swap(other); }
+
+ // Returns a pointer to the callback's target.
+ using Base::target;
+
+ // Returns true if the callback has a non-empty target.
+ using Base::operator bool;
+
+ // Invokes the callback's target.
+ // Aborts if the callback's target is empty.
+ // |fit::Callback| must be non-const to invoke. Before the target function
+ // is actually called, the fit::Callback will be set to the default empty
+ // state (== nullptr, and operator bool() will subsequently return |false|).
+ // The target function will then be released after the function is called.
+ // If the callback was shared, any remaining copies will also be cleared.
+ Result operator()(Args... args) {
+ auto temp = std::move(*this);
+ return temp.invoke(std::forward<Args>(args)...);
+ }
+
+ // Returns a new callback object that invokes the same target.
+ // The target itself is not copied; it is moved to the heap and its
+ // lifetime is extended until all references have been released.
+ // For |fit::Callback| (unlike fit::Function), the first invocation of the
+ // callback will release all references to the target. All callbacks
+ // derived from the same original callback (via share()) will be cleared,
+ // as if set to |nullptr|, and "operator bool()" will return false.
+ //
+ // Note: This method is not supported on |fit::InlineFunction<>|
+ // because it may incur a heap allocation which is contrary to
+ // the stated purpose of |fit::InlineFunction<>|.
+ CallbackImpl share() {
+ CallbackImpl copy;
+ Base::template share_with<CallbackImpl>(copy);
+ return copy;
+ }
+};
+
+template <size_t inlineTargetSize, bool requireInline, typename Result, typename... Args>
+void swap(CallbackImpl<inlineTargetSize, requireInline, Result, Args...>& a,
+ CallbackImpl<inlineTargetSize, requireInline, Result, Args...>& b) {
+ a.swap(b);
+}
+
+template <size_t inlineTargetSize, bool requireInline, typename Result, typename... Args>
+bool operator==(const CallbackImpl<inlineTargetSize, requireInline, Result, Args...>& f,
+ decltype(nullptr)) {
+ return !f;
+}
+template <size_t inlineTargetSize, bool requireInline, typename Result, typename... Args>
+bool operator==(decltype(nullptr),
+ const CallbackImpl<inlineTargetSize, requireInline, Result, Args...>& f) {
+ return !f;
+}
+template <size_t inlineTargetSize, bool requireInline, typename Result, typename... Args>
+bool operator!=(const CallbackImpl<inlineTargetSize, requireInline, Result, Args...>& f,
+ decltype(nullptr)) {
+ return !!f;
+}
+template <size_t inlineTargetSize, bool requireInline, typename Result, typename... Args>
+bool operator!=(decltype(nullptr),
+ const CallbackImpl<inlineTargetSize, requireInline, Result, Args...>& f) {
+ return !!f;
+}
+
+// Returns a Callable object that invokes a member function of an object.
+template <typename R, typename T, typename... Args>
+auto bindMember(T* instance, R (T::*fn)(Args...)) {
+ return [instance, fn](Args... args) { return (instance->*fn)(std::forward<Args>(args)...); };
+}
+
+} // namespace fit
+} // namespace android::base
diff --git a/android-emu/android/base/fit/FunctionInternal.h b/android-emu/android/base/fit/FunctionInternal.h
new file mode 100644
index 00000000..3fb1ac53
--- /dev/null
+++ b/android-emu/android/base/fit/FunctionInternal.h
@@ -0,0 +1,456 @@
+// Copyright 2021 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Copyright 2017 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#pragma once
+
+#include <stddef.h>
+#include <stdlib.h>
+
+#include <memory>
+
+#include "Nullable.h"
+
+#include <new>
+#include <type_traits>
+#include <utility>
+
+namespace android::base {
+namespace fit {
+namespace internal {
+
+template <typename Result, typename... Args>
+struct target_ops final {
+ const void* (*target_type_id)(void* bits, const void* impl_ops);
+ void* (*get)(void* bits);
+ Result (*invoke)(void* bits, Args... args);
+ void (*move)(void* from_bits, void* to_bits);
+ void (*destroy)(void* bits);
+};
+
+template <typename Callable, bool is_inline, bool is_shared, typename Result, typename... Args>
+struct target;
+
+inline const void* unshared_target_type_id(void* bits, const void* impl_ops) {
+ return impl_ops;
+}
+
+// vtable for nullptr (empty target function)
+
+template <typename Result, typename... Args>
+struct target<decltype(nullptr),
+ /*is_inline=*/true,
+ /*is_shared=*/false,
+ Result,
+ Args...>
+ final {
+ static Result invoke(void* bits, Args... args) { __builtin_abort(); }
+
+ static const target_ops<Result, Args...> ops;
+};
+
+inline void* null_target_get(void* bits) {
+ return nullptr;
+}
+inline void null_target_move(void* from_bits, void* to_bits) {}
+inline void null_target_destroy(void* bits) {}
+
+template <typename Result, typename... Args>
+constexpr target_ops<Result, Args...> target<decltype(nullptr),
+ /*is_inline=*/true,
+ /*is_shared=*/false,
+ Result,
+ Args...>::ops = {
+ &unshared_target_type_id, &null_target_get, &target::invoke, &null_target_move,
+ &null_target_destroy};
+
+// vtable for inline target function
+
+template <typename Callable, typename Result, typename... Args>
+struct target<Callable,
+ /*is_inline=*/true,
+ /*is_shared=*/false,
+ Result,
+ Args...>
+ final {
+ template <typename Callable_>
+ static void initialize(void* bits, Callable_&& target) {
+ new (bits) Callable(std::forward<Callable_>(target));
+ }
+ static Result invoke(void* bits, Args... args) {
+ auto& target = *static_cast<Callable*>(bits);
+ return target(std::forward<Args>(args)...);
+ }
+ static void move(void* from_bits, void* to_bits) {
+ auto& from_target = *static_cast<Callable*>(from_bits);
+ new (to_bits) Callable(std::move(from_target));
+ from_target.~Callable();
+ }
+ static void destroy(void* bits) {
+ auto& target = *static_cast<Callable*>(bits);
+ target.~Callable();
+ }
+
+ static const target_ops<Result, Args...> ops;
+};
+
+inline void* inline_target_get(void* bits) {
+ return bits;
+}
+
+template <typename Callable, typename Result, typename... Args>
+constexpr target_ops<Result, Args...> target<Callable,
+ /*is_inline=*/true,
+ /*is_shared=*/false,
+ Result,
+ Args...>::ops = {
+ &unshared_target_type_id, &inline_target_get, &target::invoke, &target::move, &target::destroy};
+
+// vtable for pointer to target function
+
+template <typename Callable, typename Result, typename... Args>
+struct target<Callable,
+ /*is_inline=*/false,
+ /*is_shared=*/false,
+ Result,
+ Args...>
+ final {
+ template <typename Callable_>
+ static void initialize(void* bits, Callable_&& target) {
+ auto ptr = static_cast<Callable**>(bits);
+ *ptr = new Callable(std::forward<Callable_>(target));
+ }
+ static Result invoke(void* bits, Args... args) {
+ auto& target = **static_cast<Callable**>(bits);
+ return target(std::forward<Args>(args)...);
+ }
+ static void move(void* from_bits, void* to_bits) {
+ auto from_ptr = static_cast<Callable**>(from_bits);
+ auto to_ptr = static_cast<Callable**>(to_bits);
+ *to_ptr = *from_ptr;
+ }
+ static void destroy(void* bits) {
+ auto ptr = static_cast<Callable**>(bits);
+ delete *ptr;
+ }
+
+ static const target_ops<Result, Args...> ops;
+};
+
+inline void* heap_target_get(void* bits) {
+ return *static_cast<void**>(bits);
+}
+
+template <typename Callable, typename Result, typename... Args>
+constexpr target_ops<Result, Args...> target<Callable,
+ /*is_inline=*/false,
+ /*is_shared=*/false,
+ Result,
+ Args...>::ops = {
+ &unshared_target_type_id, &heap_target_get, &target::invoke, &target::move, &target::destroy};
+
+// vtable for fit::function std::shared_ptr to target function
+
+template <typename SharedFunction>
+const void* get_target_type_id(const SharedFunction& function_or_callback) {
+ return function_or_callback.target_type_id();
+}
+
+// For this vtable,
+// Callable by definition will be either a fit::function or fit::callback
+template <typename SharedFunction, typename Result, typename... Args>
+struct target<SharedFunction,
+ /*is_inline=*/false,
+ /*is_shared=*/true,
+ Result,
+ Args...>
+ final {
+ static void initialize(void* bits, SharedFunction target) {
+ new (bits) std::shared_ptr<SharedFunction>(
+ std::move(std::make_shared<SharedFunction>(std::move(target))));
+ }
+ static void copy_shared_ptr(void* from_bits, void* to_bits) {
+ auto& from_shared_ptr = *static_cast<std::shared_ptr<SharedFunction>*>(from_bits);
+ new (to_bits) std::shared_ptr<SharedFunction>(from_shared_ptr);
+ }
+ static const void* target_type_id(void* bits, const void* impl_ops) {
+ auto& function_or_callback = **static_cast<std::shared_ptr<SharedFunction>*>(bits);
+ return ::android::base::fit::internal::get_target_type_id(function_or_callback);
+ }
+ static void* get(void* bits) {
+ auto& function_or_callback = **static_cast<std::shared_ptr<SharedFunction>*>(bits);
+ return function_or_callback.template target<SharedFunction>(
+ /*check=*/false); // void* will fail the check
+ }
+ static Result invoke(void* bits, Args... args) {
+ auto& function_or_callback = **static_cast<std::shared_ptr<SharedFunction>*>(bits);
+ return function_or_callback(std::forward<Args>(args)...);
+ }
+ static void move(void* from_bits, void* to_bits) {
+ auto from_shared_ptr = std::move(*static_cast<std::shared_ptr<SharedFunction>*>(from_bits));
+ new (to_bits) std::shared_ptr<SharedFunction>(std::move(from_shared_ptr));
+ }
+ static void destroy(void* bits) {
+ static_cast<std::shared_ptr<SharedFunction>*>(bits)->reset();
+ }
+
+ static const target_ops<Result, Args...> ops;
+};
+
+template <typename SharedFunction, typename Result, typename... Args>
+constexpr target_ops<Result, Args...> target<SharedFunction,
+ /*is_inline=*/false,
+ /*is_shared=*/true,
+ Result,
+ Args...>::ops = {
+ &target::target_type_id, &target::get, &target::invoke, &target::move, &target::destroy};
+
+template <size_t inline_target_size, bool requireInline, typename Result, typename... Args>
+class function_base;
+
+// Function implementation details.
+// See |fit::function| and |fit::callback| documentation for more information.
+template <size_t inline_target_size, bool requireInline, typename Result, typename... Args>
+class function_base<inline_target_size, requireInline, Result(Args...)> {
+ using ops_type = const target_ops<Result, Args...>*;
+ using storage_type = typename std::aligned_storage<(
+ inline_target_size >= sizeof(void*) ? inline_target_size : sizeof(void*))>::
+ type; // avoid including <algorithm> for max
+ template <typename Callable>
+ using target_type = target<Callable,
+ (sizeof(Callable) <= sizeof(storage_type)),
+ /*is_shared=*/false,
+ Result,
+ Args...>;
+ template <typename SharedFunction>
+ using shared_target_type = target<SharedFunction,
+ /*is_inline=*/false,
+ /*is_shared=*/true,
+ Result,
+ Args...>;
+ using null_target_type = target_type<decltype(nullptr)>;
+
+protected:
+ using result_type = Result;
+
+ function_base() { initialize_null_target(); }
+
+ function_base(decltype(nullptr)) { initialize_null_target(); }
+
+ function_base(Result (*target)(Args...)) { initialize_target(target); }
+
+ template <typename Callable,
+ typename = std::enable_if_t<
+ std::is_convertible<decltype(std::declval<Callable&>()(std::declval<Args>()...)),
+ result_type>::value>>
+ function_base(Callable&& target) {
+ initialize_target(std::forward<Callable>(target));
+ }
+
+ function_base(function_base&& other) { move_target_from(std::move(other)); }
+
+ ~function_base() { destroy_target(); }
+
+ // Returns true if the function has a non-empty target.
+ explicit operator bool() const { return ops_->get(&bits_) != nullptr; }
+
+ // Returns a pointer to the function's target.
+ // If |check| is true (the default), the function _may_ abort if the
+ // caller tries to assign the target to a varible of the wrong type. (This
+ // check is currently skipped for share()d objects.)
+ // Note the shared pointer vtable must set |check| to false to assign the
+ // target to |void*|.
+ template <typename Callable>
+ Callable* target(bool check = true) {
+ if (check)
+ check_target_type<Callable>();
+ return static_cast<Callable*>(ops_->get(&bits_));
+ }
+
+ // Returns a pointer to the function's target (const version).
+ // If |check| is true (the default), the function _may_ abort if the
+ // caller tries to assign the target to a varible of the wrong type. (This
+ // check is currently skipped for share()d objects.)
+ // Note the shared pointer vtable must set |check| to false to assign the
+ // target to |void*|.
+ template <typename Callable>
+ const Callable* target(bool check = true) const {
+ if (check)
+ check_target_type<Callable>();
+ return static_cast<Callable*>(ops_->get(&bits_));
+ }
+
+ // Used by the derived "impl" classes to implement share().
+ //
+ // The caller creates a new object of the same type as itself, and passes in
+ // the empty object. This function first checks if |this| is already shared,
+ // and if not, creates a new version of itself containing a
+ // |std::shared_ptr| to its original self, and updates |ops_| to the vtable
+ // for the shared version.
+ //
+ // Then it copies its |shared_ptr| to the |bits_| of the given |copy|,
+ // and assigns the same shared pointer vtable to the copy's |ops_|.
+ //
+ // The target itself is not copied; it is moved to the heap and its
+ // lifetime is extended until all references have been released.
+ //
+ // Note: This method is not supported on |fit::InlineFunction<>|
+ // because it may incur a heap allocation which is contrary to
+ // the stated purpose of |fit::InlineFunction<>|.
+ template <typename SharedFunction>
+ void share_with(SharedFunction& copy) {
+ static_assert(!requireInline, "Inline functions cannot be shared.");
+ if (ops_->get(&bits_) != nullptr) {
+ if (ops_ != &shared_target_type<SharedFunction>::ops) {
+ convert_to_shared_target<SharedFunction>();
+ }
+ copy_shared_target_to(copy);
+ }
+ }
+
+ // Used by derived "impl" classes to implement operator()().
+ // Invokes the function's target.
+ // Note that fit::callback will release the target immediately after
+ // invoke() (also affecting any share()d copies).
+ // Aborts if the function's target is empty.
+ Result invoke(Args... args) const { return ops_->invoke(&bits_, std::forward<Args>(args)...); }
+
+ // Used by derived "impl" classes to implement operator=().
+ // Assigns an empty target.
+ void assign(decltype(nullptr)) {
+ destroy_target();
+ initialize_null_target();
+ }
+
+ // Used by derived "impl" classes to implement operator=().
+ // Assigns the function's target.
+ // If target == nullptr, assigns an empty target.
+ template <typename Callable,
+ typename = std::enable_if_t<
+ std::is_convertible<decltype(std::declval<Callable&>()(std::declval<Args>()...)),
+ result_type>::value>>
+ void assign(Callable&& target) {
+ destroy_target();
+ initialize_target(std::forward<Callable>(target));
+ }
+
+ // Used by derived "impl" classes to implement operator=().
+ // Assigns the function with a target moved from another function,
+ // leaving the other function with an empty target.
+ void assign(function_base&& other) {
+ destroy_target();
+ move_target_from(std::move(other));
+ }
+
+ void swap(function_base& other) {
+ if (&other == this)
+ return;
+ ops_type temp_ops = ops_;
+ storage_type temp_bits;
+ ops_->move(&bits_, &temp_bits);
+
+ ops_ = other.ops_;
+ other.ops_->move(&other.bits_, &bits_);
+
+ other.ops_ = temp_ops;
+ temp_ops->move(&temp_bits, &other.bits_);
+ }
+
+ // returns an opaque ID unique to the |Callable| type of the target.
+ // Used by check_target_type.
+ const void* target_type_id() const { return ops_->target_type_id(&bits_, ops_); }
+
+ // Deleted copy constructor and assign. |function_base| implementations are
+ // move-only.
+ function_base(const function_base& other) = delete;
+ function_base& operator=(const function_base& other) = delete;
+
+ // Move assignment must be provided by subclasses.
+ function_base& operator=(function_base&& other) = delete;
+
+private:
+ // Implements the move operation, used by move construction and move
+ // assignment. Leaves other target initialized to null.
+ void move_target_from(function_base&& other) {
+ ops_ = other.ops_;
+ other.ops_->move(&other.bits_, &bits_);
+ other.initialize_null_target();
+ }
+
+ // fit::function and fit::callback are not directly copyable, but share()
+ // will create shared references to the original object. This method
+ // implements the copy operation for the |std::shared_ptr| wrapper.
+ template <typename SharedFunction>
+ void copy_shared_target_to(SharedFunction& copy) {
+ copy.destroy_target();
+ assert(ops_ == &shared_target_type<SharedFunction>::ops);
+ shared_target_type<SharedFunction>::copy_shared_ptr(&bits_, &copy.bits_);
+ copy.ops_ = ops_;
+ }
+
+ // assumes target is uninitialized
+ void initialize_null_target() { ops_ = &null_target_type::ops; }
+
+ // target may or may not be initialized.
+ template <typename Callable>
+ void initialize_target(Callable&& target) {
+ // Convert function or function references to function pointer.
+ using DecayedCallable = std::decay_t<Callable>;
+ static_assert(
+ std::alignment_of<DecayedCallable>::value <= std::alignment_of<storage_type>::value,
+ "Alignment of Callable must be <= alignment of max_align_t.");
+ static_assert(!requireInline || sizeof(DecayedCallable) <= inline_target_size,
+ "Callable too large to store inline as requested.");
+ if (is_null(target)) {
+ initialize_null_target();
+ } else {
+ ops_ = &target_type<DecayedCallable>::ops;
+ target_type<DecayedCallable>::initialize(&bits_, std::forward<Callable>(target));
+ }
+ }
+
+ // assumes target is uninitialized
+ template <typename SharedFunction>
+ void convert_to_shared_target() {
+ shared_target_type<SharedFunction>::initialize(
+ &bits_, std::move(*static_cast<SharedFunction*>(this)));
+ ops_ = &shared_target_type<SharedFunction>::ops;
+ }
+
+ // leaves target uninitialized
+ void destroy_target() { ops_->destroy(&bits_); }
+
+ // Called by target() if |check| is true.
+ // Checks the template parameter, usually inferred from the context of
+ // the call to target(), and aborts the program if it can determine that
+ // the Callable type is not compatible with the function's Result and Args.
+ template <typename Callable>
+ void check_target_type() const {
+ if (target_type<Callable>::ops.target_type_id(nullptr, &target_type<Callable>::ops) !=
+ target_type_id()) {
+ __builtin_abort();
+ }
+ }
+
+ ops_type ops_;
+ mutable storage_type bits_;
+};
+
+} // namespace internal
+
+} // namespace fit
+} // namespace android::base
diff --git a/android-emu/android/base/fit/Nullable.h b/android-emu/android/base/fit/Nullable.h
new file mode 100644
index 00000000..e05021bb
--- /dev/null
+++ b/android-emu/android/base/fit/Nullable.h
@@ -0,0 +1,265 @@
+// Copyright 2021 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#pragma once
+
+#include <assert.h>
+
+#include <optional>
+#include <type_traits>
+#include <utility>
+
+namespace android::base {
+namespace fit {
+
+// Determines whether a type can be compared with nullptr.
+template <typename T, typename Comparable = bool>
+struct IsComparableWithNull : public std::false_type {};
+template <typename T>
+struct IsComparableWithNull<T, decltype(std::declval<const T&>() == nullptr)>
+ : public std::true_type {};
+
+// Suppress the warning when the compiler can see that a nullable value is
+// never equal to nullptr.
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Waddress"
+template <typename T, std::enable_if_t<IsComparableWithNull<T>::value, bool> = true>
+constexpr inline bool isNull(T&& value) {
+ return std::forward<T>(value) == nullptr;
+}
+#pragma GCC diagnostic pop
+
+template <typename T, std::enable_if_t<!IsComparableWithNull<T>::value, bool> = false>
+constexpr inline bool isNull(T&&) {
+ return false;
+}
+
+// Determines whether a type can be initialized, assigned, and compared
+// with nullptr.
+template <typename T>
+struct IsNullable
+ : public std::integral_constant<bool,
+ std::is_constructible<T, decltype(nullptr)>::value &&
+ std::is_assignable<T&, decltype(nullptr)>::value &&
+ IsComparableWithNull<T>::value> {};
+template <>
+struct IsNullable<void> : public std::false_type {};
+
+// Holds a value or nullptr.
+//
+// This class is similar to |std::optional<T>| except that it uses less
+// storage when the value type can be initialized, assigned, and compared
+// with nullptr.
+//
+// For example:
+// - sizeof(fit::nullable<void*>) == sizeof(void*)
+// - sizeof(std::optional<void*>) == sizeof(struct { bool; void*; })
+// - sizeof(fit::nullable<int>) == sizeof(struct { bool; int; })
+// - sizeof(std::optional<int>) == sizeof(struct { bool; int; })
+//
+// TODO(fxbug.dev/4681): fit::nullable does not precisely mirror
+// std::optional. This should be corrected to avoid surprises when switching
+// between the types.
+template <typename T,
+ bool = (IsNullable<T>::value && std::is_constructible<T, T&&>::value &&
+ std::is_assignable<T&, T&&>::value)>
+class Nullable final {
+public:
+ using value_type = T;
+
+ ~Nullable() = default;
+ constexpr Nullable() = default;
+
+ explicit constexpr Nullable(decltype(nullptr)) {}
+ explicit constexpr Nullable(T value) : mOpt(std::move(value)) {}
+
+ constexpr Nullable(const Nullable& other) = default;
+ constexpr Nullable& operator=(const Nullable& other) = default;
+
+ constexpr Nullable(Nullable&& other) = default;
+ constexpr Nullable& operator=(Nullable&& other) = default;
+
+ constexpr T& value() & { return mOpt.value(); }
+ constexpr const T& value() const& { return mOpt.value(); }
+ constexpr T&& value() && { return std::move(mOpt.value()); }
+ constexpr const T&& value() const&& { return std::move(mOpt.value()); }
+
+ template <typename U = T>
+ constexpr T valueOr(U&& default_value) const {
+ return mOpt.value_or(std::forward<U>(default_value));
+ }
+
+ constexpr T* operator->() { return &*mOpt; }
+ constexpr const T* operator->() const { return &*mOpt; }
+ constexpr T& operator*() { return *mOpt; }
+ constexpr const T& operator*() const { return *mOpt; }
+
+ constexpr bool hasValue() const { return mOpt.has_value(); }
+ explicit constexpr operator bool() const { return hasValue(); }
+
+ constexpr Nullable& operator=(decltype(nullptr)) {
+ reset();
+ return *this;
+ }
+
+ constexpr Nullable& operator=(T value) {
+ mOpt = std::move(value);
+ return *this;
+ }
+
+ constexpr void reset() { mOpt.reset(); }
+
+ constexpr void swap(Nullable& other) { mOpt.swap(other.mOpt); }
+
+private:
+ std::optional<T> mOpt;
+};
+
+template <typename T>
+class Nullable<T, true> final {
+public:
+ using value_type = T;
+
+ constexpr Nullable() : mValue(nullptr) {}
+ explicit constexpr Nullable(decltype(nullptr)) : mValue(nullptr) {}
+ explicit constexpr Nullable(T value) : mValue(std::move(value)) {}
+ constexpr Nullable(const Nullable& other) = default;
+ constexpr Nullable(Nullable&& other) : mValue(std::move(other.value_)) {}
+ ~Nullable() = default;
+
+ constexpr T& value() & {
+ if (hasValue()) {
+ return mValue;
+ } else {
+ __builtin_abort();
+ }
+ }
+ constexpr const T& value() const& {
+ if (hasValue()) {
+ return mValue;
+ } else {
+ __builtin_abort();
+ }
+ }
+ constexpr T&& value() && {
+ if (hasValue()) {
+ return std::move(mValue);
+ } else {
+ __builtin_abort();
+ }
+ }
+ constexpr const T&& value() const&& {
+ if (hasValue()) {
+ return std::move(mValue);
+ } else {
+ __builtin_abort();
+ }
+ }
+
+ template <typename U = T>
+ constexpr T valueOr(U&& default_value) const {
+ return hasValue() ? mValue : static_cast<T>(std::forward<U>(default_value));
+ }
+
+ constexpr T* operator->() { return &mValue; }
+ constexpr const T* operator->() const { return &mValue; }
+ constexpr T& operator*() { return mValue; }
+ constexpr const T& operator*() const { return mValue; }
+
+ constexpr bool hasValue() const { return !(mValue == nullptr); }
+ explicit constexpr operator bool() const { return hasValue(); }
+
+ constexpr Nullable& operator=(const Nullable& other) = default;
+ constexpr Nullable& operator=(Nullable&& other) {
+ mValue = std::move(other.value_);
+ return *this;
+ }
+
+ constexpr Nullable& operator=(decltype(nullptr)) {
+ reset();
+ return *this;
+ }
+
+ constexpr Nullable& operator=(T value) {
+ mValue = std::move(value);
+ return *this;
+ }
+
+ constexpr void reset() { mValue = nullptr; }
+
+ constexpr void swap(Nullable& other) {
+ using std::swap;
+ swap(mValue, other.value_);
+ }
+
+private:
+ T mValue;
+};
+
+template <typename T>
+void swap(Nullable<T>& a, Nullable<T>& b) {
+ a.swap(b);
+}
+
+template <typename T>
+constexpr bool operator==(const Nullable<T>& lhs, decltype(nullptr)) {
+ return !lhs.hasValue();
+}
+template <typename T>
+constexpr bool operator!=(const Nullable<T>& lhs, decltype(nullptr)) {
+ return lhs.hasValue();
+}
+
+template <typename T>
+constexpr bool operator==(decltype(nullptr), const Nullable<T>& rhs) {
+ return !rhs.hasValue();
+}
+template <typename T>
+constexpr bool operator!=(decltype(nullptr), const Nullable<T>& rhs) {
+ return rhs.hasValue();
+}
+
+template <typename T, typename U>
+constexpr bool operator==(const Nullable<T>& lhs, const Nullable<U>& rhs) {
+ return (lhs.hasValue() == rhs.hasValue()) && (!lhs.hasValue() || *lhs == *rhs);
+}
+template <typename T, typename U>
+constexpr bool operator!=(const Nullable<T>& lhs, const Nullable<U>& rhs) {
+ return (lhs.hasValue() != rhs.hasValue()) || (lhs.hasValue() && *lhs != *rhs);
+}
+
+template <typename T, typename U>
+constexpr bool operator==(const Nullable<T>& lhs, const U& rhs) {
+ return (lhs.hasValue() != isNull(rhs)) && (!lhs.hasValue() || *lhs == rhs);
+}
+template <typename T, typename U>
+constexpr bool operator!=(const Nullable<T>& lhs, const U& rhs) {
+ return (lhs.hasValue() == isNull(rhs)) || (lhs.hasValue() && *lhs != rhs);
+}
+
+template <typename T, typename U>
+constexpr bool operator==(const T& lhs, const Nullable<U>& rhs) {
+ return (isNull(lhs) != rhs.hasValue()) && (!rhs.hasValue() || lhs == *rhs);
+}
+template <typename T, typename U>
+constexpr bool operator!=(const T& lhs, const Nullable<U>& rhs) {
+ return (isNull(lhs) == rhs.hasValue()) || (rhs.hasValue() && lhs != *rhs);
+}
+
+} // namespace fit
+} // namespace android::base
diff --git a/android-emu/android/base/fit/README b/android-emu/android/base/fit/README
new file mode 100644
index 00000000..4b3eeebe
--- /dev/null
+++ b/android-emu/android/base/fit/README
@@ -0,0 +1,150 @@
+libfit
+
+Source: https://fuchsia.googlesource.com/fuchsia/+/main/sdk/lib/fit/
+Version: 36303cd2d1611cb1b670235692d01a92e83ecd21
+License:
+
+Copyright 2019 The Fuchsia Authors.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+======
+
+FIT is a lean library of portable C++ abstractions for control flow and
+memory management beyond what is offered by the C++ 17 standard library.
+
+FIT only depends on the C++ language and standard library, including some C++17
+library features. It offers essential enhancements to the C++ standard library
+rather than attempting to replace it or become a framework for writing
+applications. FIT can be thought of as an "annex" that expresses a few ideas
+we wish the C++ standard library might itself implement someday.
+
+FIT is lean.
+
+## What Belongs in FIT
+
+Several Fuchsia SDK libraries, such as *libfidl*, depend on FIT and on the C++
+standard library. As these libraries are broadly used, we must take care in
+deciding what features to include in FIT to avoid burdening developers with
+unnecessary code or dependencies.
+
+In general, the goal is to identify specific abstractions that make sense to
+generalize across the entire ecosystem of Fuchsia C++ applications. These will
+necessarily be somewhat low-level but high impact. We don't want to add code to
+FIT simply because we think it's cool. We need evidence that it is a common
+idiom and that a broad audience of developers will significantly benefit from
+its promotion.
+
+Here are a few criteria to consider:
+
+- Is the feature lightweight, general-purpose, and platform-independent?
+- Is the feature not well served by other means, particularly by the C++
+ standard library?
+- Is the feature needed by a Fuchsia SDK library?
+- Does the feature embody a beneficial idiom that clients of the Fuchsia SDK
+ commonly use?
+- Has the feature been re-implemented many times already leading to code
+ fragmentation that we would like to eliminate?
+
+If in doubt, leave it out. See [Justifications] below.
+
+## What Doesn't Belong in FIT
+
+FIT is not intended to become a catch-all class library.
+
+Specifically prohibited features:
+
+- Features that introduce dependencies on libraries other than the C and C++
+ standard library.
+- Features that only work on certain operating systems.
+- Collection classes where the C++ 17 standard library already offers an
+ adequate (if not perfect) alternative.
+- Classes that impose an implementation burden on clients such as event loops,
+ dispatchers, frameworks, and other glue code.
+
+## Implementation Considerations
+
+FIT is not exception safe (but could be made to be in the future).
+
+## Style Conventions
+
+The API style was modified to fit current android::base library conventions.
+
+In brief:
+
+- Class identifiers are CamelCase
+- Class methods and variable identifiers use "camelCase", class fields use
+ "mCamelCase".
+- Template parameters are `CamelCase`.
+- Preprocessor macros are `UPPER_SNAKE_CASE`.
+
+## Justifications
+
+These sections explain why certain features are in FIT.
+
+### fit::Function
+
+- *libfidl*'s API needs a callable function wrapper with move semantics but
+ C++ 14's `std::function` only supports copyable function objects which forces
+ FIDL to allocate callback state on the heap making programs less efficient
+ and harder to write.
+- Lots of other C++ code uses callbacks extensively and would benefit from move
+ semantics for similar reasons.
+- So we should create a move-only function wrapper to use everywhere.
+
+### fit::Defer
+
+- When writing asynchronous event-driven programs, it can become challenging
+ to ensure that resources remain in scope for the duration of an operation
+ in progress and are subsequently released.
+- The C++ 14 standard library offers several classes with RAII semantics, such
+ as `std::unique_ptr`, which are helpful in these situations. Unfortunately the
+ C++ 14 standard library does not offer affordances for easily invoking a
+ function when a block or object goes out of scope short of implementing a
+ new class from scratch.
+- We have observed several re-implementations of the same idea throughout the
+ system.
+- So we should create a simple way to invoke a function on scope exit.
+
+### fit::Nullable
+
+- Case study: fit::defer has a need to store a closure that may be nullable.
+ We were able to replace its hand-rolled lifetime management code with
+ fit::nullable thereby vastly simplifying its implementation.
+- Case study: fit::future has a need to track its own validity along with
+ a continuation that may or not be present.
+- Case study: We have previously observed bugs where developers were
+ surprised when assigning a null closure to wrappers such as fit::function
+ fit::defer, or fit::future left these objects in a supposedly "valid"
+ but uninvocable state. These objects therefore take care to detect
+ null closures and enter an "invalid" state. Using fit::is_null and
+ fit::nullable makes it easier to eliminate this redundant state and
+ simplifies the API for clients of these wrappers.
+- std::optional can be effective here but it doesn't directly handle nullity
+ so it takes more care to coalesce the null and "not present" states.
+ std::optional also increases the size of the object to carry an extra
+ bool and passing, whereas fit::nullable eliminates this overhead by
+ taking advantage of the underlying value's null state (if there is one).
+- So we introduce fit::nullable to handle both cases systematically while
+ still hewing close to the semantics of std::optional.
diff --git a/android-emu/android/base/fit/ThreadChecker.h b/android-emu/android/base/fit/ThreadChecker.h
new file mode 100644
index 00000000..3859ecf1
--- /dev/null
+++ b/android-emu/android/base/fit/ThreadChecker.h
@@ -0,0 +1,87 @@
+// Copyright 2021 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Copyright 2016 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// A class for checking that the current thread is/isn't the same as an initial
+// thread.
+
+#pragma once
+
+#include <assert.h>
+
+#include <thread>
+
+#include "ThreadSafety.h"
+
+namespace android::base {
+namespace fit {
+
+// A simple class that records the identity of the thread that it was created
+// on, and at later points can tell if the current thread is the same as its
+// creation thread. This class is thread-safe.
+//
+// In addition to providing an explicit check of the current thread,
+// |thread_checker| complies with BasicLockable, checking the current thread
+// when |lock| is called. This allows static thread safety analysis to be used
+// to ensure that resources are accessed in a context that is checked (at debug
+// runtime) to ensure that it's running on the correct thread:
+//
+// class MyClass {
+// public:
+// void Foo() {
+// std::lock_guard<fit::thread_checker> locker(thread_checker_);
+// resource_ = 0;
+// }
+// private:
+// fit::thread_checker thread_checker_;
+// int resource_ GUARDED_BY(thread_checker_);
+// }
+//
+// Note: |lock| checks the thread in debug builds only.
+//
+class CAPABILITY("mutex") ThreadChecker final {
+public:
+ // Default constructor. Constructs a thread checker bound to the currently
+ // running thread.
+ ThreadChecker() : self_(std::this_thread::get_id()) {}
+ // Constructs a thread checker bound to an explicit other thread.
+ explicit ThreadChecker(std::thread::id self) : self_(self) {}
+ ~ThreadChecker() = default;
+
+ // Returns true if the current thread is the thread this object was created
+ // on and false otherwise.
+ bool isThreadValid() const { return std::this_thread::get_id() == self_; }
+
+ // Implementation of the BaseLockable requirement
+ void lock() ACQUIRE() { assert(isThreadValid()); }
+
+ void unlock() RELEASE() {}
+
+private:
+ const std::thread::id self_;
+};
+
+#ifndef NDEBUG
+#define DECLARE_THREAD_CHECKER(c) android::base::fit::ThreadChecker c
+#define DCHECK_IS_THREAD_VALID(c) assert((c).isThreadValid())
+#else
+#define DECLARE_THREAD_CHECKER(c)
+#define DCHECK_IS_THREAD_VALID(c) ((void)0)
+#endif
+
+} // namespace fit
+} // namespace android::base
diff --git a/android-emu/android/base/fit/ThreadSafety.h b/android-emu/android/base/fit/ThreadSafety.h
new file mode 100644
index 00000000..bce528e4
--- /dev/null
+++ b/android-emu/android/base/fit/ThreadSafety.h
@@ -0,0 +1,81 @@
+// Copyright 2021 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#pragma once
+
+// Other libraries (e.g. libbase) may have already defined these symbols.
+// Only define them if they are not defined elsewhere.
+
+// Thread-safety annotations.
+// Currently these are only supported on Clang.
+#ifndef THREAD_ANNOTATION_ATTRIBUTE__
+#if defined(__clang__) && defined(_LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS) && \
+ __has_attribute(acquire_capability)
+#define THREAD_ANNOTATION_ATTRIBUTE__(x) __attribute__((x))
+#else
+#define THREAD_ANNOTATION_ATTRIBUTE__(x)
+#endif
+#endif // THREAD_ANNOTATION_ATTRIBUTE__
+
+#ifndef CAPABILITY
+#define CAPABILITY(x) THREAD_ANNOTATION_ATTRIBUTE__(__capability__(x))
+#endif // CAPABILITY
+
+#ifndef GUARDED_BY
+#define GUARDED_BY(x) THREAD_ANNOTATION_ATTRIBUTE__(__guarded_by__(x))
+#endif // GUARDED_BY
+
+#ifndef ACQUIRE
+#define ACQUIRE(...) THREAD_ANNOTATION_ATTRIBUTE__(__acquire_capability__(__VA_ARGS__))
+#endif // ACQUIRE
+
+#ifndef TRY_ACQUIRE
+#define TRY_ACQUIRE(...) THREAD_ANNOTATION_ATTRIBUTE__(__try_acquire_capability__(__VA_ARGS__))
+#endif // TRY_ACQUIRE
+
+#ifndef ACQUIRED_BEFORE
+#define ACQUIRED_BEFORE(...) THREAD_ANNOTATION_ATTRIBUTE__(__acquired_before__(__VA_ARGS__))
+#endif // ACQUIRED_BEFORE
+
+#ifndef ACQUIRED_AFTER
+#define ACQUIRED_AFTER(...) THREAD_ANNOTATION_ATTRIBUTE__(__acquired_after__(__VA_ARGS__))
+#endif // ACQUIRED_AFTER
+
+#ifndef RELEASE
+#define RELEASE(...) THREAD_ANNOTATION_ATTRIBUTE__(__release_capability__(__VA_ARGS__))
+#endif // RELEASE
+
+#ifndef REQUIRES
+#define REQUIRES(...) THREAD_ANNOTATION_ATTRIBUTE__(__requires_capability__(__VA_ARGS__))
+#endif // REQUIRES
+
+#ifndef EXCLUDES
+#define EXCLUDES(...) THREAD_ANNOTATION_ATTRIBUTE__(__locks_excluded__(__VA_ARGS__))
+#endif // EXCLUDES
+
+#ifndef RETURN_CAPABILITY
+#define RETURN_CAPABILITY(x) THREAD_ANNOTATION_ATTRIBUTE__(__lock_returned__(x))
+#endif // RETURN_CAPABILITY
+
+#ifndef SCOPED_CAPABILITY
+#define SCOPED_CAPABILITY THREAD_ANNOTATION_ATTRIBUTE__(__scoped_lockable__)
+#endif // SCOPED_CAPABILITY
+
+#ifndef NO_THREAD_SAFETY_ANALYSIS
+#define NO_THREAD_SAFETY_ANALYSIS THREAD_ANNOTATION_ATTRIBUTE__(__no_thread_safety_analysis__)
+#endif // NO_THREAD_SAFETY_ANALYSIS
diff --git a/android-emu/android/base/fit/UtilityInternal.h b/android-emu/android/base/fit/UtilityInternal.h
new file mode 100644
index 00000000..274105e0
--- /dev/null
+++ b/android-emu/android/base/fit/UtilityInternal.h
@@ -0,0 +1,146 @@
+// Copyright 2021 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Copyright 2019 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#pragma once
+
+#include <type_traits>
+#include <utility>
+
+namespace android::base {
+namespace fit {
+namespace internal {
+
+// Utility to return the first type in a parameter pack.
+template <typename... Ts>
+struct First;
+template <typename FirstType, typename... Rest>
+struct First<FirstType, Rest...> {
+ using Type = FirstType;
+};
+
+template <typename... Ts>
+using First_t = typename First<Ts...>::Type;
+
+// Utility to count the occurences of type T in the parameter pack Ts.
+template <typename T, typename... Ts>
+struct OccurencesOf : std::integral_constant<size_t, 0> {};
+template <typename T, typename U>
+struct OccurencesOf<T, U> : std::integral_constant<size_t, std::is_same<T, U>::value> {};
+template <typename T, typename First, typename... Rest>
+struct OccurencesOf<T, First, Rest...>
+ : std::integral_constant<size_t,
+ OccurencesOf<T, First>::value + OccurencesOf<T, Rest...>::value> {};
+
+template <typename T, typename... Ts>
+constexpr size_t occurencesOf = OccurencesOf<T, Ts...>::value;
+
+// Utility to remove const, volatile, and reference qualifiers.
+template <typename T>
+using RemoveCvref_t = std::remove_cv_t<std::remove_reference_t<T>>;
+
+// Evaluates to truth-like when type T matches type U with cv-reference removed.
+template <typename T, typename U>
+using NotSameType = std::negation<std::is_same<T, RemoveCvref_t<U>>>;
+
+// Concept helper for constructors.
+template <typename... Conditions>
+using RequiresConditions = std::enable_if_t<std::conjunction_v<Conditions...>, bool>;
+
+// Concept helper for assignment operators.
+template <typename Return, typename... Conditions>
+using AssignmentRequiresConditions =
+ std::enable_if_t<std::conjunction_v<Conditions...>, std::add_lvalue_reference_t<Return>>;
+
+// Evaluates to true when every element type of Ts is trivially destructible.
+template <typename... Ts>
+constexpr bool isTriviallyDestructible = std::conjunction_v<std::is_trivially_destructible<Ts>...>;
+
+// Evaluates to true when every element type of Ts is trivially copyable.
+template <typename... Ts>
+constexpr bool isTriviallyCopyable =
+ (std::conjunction_v<std::is_trivially_copy_assignable<Ts>...> &&
+ std::conjunction_v<std::is_trivially_copy_constructible<Ts>...>);
+
+// Evaluates to true when every element type of Ts is trivially movable.
+template <typename... Ts>
+constexpr bool isTriviallyMovable =
+ (std::conjunction_v<std::is_trivially_move_assignable<Ts>...> &&
+ std::conjunction_v<std::is_trivially_move_constructible<Ts>...>);
+
+// Enable if relational operator is convertible to bool and the optional
+// conditions are true.
+template <typename Op, typename... Conditions>
+using enable_relop_t =
+ std::enable_if_t<(std::is_convertible<Op, bool>::value && std::conjunction_v<Conditions...>),
+ bool>;
+
+template <typename T>
+struct Identity {
+ using Type = T;
+};
+
+// Evaluates to true when T is an unbounded array.
+template <typename T>
+struct IsUnboundedArray : std::conjunction<std::is_array<T>, std::negation<std::extent<T>>> {};
+
+// Returns true when T is a complete type or an unbounded array.
+template <typename T, size_t = sizeof(T)>
+constexpr bool isCompleteOrUnboundedArray(Identity<T>) {
+ return true;
+}
+template <typename Identity, typename T = typename Identity::Type>
+constexpr bool isCompleteOrUnboundedArray(Identity) {
+ return std::disjunction<std::is_reference<T>, std::is_function<T>, std::is_void<T>,
+ IsUnboundedArray<T>>::value;
+}
+
+// Using swap for ADL. This directive is contained within the fit::internal
+// namespace, which prevents leaking std::swap into user namespaces. Doing this
+// at namespace scope is necessary to lookup swap via ADL while preserving the
+// noexcept() specification of the resulting lookup.
+using std::swap;
+
+// Evaluates to true when T is swappable.
+template <typename T, typename = void>
+struct IsSwappable : std::false_type {
+ static_assert(isCompleteOrUnboundedArray(Identity<T>{}),
+ "T must be a complete type or an unbounded array!");
+};
+template <typename T>
+struct IsSwappable<T, std::void_t<decltype(swap(std::declval<T&>(), std::declval<T&>()))>>
+ : std::true_type {
+ static_assert(isCompleteOrUnboundedArray(Identity<T>{}),
+ "T must be a complete type or an unbounded array!");
+};
+
+// Evaluates to true when T is nothrow swappable.
+template <typename T, typename = void>
+struct IsNothrowSwappable : std::false_type {
+ static_assert(isCompleteOrUnboundedArray(Identity<T>{}),
+ "T must be a complete type or an unbounded array!");
+};
+template <typename T>
+struct IsNothrowSwappable<T, std::void_t<decltype(swap(std::declval<T&>(), std::declval<T&>()))>>
+ : std::integral_constant<bool, noexcept(swap(std::declval<T&>(), std::declval<T&>()))> {
+ static_assert(isCompleteOrUnboundedArray(Identity<T>{}),
+ "T must be a complete type or an unbounded array!");
+};
+
+} // namespace internal
+} // namespace fit
+} // namespace android::base