| // Copyright 2023 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_ASYNC_PATTERNS_CPP_INTERNAL_SENDABLE_H_ |
| #define LIB_ASYNC_PATTERNS_CPP_INTERNAL_SENDABLE_H_ |
| |
| #include <lib/stdcompat/type_traits.h> |
| |
| #include <tuple> |
| #include <type_traits> |
| |
| namespace async_patterns::internal { |
| |
| template <typename T> |
| struct Smuggled { |
| T value; |
| |
| // Pretend this is a |T| to support |std::is_invocable| tests. |
| // It is never called in practice. |
| // NOLINTNEXTLINE(google-explicit-constructor) |
| operator T() const { |
| __builtin_abort(); |
| return {}; |
| } |
| }; |
| |
| // |BindForSending| disallows sending pointers. In some cases we know the |
| // pointee will outlive the consumer. This function wraps a value (likely |
| // some pointer) to be sent and disables any restrictions in |BindForSending|. |
| template <typename T> |
| auto Smuggle(T&& value) { |
| return Smuggled<std::remove_reference_t<T>>{std::forward<T>(value)}; |
| } |
| |
| template <typename T> |
| auto UnSmuggle(T&& value) { |
| return std::forward<T>(value); |
| } |
| |
| template <typename T> |
| auto UnSmuggle(Smuggled<T>&& value) { |
| return std::forward<T>(value.value); |
| } |
| |
| } // namespace async_patterns::internal |
| |
| #endif // LIB_ASYNC_PATTERNS_CPP_INTERNAL_SENDABLE_H_ |