aboutsummaryrefslogtreecommitdiff
path: root/third_party/fuchsia/repo/sdk/lib/fit/include/lib
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/fuchsia/repo/sdk/lib/fit/include/lib')
-rw-r--r--third_party/fuchsia/repo/sdk/lib/fit/include/lib/fit/defer.h145
-rw-r--r--third_party/fuchsia/repo/sdk/lib/fit/include/lib/fit/function.h138
-rw-r--r--third_party/fuchsia/repo/sdk/lib/fit/include/lib/fit/internal/compiler.h19
-rw-r--r--third_party/fuchsia/repo/sdk/lib/fit/include/lib/fit/internal/function.h100
-rw-r--r--third_party/fuchsia/repo/sdk/lib/fit/include/lib/fit/internal/result.h17
-rw-r--r--third_party/fuchsia/repo/sdk/lib/fit/include/lib/fit/internal/utility.h6
-rw-r--r--third_party/fuchsia/repo/sdk/lib/fit/include/lib/fit/nullable.h20
-rw-r--r--third_party/fuchsia/repo/sdk/lib/fit/include/lib/fit/result.h18
-rw-r--r--third_party/fuchsia/repo/sdk/lib/fit/include/lib/fit/traits.h6
9 files changed, 319 insertions, 150 deletions
diff --git a/third_party/fuchsia/repo/sdk/lib/fit/include/lib/fit/defer.h b/third_party/fuchsia/repo/sdk/lib/fit/include/lib/fit/defer.h
new file mode 100644
index 000000000..907a3b77e
--- /dev/null
+++ b/third_party/fuchsia/repo/sdk/lib/fit/include/lib/fit/defer.h
@@ -0,0 +1,145 @@
+// 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.
+
+#ifndef LIB_FIT_DEFER_H_
+#define LIB_FIT_DEFER_H_
+
+#include <utility>
+
+#include "function.h"
+#include "nullable.h"
+
+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 deferred_action final {
+ public:
+ // Creates a deferred action without a pending target.
+ deferred_action() = default;
+ explicit deferred_action(decltype(nullptr)) {}
+
+ // Creates a deferred action with a pending target.
+ explicit deferred_action(T target) : target_(std::move(target)) {}
+
+ // Creates a deferred action with a pending target moved from another
+ // deferred action, leaving the other one without a pending target.
+ deferred_action(deferred_action&& other) : target_(std::move(other.target_)) {
+ other.target_.reset();
+ }
+
+ // Invokes and releases the deferred action's pending target (if any).
+ ~deferred_action() { call(); }
+
+ // Returns true if the deferred action has a pending target.
+ explicit operator bool() const { return !!target_; }
+
+ // 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.
+ deferred_action& operator=(deferred_action&& other) {
+ if (&other == this)
+ return *this;
+ call();
+ target_ = std::move(other.target_);
+ other.target_.reset();
+ return *this;
+ }
+
+ // Invokes and releases the deferred action's pending target (if any).
+ void call() {
+ if (target_) {
+ // Move to a local to guard against re-entrance.
+ T local_target = std::move(*target_);
+ target_.reset();
+ local_target();
+ }
+ }
+
+ // Releases the deferred action's pending target (if any) without
+ // invoking it.
+ void cancel() { target_.reset(); }
+ deferred_action& operator=(decltype(nullptr)) {
+ cancel();
+ return *this;
+ }
+
+ // Assigns a new target to the deferred action.
+ deferred_action& operator=(T target) {
+ target_ = std::move(target);
+ return *this;
+ }
+
+ deferred_action(const deferred_action& other) = delete;
+ deferred_action& operator=(const deferred_action& other) = delete;
+
+ private:
+ nullable<T> target_;
+};
+
+template <typename T>
+bool operator==(const deferred_action<T>& action, decltype(nullptr)) {
+ return !action;
+}
+template <typename T>
+bool operator==(decltype(nullptr), const deferred_action<T>& action) {
+ return !action;
+}
+template <typename T>
+bool operator!=(const deferred_action<T>& action, decltype(nullptr)) {
+ return !!action;
+}
+template <typename T>
+bool operator!=(decltype(nullptr), const deferred_action<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>
+__attribute__((__warn_unused_result__)) inline deferred_action<T> defer(T target) {
+ return deferred_action<T>(std::move(target));
+}
+
+// Alias for a deferred_action using a fit::callback.
+using deferred_callback = deferred_action<fit::callback<void()>>;
+
+// Defers execution of a fit::callback with no arguments. See |fit::defer| for
+// details.
+__attribute__((__warn_unused_result__)) inline deferred_callback defer_callback(
+ fit::callback<void()> target) {
+ return deferred_callback(std::move(target));
+}
+
+} // namespace fit
+
+#endif // LIB_FIT_DEFER_H_
diff --git a/third_party/fuchsia/repo/sdk/lib/fit/include/lib/fit/function.h b/third_party/fuchsia/repo/sdk/lib/fit/include/lib/fit/function.h
index fba3e95c2..2403dee3b 100644
--- a/third_party/fuchsia/repo/sdk/lib/fit/include/lib/fit/function.h
+++ b/third_party/fuchsia/repo/sdk/lib/fit/include/lib/fit/function.h
@@ -2,9 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef LIB_FIT_INCLUDE_LIB_FIT_FUNCTION_H_
-#define LIB_FIT_INCLUDE_LIB_FIT_FUNCTION_H_
+#ifndef LIB_FIT_FUNCTION_H_
+#define LIB_FIT_FUNCTION_H_
+#include <cstddef>
+#include <memory>
#include <type_traits>
#include "internal/function.h"
@@ -13,14 +15,14 @@
namespace fit {
-template <size_t inline_target_size, bool require_inline, typename FunctionType>
+template <size_t inline_target_size, bool require_inline, typename FunctionType, typename Allocator>
class function_impl {
static_assert(std::is_function<FunctionType>::value,
"fit::function must be instantiated with a function type, such as void() or "
"int(char*, bool)");
};
-template <size_t inline_target_size, bool require_inline, typename FunctionType>
+template <size_t inline_target_size, bool require_inline, typename FunctionType, typename Allocator>
class callback_impl {
static_assert(std::is_function<FunctionType>::value,
"fit::callback must be instantiated with a function type, such as void() or "
@@ -33,6 +35,10 @@ class callback_impl {
// function.
constexpr size_t default_inline_target_size = sizeof(void*) * 2;
+// The default allocator used for allocating callables on the heap. Its `value_type` is irrelevant,
+// since it must support rebinding.
+using default_callable_allocator = std::allocator<std::byte>;
+
// A |fit::function| is a move-only polymorphic function wrapper.
//
// If you need a class with similar characteristics that also ensures
@@ -61,6 +67,9 @@ constexpr size_t default_inline_target_size = sizeof(void*) * 2;
// fit within a function without requiring heap allocation.
// Defaults to |default_inline_target_size|.
//
+// |Allocator| is the Allocator used for heap allocation, if required. Its `value_type` is
+// irrelevant, since it must support rebinding.
+//
// Class members are documented in |fit::function_impl|, below.
//
// EXAMPLES
@@ -70,9 +79,10 @@ constexpr size_t default_inline_target_size = sizeof(void*) * 2;
// -
// https://fuchsia.googlesource.com/fuchsia/+/HEAD/sdk/lib/fit/test/examples/function_example2.cc
//
-template <typename T, size_t inline_target_size = default_inline_target_size>
+template <typename T, size_t inline_target_size = default_inline_target_size,
+ typename Allocator = default_callable_allocator>
using function = function_impl<internal::RoundUpToWord(inline_target_size),
- /*require_inline=*/false, T>;
+ /*require_inline=*/false, T, Allocator>;
// A move-only callable object wrapper that forces callables to be stored inline
// and never performs heap allocation.
@@ -82,7 +92,7 @@ using function = function_impl<internal::RoundUpToWord(inline_target_size),
// compile.
template <typename T, size_t inline_target_size = default_inline_target_size>
using inline_function = function_impl<internal::RoundUpToWord(inline_target_size),
- /*require_inline=*/true, T>;
+ /*require_inline=*/true, T, default_callable_allocator>;
// Synonym for a function which takes no arguments and produces no result.
using closure = function<void()>;
@@ -153,11 +163,15 @@ using closure = function<void()>;
// fit within a callback without requiring heap allocation.
// Defaults to |default_inline_target_size|.
//
+// |Allocator| is the Allocator used for heap allocation, if required. Its `value_type` is
+// irrelevant, since it must support rebinding.
+//
// Class members are documented in |fit::callback_impl|, below.
//
-template <typename T, size_t inline_target_size = default_inline_target_size>
-using callback =
- callback_impl<internal::RoundUpToWord(inline_target_size), /*require_inline=*/false, T>;
+template <typename T, size_t inline_target_size = default_inline_target_size,
+ typename Allocator = default_callable_allocator>
+using callback = callback_impl<internal::RoundUpToWord(inline_target_size),
+ /*require_inline=*/false, T, Allocator>;
// A move-only, run-once, callable object wrapper that forces callables to be
// stored inline and never performs heap allocation.
@@ -167,19 +181,22 @@ using callback =
// compile.
template <typename T, size_t inline_target_size = default_inline_target_size>
using inline_callback = callback_impl<internal::RoundUpToWord(inline_target_size),
- /*require_inline=*/true, T>;
+ /*require_inline=*/true, T, default_callable_allocator>;
-template <size_t inline_target_size, bool require_inline, typename Result, typename... Args>
-class function_impl<inline_target_size, require_inline, Result(Args...)> final
- : private ::fit::internal::function_base<inline_target_size, require_inline, Result(Args...)> {
- using base = ::fit::internal::function_base<inline_target_size, require_inline, Result(Args...)>;
+template <size_t inline_target_size, bool require_inline, typename Allocator, typename Result,
+ typename... Args>
+class function_impl<inline_target_size, require_inline, Result(Args...), Allocator> final
+ : private ::fit::internal::function_base<inline_target_size, require_inline, Result(Args...),
+ Allocator> {
+ using base = ::fit::internal::function_base<inline_target_size, require_inline, Result(Args...),
+ Allocator>;
// function_base requires private access during share()
- friend class ::fit::internal::function_base<inline_target_size, require_inline, Result(Args...)>;
+ friend base;
// supports target() for shared functions
friend const void* ::fit::internal::get_target_type_id<>(
- const function_impl<inline_target_size, require_inline, Result(Args...)>&);
+ const function_impl<inline_target_size, require_inline, Result(Args...), Allocator>&);
template <typename U>
using not_self_type = ::fit::internal::not_same_type<function_impl, U>;
@@ -228,10 +245,9 @@ class function_impl<inline_target_size, require_inline, Result(Args...)> final
// 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 other_inline_target_size, bool other_require_inline>
- function_impl(
- ::fit::callback_impl<other_inline_target_size, other_require_inline, Result(Args...)>) =
- delete;
+ template <size_t other_inline_target_size, bool other_require_inline, typename OtherAllocator>
+ function_impl(::fit::callback_impl<other_inline_target_size, other_require_inline,
+ Result(Args...), OtherAllocator>) = delete;
// Creates a function with a target moved from another function,
// leaving the other function with an empty target.
@@ -273,10 +289,9 @@ class function_impl<inline_target_size, require_inline, Result(Args...)> final
// 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 other_inline_target_size, bool other_require_inline>
- function_impl& operator=(
- ::fit::callback_impl<other_inline_target_size, other_require_inline, Result(Args...)>) =
- delete;
+ template <size_t other_inline_target_size, bool other_require_inline, typename OtherAllocator>
+ function_impl& operator=(::fit::callback_impl<other_inline_target_size, other_require_inline,
+ Result(Args...), OtherAllocator>) = delete;
// Move assignment
function_impl& operator=(function_impl&& other) noexcept {
@@ -313,44 +328,49 @@ class function_impl<inline_target_size, require_inline, Result(Args...)> final
}
};
-template <size_t inline_target_size, bool require_inline, typename FunctionType>
-void swap(function_impl<inline_target_size, require_inline, FunctionType>& a,
- function_impl<inline_target_size, require_inline, FunctionType>& b) {
+template <size_t inline_target_size, bool require_inline, typename FunctionType, typename Allocator>
+void swap(function_impl<inline_target_size, require_inline, FunctionType, Allocator>& a,
+ function_impl<inline_target_size, require_inline, FunctionType, Allocator>& b) {
a.swap(b);
}
-template <size_t inline_target_size, bool require_inline, typename FunctionType>
-bool operator==(const function_impl<inline_target_size, require_inline, FunctionType>& f,
+template <size_t inline_target_size, bool require_inline, typename FunctionType, typename Allocator>
+bool operator==(const function_impl<inline_target_size, require_inline, FunctionType, Allocator>& f,
decltype(nullptr)) {
return !f;
}
-template <size_t inline_target_size, bool require_inline, typename FunctionType>
-bool operator==(decltype(nullptr),
- const function_impl<inline_target_size, require_inline, FunctionType>& f) {
+template <size_t inline_target_size, bool require_inline, typename FunctionType, typename Allocator>
+bool operator==(
+ decltype(nullptr),
+ const function_impl<inline_target_size, require_inline, FunctionType, Allocator>& f) {
return !f;
}
-template <size_t inline_target_size, bool require_inline, typename FunctionType>
-bool operator!=(const function_impl<inline_target_size, require_inline, FunctionType>& f,
+template <size_t inline_target_size, bool require_inline, typename FunctionType, typename Allocator>
+bool operator!=(const function_impl<inline_target_size, require_inline, FunctionType, Allocator>& f,
decltype(nullptr)) {
return !!f;
}
-template <size_t inline_target_size, bool require_inline, typename FunctionType>
-bool operator!=(decltype(nullptr),
- const function_impl<inline_target_size, require_inline, FunctionType>& f) {
+template <size_t inline_target_size, bool require_inline, typename FunctionType, typename Allocator>
+bool operator!=(
+ decltype(nullptr),
+ const function_impl<inline_target_size, require_inline, FunctionType, Allocator>& f) {
return !!f;
}
-template <size_t inline_target_size, bool require_inline, typename Result, typename... Args>
-class callback_impl<inline_target_size, require_inline, Result(Args...)> final
- : private ::fit::internal::function_base<inline_target_size, require_inline, Result(Args...)> {
- using base = ::fit::internal::function_base<inline_target_size, require_inline, Result(Args...)>;
+template <size_t inline_target_size, bool require_inline, typename Allocator, typename Result,
+ typename... Args>
+class callback_impl<inline_target_size, require_inline, Result(Args...), Allocator> final
+ : private ::fit::internal::function_base<inline_target_size, require_inline, Result(Args...),
+ Allocator> {
+ using base = ::fit::internal::function_base<inline_target_size, require_inline, Result(Args...),
+ Allocator>;
// function_base requires private access during share()
- friend class ::fit::internal::function_base<inline_target_size, require_inline, Result(Args...)>;
+ friend base;
// supports target() for shared functions
friend const void* ::fit::internal::get_target_type_id<>(
- const callback_impl<inline_target_size, require_inline, Result(Args...)>&);
+ const callback_impl<inline_target_size, require_inline, Result(Args...), Allocator>&);
template <typename U>
using not_self_type = ::fit::internal::not_same_type<callback_impl, U>;
@@ -469,30 +489,32 @@ class callback_impl<inline_target_size, require_inline, Result(Args...)> final
}
};
-template <size_t inline_target_size, bool require_inline, typename FunctionType>
-void swap(callback_impl<inline_target_size, require_inline, FunctionType>& a,
- callback_impl<inline_target_size, require_inline, FunctionType>& b) {
+template <size_t inline_target_size, bool require_inline, typename FunctionType, typename Allocator>
+void swap(callback_impl<inline_target_size, require_inline, FunctionType, Allocator>& a,
+ callback_impl<inline_target_size, require_inline, FunctionType, Allocator>& b) {
a.swap(b);
}
-template <size_t inline_target_size, bool require_inline, typename FunctionType>
-bool operator==(const callback_impl<inline_target_size, require_inline, FunctionType>& f,
+template <size_t inline_target_size, bool require_inline, typename FunctionType, typename Allocator>
+bool operator==(const callback_impl<inline_target_size, require_inline, FunctionType, Allocator>& f,
decltype(nullptr)) {
return !f;
}
-template <size_t inline_target_size, bool require_inline, typename FunctionType>
-bool operator==(decltype(nullptr),
- const callback_impl<inline_target_size, require_inline, FunctionType>& f) {
+template <size_t inline_target_size, bool require_inline, typename FunctionType, typename Allocator>
+bool operator==(
+ decltype(nullptr),
+ const callback_impl<inline_target_size, require_inline, FunctionType, Allocator>& f) {
return !f;
}
-template <size_t inline_target_size, bool require_inline, typename FunctionType>
-bool operator!=(const callback_impl<inline_target_size, require_inline, FunctionType>& f,
+template <size_t inline_target_size, bool require_inline, typename FunctionType, typename Allocator>
+bool operator!=(const callback_impl<inline_target_size, require_inline, FunctionType, Allocator>& f,
decltype(nullptr)) {
return !!f;
}
-template <size_t inline_target_size, bool require_inline, typename FunctionType>
-bool operator!=(decltype(nullptr),
- const callback_impl<inline_target_size, require_inline, FunctionType>& f) {
+template <size_t inline_target_size, bool require_inline, typename FunctionType, typename Allocator>
+bool operator!=(
+ decltype(nullptr),
+ const callback_impl<inline_target_size, require_inline, FunctionType, Allocator>& f) {
return !!f;
}
@@ -537,4 +559,4 @@ auto bind_member(T* instance) {
} // namespace fit
-#endif // LIB_FIT_INCLUDE_LIB_FIT_FUNCTION_H_
+#endif // LIB_FIT_FUNCTION_H_
diff --git a/third_party/fuchsia/repo/sdk/lib/fit/include/lib/fit/internal/compiler.h b/third_party/fuchsia/repo/sdk/lib/fit/include/lib/fit/internal/compiler.h
index 1bd806414..2b989a780 100644
--- a/third_party/fuchsia/repo/sdk/lib/fit/include/lib/fit/internal/compiler.h
+++ b/third_party/fuchsia/repo/sdk/lib/fit/include/lib/fit/internal/compiler.h
@@ -2,20 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef LIB_FIT_INCLUDE_LIB_FIT_INTERNAL_COMPILER_H_
-#define LIB_FIT_INCLUDE_LIB_FIT_INTERNAL_COMPILER_H_
+#ifndef LIB_FIT_INTERNAL_COMPILER_H_
+#define LIB_FIT_INTERNAL_COMPILER_H_
-// Annotate a class or function with C++17's [[nodiscard]] or similar where supported by the
-// compiler.
-//
-// C++14 doesn't support [[nodiscard]], but Clang allows __attribute__((warn_unused_result))
-// to be placed on class declarations. GCC only allows the attribute to be used on methods.
-#if __cplusplus >= 201703L
-#define LIB_FIT_NODISCARD [[nodiscard]]
-#elif defined(__clang__)
-#define LIB_FIT_NODISCARD __attribute__((__warn_unused_result__))
-#else
-#define LIB_FIT_NODISCARD /* nothing */
-#endif
-
-#endif // LIB_FIT_INCLUDE_LIB_FIT_INTERNAL_COMPILER_H_
+#endif // LIB_FIT_INTERNAL_COMPILER_H_
diff --git a/third_party/fuchsia/repo/sdk/lib/fit/include/lib/fit/internal/function.h b/third_party/fuchsia/repo/sdk/lib/fit/include/lib/fit/internal/function.h
index dd655f3d0..b2ac66626 100644
--- a/third_party/fuchsia/repo/sdk/lib/fit/include/lib/fit/internal/function.h
+++ b/third_party/fuchsia/repo/sdk/lib/fit/include/lib/fit/internal/function.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef LIB_FIT_INCLUDE_LIB_FIT_INTERNAL_FUNCTION_H_
-#define LIB_FIT_INCLUDE_LIB_FIT_INTERNAL_FUNCTION_H_
+#ifndef LIB_FIT_INTERNAL_FUNCTION_H_
+#define LIB_FIT_INTERNAL_FUNCTION_H_
#include <lib/stdcompat/bit.h>
#include <stddef.h>
@@ -68,7 +68,8 @@ struct target_ops final : public base_target_ops {
static_assert(sizeof(target_ops<void>) == sizeof(void (*)()) * 5, "Unexpected target_ops padding");
-template <typename Callable, bool is_inline, bool is_shared, typename Result, typename... Args>
+template <typename Callable, bool is_inline, bool is_shared, typename Allocator, typename Result,
+ typename... Args>
struct target;
inline void trivial_target_destroy(void* /*bits*/) {}
@@ -96,9 +97,10 @@ struct null_target {
static_assert(std::is_same<Unused, void>::value, "Only instantiate null_target with void");
};
-template <typename Result, typename... Args>
-struct target<decltype(nullptr), /*is_inline=*/true, /*is_shared=*/false, Result, Args...> final
- : public null_target<> {};
+template <typename Allocator, typename Result, typename... Args>
+struct target<decltype(nullptr), /*is_inline=*/true, /*is_shared=*/false, Allocator, Result,
+ Args...>
+ final : public null_target<> {};
inline void* null_target_get(void* /*bits*/) { return nullptr; }
inline void null_target_move(void* /*from_bits*/, void* /*to_bits*/) {}
@@ -117,10 +119,8 @@ inline void inline_trivial_target_move(void* from_bits, void* to_bits) {
std::memcpy(to_bits, from_bits, size_bytes);
}
-template <typename Callable, typename Result, typename... Args>
-struct target<Callable,
- /*is_inline=*/true, /*is_shared=*/false, Result, Args...>
- final {
+template <typename Callable, typename Allocator, typename Result, typename... Args>
+struct target<Callable, /*is_inline=*/true, /*is_shared=*/false, Allocator, Result, Args...> final {
template <typename Callable_>
static void initialize(void* bits, Callable_&& target) {
new (bits) Callable(std::forward<Callable_>(target));
@@ -160,23 +160,25 @@ struct target<Callable,
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::get_move_function(),
- target::get_destroy_function(), &target::invoke};
+template <typename Callable, typename Allocator, typename Result, typename... Args>
+constexpr target_ops<Result, Args...>
+ target<Callable, /*is_inline=*/true, /*is_shared=*/false, Allocator, Result, Args...>::ops = {
+ &unshared_target_type_id, &inline_target_get, target::get_move_function(),
+ target::get_destroy_function(), &target::invoke};
// vtable for pointer to target function
-template <typename Callable, typename Result, typename... Args>
-struct target<Callable,
- /*is_inline=*/false, /*is_shared=*/false, Result, Args...>
+template <typename Callable, typename Allocator, typename Result, typename... Args>
+struct target<Callable, /*is_inline=*/false, /*is_shared=*/false, Allocator, 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));
+ CallableAllocator allocator;
+ *ptr = CallableAllocatorTraits::allocate(allocator, 1u);
+ if (*ptr) {
+ CallableAllocatorTraits::construct(allocator, *ptr, std::forward<Callable_>(target));
+ }
}
static Result invoke(void* bits, Args... args) {
auto& target = **static_cast<Callable**>(bits);
@@ -189,19 +191,33 @@ struct target<Callable,
}
static void destroy(void* bits) {
auto ptr = static_cast<Callable**>(bits);
- delete *ptr;
+ if (*ptr) {
+ CallableAllocator allocator;
+ CallableAllocatorTraits::destroy(allocator, *ptr);
+ CallableAllocatorTraits::deallocate(allocator, *ptr, 1u);
+ *ptr = nullptr;
+ }
}
static const target_ops<Result, Args...> ops;
+
+ private:
+ using AllocatorTraits = std::allocator_traits<Allocator>;
+ using CallableAllocator = typename AllocatorTraits::template rebind_alloc<Callable>;
+ using CallableAllocatorTraits = std::allocator_traits<CallableAllocator>;
+
+ static_assert(CallableAllocatorTraits::is_always_equal::value,
+ "Objects of type Allocator must always be equal to each other: an Allocator object "
+ "must be able to deallocate the memory allocated by a different Allocator object.");
};
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::move, &target::destroy, &target::invoke};
+template <typename Callable, typename Allocator, typename Result, typename... Args>
+constexpr target_ops<Result, Args...>
+ target<Callable, /*is_inline=*/false, /*is_shared=*/false, Allocator, Result, Args...>::ops = {
+ &unshared_target_type_id, &heap_target_get, &target::move, &target::destroy,
+ &target::invoke};
// vtable for fit::function std::shared_ptr to target function
@@ -212,13 +228,12 @@ const void* get_target_type_id(const SharedFunction& function_or_callback) {
// 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...>
+template <typename SharedFunction, typename Allocator, typename Result, typename... Args>
+struct target<SharedFunction, /*is_inline=*/false, /*is_shared=*/true, Allocator, 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))));
+ std::move(std::allocate_shared<SharedFunction, Allocator>(Allocator(), 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);
@@ -246,10 +261,9 @@ struct target<SharedFunction,
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 = {
+template <typename SharedFunction, typename Allocator, typename Result, typename... Args>
+constexpr target_ops<Result, Args...> target<
+ SharedFunction, /*is_inline=*/false, /*is_shared=*/true, Allocator, Result, Args...>::ops = {
&target::target_type_id, &target::get, &target::move, &target::destroy, &target::invoke};
// Calculates the alignment to use for a function of the provided
@@ -388,13 +402,14 @@ class alignas(FunctionAlignment(inline_target_size)) generic_function_base {
const base_target_ops* ops_;
};
-template <size_t inline_target_size, bool require_inline, typename FunctionType>
+template <size_t inline_target_size, bool require_inline, typename FunctionType, typename Allocator>
class function_base;
// Function implementation details that require the function signature.
// See |fit::function| and |fit::callback| documentation for more information.
-template <size_t inline_target_size, bool require_inline, typename Result, typename... Args>
-class function_base<inline_target_size, require_inline, Result(Args...)>
+template <size_t inline_target_size, bool require_inline, typename Allocator, typename Result,
+ typename... Args>
+class function_base<inline_target_size, require_inline, Result(Args...), Allocator>
: public generic_function_base<inline_target_size> {
using base = generic_function_base<inline_target_size>;
@@ -407,11 +422,10 @@ class function_base<inline_target_size, require_inline, Result(Args...)>
template <typename Callable>
using target_type = target<Callable, (sizeof(Callable) <= inline_target_size),
- /*is_shared=*/false, Result, Args...>;
+ /*is_shared=*/false, Allocator, Result, Args...>;
template <typename SharedFunction>
- using shared_target_type = target<SharedFunction,
- /*is_inline=*/false,
- /*is_shared=*/true, Result, Args...>;
+ using shared_target_type =
+ target<SharedFunction, /*is_inline=*/false, /*is_shared=*/true, Allocator, Result, Args...>;
using ops_type = const target_ops<Result, Args...>*;
@@ -495,7 +509,7 @@ class function_base<inline_target_size, require_inline, Result(Args...)>
// 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.
- // TODO(b/241567321): Remove "no sanitize" after pw_protobuf is fixed.
+ // TODO: b/241567321 - Remove "no sanitize" after pw_protobuf is fixed.
Result invoke(Args... args) const PW_NO_SANITIZE("function") {
// Down cast the ops to the derived type that this function was instantiated
// with, which includes the invoke function.
@@ -564,4 +578,4 @@ class function_base<inline_target_size, require_inline, Result(Args...)>
} // namespace internal
} // namespace fit
-#endif // LIB_FIT_INCLUDE_LIB_FIT_INTERNAL_FUNCTION_H_
+#endif // LIB_FIT_INTERNAL_FUNCTION_H_
diff --git a/third_party/fuchsia/repo/sdk/lib/fit/include/lib/fit/internal/result.h b/third_party/fuchsia/repo/sdk/lib/fit/include/lib/fit/internal/result.h
index 18a0c8751..fe90c10d3 100644
--- a/third_party/fuchsia/repo/sdk/lib/fit/include/lib/fit/internal/result.h
+++ b/third_party/fuchsia/repo/sdk/lib/fit/include/lib/fit/internal/result.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef LIB_FIT_INCLUDE_LIB_FIT_INTERNAL_RESULT_H_
-#define LIB_FIT_INCLUDE_LIB_FIT_INTERNAL_RESULT_H_
+#ifndef LIB_FIT_INTERNAL_RESULT_H_
+#define LIB_FIT_INTERNAL_RESULT_H_
#include <lib/fit/internal/compiler.h>
#include <lib/stdcompat/type_traits.h>
@@ -258,12 +258,12 @@ struct storage_type<storage_class_e::non_trivial, E, T> {
return *this;
}
- constexpr storage_type(storage_type&& other) noexcept(
- std::is_nothrow_move_constructible<E>::value&& std::is_nothrow_move_constructible<T>::value) {
+ constexpr storage_type(storage_type&& other) noexcept(std::is_nothrow_move_constructible_v<E> &&
+ std::is_nothrow_move_constructible_v<T>) {
move_from(std::move(other));
}
constexpr storage_type& operator=(storage_type&& other) noexcept(
- std::is_nothrow_move_assignable<E>::value&& std::is_nothrow_move_assignable<T>::value) {
+ std::is_nothrow_move_assignable_v<E> && std::is_nothrow_move_assignable_v<T>) {
destroy();
move_from(std::move(other));
return *this;
@@ -375,12 +375,11 @@ struct storage_type<storage_class_e::non_trivial, E> {
return *this;
}
- constexpr storage_type(storage_type&& other) noexcept(
- std::is_nothrow_move_constructible<E>::value) {
+ constexpr storage_type(storage_type&& other) noexcept(std::is_nothrow_move_constructible_v<E>) {
move_from(std::move(other));
}
constexpr storage_type& operator=(storage_type&& other) noexcept(
- std::is_nothrow_move_assignable<E>::value) {
+ std::is_nothrow_move_assignable_v<E>) {
destroy();
move_from(std::move(other));
return *this;
@@ -442,4 +441,4 @@ using storage = storage_type<storage_class_trait<E, Ts...>, E, Ts...>;
} // namespace internal
} // namespace fit
-#endif // LIB_FIT_INCLUDE_LIB_FIT_INTERNAL_RESULT_H_
+#endif // LIB_FIT_INTERNAL_RESULT_H_
diff --git a/third_party/fuchsia/repo/sdk/lib/fit/include/lib/fit/internal/utility.h b/third_party/fuchsia/repo/sdk/lib/fit/include/lib/fit/internal/utility.h
index 2d1f8a03a..14f887725 100644
--- a/third_party/fuchsia/repo/sdk/lib/fit/include/lib/fit/internal/utility.h
+++ b/third_party/fuchsia/repo/sdk/lib/fit/include/lib/fit/internal/utility.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef LIB_FIT_INCLUDE_LIB_FIT_INTERNAL_UTILITY_H_
-#define LIB_FIT_INCLUDE_LIB_FIT_INTERNAL_UTILITY_H_
+#ifndef LIB_FIT_INTERNAL_UTILITY_H_
+#define LIB_FIT_INTERNAL_UTILITY_H_
#include <lib/stdcompat/type_traits.h>
@@ -135,4 +135,4 @@ struct is_nothrow_swappable<T,
} // namespace internal
} // namespace fit
-#endif // LIB_FIT_INCLUDE_LIB_FIT_INTERNAL_UTILITY_H_
+#endif // LIB_FIT_INTERNAL_UTILITY_H_
diff --git a/third_party/fuchsia/repo/sdk/lib/fit/include/lib/fit/nullable.h b/third_party/fuchsia/repo/sdk/lib/fit/include/lib/fit/nullable.h
index d6ba9b7ff..56892693b 100644
--- a/third_party/fuchsia/repo/sdk/lib/fit/include/lib/fit/nullable.h
+++ b/third_party/fuchsia/repo/sdk/lib/fit/include/lib/fit/nullable.h
@@ -41,8 +41,8 @@ constexpr inline bool is_null(T&&) {
// with nullptr.
template <typename T>
struct is_nullable
- : public std::integral_constant<bool, std::is_constructible<T, decltype(nullptr)>::value &&
- std::is_assignable<T&, decltype(nullptr)>::value &&
+ : public std::integral_constant<bool, std::is_constructible_v<T, decltype(nullptr)> &&
+ std::is_assignable_v<T&, decltype(nullptr)> &&
is_comparable_with_null<T>::value> {};
template <>
struct is_nullable<void> : public std::false_type {};
@@ -62,8 +62,8 @@ struct is_nullable<void> : public std::false_type {};
// TODO(fxbug.dev/4681): fit::nullable does not precisely mirror
// cpp17::optional. This should be corrected to avoid surprises when switching
// between the types.
-template <typename T, bool = (is_nullable<T>::value && std::is_constructible<T, T&&>::value &&
- std::is_assignable<T&, T&&>::value)>
+template <typename T, bool = (is_nullable<T>::value && std::is_constructible_v<T, T&&> &&
+ std::is_assignable_v<T&, T&&>)>
class nullable final {
public:
using value_type = T;
@@ -131,30 +131,26 @@ class nullable<T, true> final {
constexpr T& value() & {
if (has_value()) {
return value_;
- } else {
- PW_ASSERT(false);
}
+ PW_ASSERT(false);
}
constexpr const T& value() const& {
if (has_value()) {
return value_;
- } else {
- PW_ASSERT(false);
}
+ PW_ASSERT(false);
}
constexpr T&& value() && {
if (has_value()) {
return std::move(value_);
- } else {
- PW_ASSERT(false);
}
+ PW_ASSERT(false);
}
constexpr const T&& value() const&& {
if (has_value()) {
return std::move(value_);
- } else {
- PW_ASSERT(false);
}
+ PW_ASSERT(false);
}
template <typename U = T>
diff --git a/third_party/fuchsia/repo/sdk/lib/fit/include/lib/fit/result.h b/third_party/fuchsia/repo/sdk/lib/fit/include/lib/fit/result.h
index a7f77cac9..86bbb9041 100644
--- a/third_party/fuchsia/repo/sdk/lib/fit/include/lib/fit/result.h
+++ b/third_party/fuchsia/repo/sdk/lib/fit/include/lib/fit/result.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef LIB_FIT_INCLUDE_LIB_FIT_RESULT_H_
-#define LIB_FIT_INCLUDE_LIB_FIT_RESULT_H_
+#ifndef LIB_FIT_RESULT_H_
+#define LIB_FIT_RESULT_H_
#include <lib/fit/internal/compiler.h>
#include <lib/fit/internal/result.h>
@@ -192,7 +192,7 @@ class success<> {
#if __cplusplus >= 201703L
// Deduction guides to simplify zero and single argument success expressions in C++17.
-success()->success<>;
+success() -> success<>;
template <typename T>
success(T) -> success<T>;
@@ -226,9 +226,15 @@ constexpr success<> ok() { return success<>{}; }
template <typename E, typename... Ts>
class result;
+// This suppresses the '-Wctad-maybe-unsupported' compiler warning when CTAD is used.
+//
+// See https://github.com/llvm/llvm-project/blob/42874f6/libcxx/include/__config#L1259-L1261.
+template <class... Tag>
+result(typename Tag::__allow_ctad...) -> result<Tag...>;
+
// Specialization of result for one value type.
template <typename E, typename T>
-class LIB_FIT_NODISCARD result<E, T> {
+class [[nodiscard]] result<E, T> {
static_assert(!::fit::internal::is_success_v<E>,
"fit::success may not be used as the error type of fit::result!");
static_assert(!cpp17::is_same_v<failed, std::decay_t<T>>,
@@ -473,7 +479,7 @@ class LIB_FIT_NODISCARD result<E, T> {
// Specialization of the result type for zero values.
template <typename E>
-class LIB_FIT_NODISCARD result<E> {
+class [[nodiscard]] result<E> {
static_assert(!::fit::internal::is_success_v<E>,
"fit::success may not be used as the error type of fit::result!");
@@ -797,4 +803,4 @@ constexpr bool operator>=(const T& lhs, const result<F, U>& rhs) {
} // namespace fit
-#endif // LIB_FIT_INCLUDE_LIB_FIT_RESULT_H_
+#endif // LIB_FIT_RESULT_H_
diff --git a/third_party/fuchsia/repo/sdk/lib/fit/include/lib/fit/traits.h b/third_party/fuchsia/repo/sdk/lib/fit/include/lib/fit/traits.h
index 916a47507..f2c8c61f0 100644
--- a/third_party/fuchsia/repo/sdk/lib/fit/include/lib/fit/traits.h
+++ b/third_party/fuchsia/repo/sdk/lib/fit/include/lib/fit/traits.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef LIB_FIT_INCLUDE_LIB_FIT_TRAITS_H_
-#define LIB_FIT_INCLUDE_LIB_FIT_TRAITS_H_
+#ifndef LIB_FIT_TRAITS_H_
+#define LIB_FIT_TRAITS_H_
#include <lib/stdcompat/type_traits.h>
@@ -178,4 +178,4 @@ constexpr bool is_detected_convertible_v = is_detected_convertible<To, Op, Args.
} // namespace fit
-#endif // LIB_FIT_INCLUDE_LIB_FIT_TRAITS_H_
+#endif // LIB_FIT_TRAITS_H_