From 74e42d0f2f9c3ffa7d27c2dd28b4b7277a84fb39 Mon Sep 17 00:00:00 2001 From: Molnar Sandor Date: Sat, 14 May 2022 10:31:12 +0300 Subject: [PATCH] Backed out 5 changesets (bug 1743020) for causing linux build bustages in function2.hpp CLOSED TREE Backed out changeset cf237471cf75 (bug 1743020) Backed out changeset 78eb51447ce5 (bug 1743020) Backed out changeset c486f95d55ec (bug 1743020) Backed out changeset c0abfda55404 (bug 1743020) Backed out changeset 16be18ca73fb (bug 1743020) --- .../NoExplicitMoveConstructorChecker.cpp | 4 +- dom/cache/CacheWorkerRef.cpp | 30 +- dom/workers/WorkerRef.cpp | 8 +- dom/workers/WorkerRef.h | 10 +- ipc/glue/DataPipe.cpp | 21 +- js/src/make-source-package.py | 1 - mfbt/MoveOnlyFunction.h | 43 - mfbt/moz.build | 5 - python/mozbuild/mozbuild/vendor/moz_yaml.py | 1 - third_party/function2/.clang-format | 9 - third_party/function2/.editorconfig | 11 - third_party/function2/.travis.yml | 93 - third_party/function2/CMakeLists.txt | 130 -- third_party/function2/Findfunction2.cmake | 10 - third_party/function2/LICENSE.txt | 23 - third_party/function2/Readme.md | 260 --- third_party/function2/appveyor.yml | 44 - third_party/function2/conanfile.py | 33 - .../function2/include/function2/function2.hpp | 1792 ----------------- third_party/function2/moz.yaml | 38 - third_party/moz.build | 3 - toolkit/content/license.html | 35 - tools/rewriting/ThirdPartyPaths.txt | 1 - 23 files changed, 56 insertions(+), 2549 deletions(-) delete mode 100644 mfbt/MoveOnlyFunction.h delete mode 100644 third_party/function2/.clang-format delete mode 100644 third_party/function2/.editorconfig delete mode 100644 third_party/function2/.travis.yml delete mode 100644 third_party/function2/CMakeLists.txt delete mode 100644 third_party/function2/Findfunction2.cmake delete mode 100644 third_party/function2/LICENSE.txt delete mode 100644 third_party/function2/Readme.md delete mode 100644 third_party/function2/appveyor.yml delete mode 100644 third_party/function2/conanfile.py delete mode 100644 third_party/function2/include/function2/function2.hpp delete mode 100644 third_party/function2/moz.yaml diff --git a/build/clang-plugin/NoExplicitMoveConstructorChecker.cpp b/build/clang-plugin/NoExplicitMoveConstructorChecker.cpp index 69e324dee3a4..3e46c55a71b9 100644 --- a/build/clang-plugin/NoExplicitMoveConstructorChecker.cpp +++ b/build/clang-plugin/NoExplicitMoveConstructorChecker.cpp @@ -8,9 +8,7 @@ void NoExplicitMoveConstructorChecker::registerMatchers( MatchFinder *AstMatcher) { AstMatcher->addMatcher( - cxxConstructorDecl(isExplicitMoveConstructor(), isFirstParty()) - .bind("node"), - this); + cxxConstructorDecl(isExplicitMoveConstructor()).bind("node"), this); } void NoExplicitMoveConstructorChecker::check( diff --git a/dom/cache/CacheWorkerRef.cpp b/dom/cache/CacheWorkerRef.cpp index 992de976e191..6f864fa0ba2c 100644 --- a/dom/cache/CacheWorkerRef.cpp +++ b/dom/cache/CacheWorkerRef.cpp @@ -12,6 +12,33 @@ namespace mozilla::dom::cache { +namespace { +// XXX Move this to mfbt, or do we already have something like this? Or remove +// the need for that by changing StrongWorkerRef/IPCWorkerRef? + +template +class FakeCopyable { + public: + explicit FakeCopyable(T&& aTarget) : mTarget(std::forward(aTarget)) {} + + FakeCopyable(FakeCopyable&&) = default; + + FakeCopyable(const FakeCopyable& aOther) + : mTarget(std::move(const_cast(aOther).mTarget)) { + MOZ_CRASH("Do not copy."); + } + + template + auto operator()(Args&&... aArgs) { + return mTarget(std::forward(aArgs)...); + } + + private: + T mTarget; +}; + +} // namespace + // static SafeRefPtr CacheWorkerRef::Create(WorkerPrivate* aWorkerPrivate, Behavior aBehavior) { @@ -21,7 +48,8 @@ SafeRefPtr CacheWorkerRef::Create(WorkerPrivate* aWorkerPrivate, // of CacheWorkerRef, since we can now use SafeRefPtrFromThis in the ctor auto workerRef = MakeSafeRefPtr(aBehavior, ConstructorGuard{}); - auto notify = [workerRef = workerRef.clonePtr()] { workerRef->Notify(); }; + auto notify = + FakeCopyable([workerRef = workerRef.clonePtr()] { workerRef->Notify(); }); if (aBehavior == eStrongWorkerRef) { workerRef->mStrongWorkerRef = StrongWorkerRef::Create( aWorkerPrivate, "CacheWorkerRef-Strong", std::move(notify)); diff --git a/dom/workers/WorkerRef.cpp b/dom/workers/WorkerRef.cpp index 9fcf329495b7..677055d88c31 100644 --- a/dom/workers/WorkerRef.cpp +++ b/dom/workers/WorkerRef.cpp @@ -91,7 +91,7 @@ void WorkerRef::Notify() { return; } - MoveOnlyFunction callback = std::move(mCallback); + std::function callback = std::move(mCallback); MOZ_ASSERT(!mCallback); callback(); @@ -102,7 +102,7 @@ void WorkerRef::Notify() { /* static */ already_AddRefed WeakWorkerRef::Create( - WorkerPrivate* aWorkerPrivate, MoveOnlyFunction&& aCallback) { + WorkerPrivate* aWorkerPrivate, std::function&& aCallback) { MOZ_ASSERT(aWorkerPrivate); aWorkerPrivate->AssertIsOnWorkerThread(); @@ -148,7 +148,7 @@ WorkerPrivate* WeakWorkerRef::GetUnsafePrivate() const { /* static */ already_AddRefed StrongWorkerRef::Create( WorkerPrivate* const aWorkerPrivate, const char* const aName, - MoveOnlyFunction&& aCallback) { + std::function&& aCallback) { if (RefPtr ref = CreateImpl(aWorkerPrivate, aName, Canceling)) { ref->mCallback = std::move(aCallback); @@ -218,7 +218,7 @@ WorkerPrivate* ThreadSafeWorkerRef::Private() const { /* static */ already_AddRefed IPCWorkerRef::Create( WorkerPrivate* aWorkerPrivate, const char* aName, - MoveOnlyFunction&& aCallback) { + std::function&& aCallback) { MOZ_ASSERT(aWorkerPrivate); aWorkerPrivate->AssertIsOnWorkerThread(); diff --git a/dom/workers/WorkerRef.h b/dom/workers/WorkerRef.h index decee3994e95..dbbc87d8ab1c 100644 --- a/dom/workers/WorkerRef.h +++ b/dom/workers/WorkerRef.h @@ -7,8 +7,8 @@ #ifndef mozilla_dom_workers_WorkerRef_h #define mozilla_dom_workers_WorkerRef_h +#include #include "mozilla/dom/WorkerStatus.h" -#include "mozilla/MoveOnlyFunction.h" #include "mozilla/RefPtr.h" #include "nsISupports.h" @@ -123,7 +123,7 @@ class WorkerRef { WorkerPrivate* mWorkerPrivate; - MoveOnlyFunction mCallback; + std::function mCallback; const char* const mName; const bool mIsPreventingShutdown; @@ -135,7 +135,7 @@ class WeakWorkerRef final : public WorkerRef { public: static already_AddRefed Create( WorkerPrivate* aWorkerPrivate, - MoveOnlyFunction&& aCallback = nullptr); + std::function&& aCallback = nullptr); WorkerPrivate* GetPrivate() const; @@ -154,7 +154,7 @@ class StrongWorkerRef final : public WorkerRef { public: static already_AddRefed Create( WorkerPrivate* aWorkerPrivate, const char* aName, - MoveOnlyFunction&& aCallback = nullptr); + std::function&& aCallback = nullptr); // This function creates a StrongWorkerRef even when in the Canceling state of // the worker's lifecycle. It's intended to be used by system code, e.g. code @@ -205,7 +205,7 @@ class IPCWorkerRef final : public WorkerRef { public: static already_AddRefed Create( WorkerPrivate* aWorkerPrivate, const char* aName, - MoveOnlyFunction&& aCallback = nullptr); + std::function&& aCallback = nullptr); WorkerPrivate* Private() const; diff --git a/ipc/glue/DataPipe.cpp b/ipc/glue/DataPipe.cpp index 98ba56842dae..a87cee8a596f 100644 --- a/ipc/glue/DataPipe.cpp +++ b/ipc/glue/DataPipe.cpp @@ -10,7 +10,6 @@ #include "mozilla/CheckedInt.h" #include "mozilla/ErrorNames.h" #include "mozilla/Logging.h" -#include "mozilla/MoveOnlyFunction.h" #include "mozilla/ipc/InputStreamParams.h" #include "nsIAsyncInputStream.h" #include "nsStreamUtils.h" @@ -36,19 +35,33 @@ class SCOPED_CAPABILITY DataPipeAutoLock { template void AddUnlockAction(F aAction) { - mActions.AppendElement(std::move(aAction)); + mActions.AppendElement(MakeUnique>(std::move(aAction))); } ~DataPipeAutoLock() CAPABILITY_RELEASE() { mMutex.Unlock(); for (auto& action : mActions) { - action(); + action->Run(); } } private: + // NOTE: This would be better served by something like llvm's + // `UniqueFunction`, but this works as well. We can't use `std::function`, as + // the actions may not be copy constructable. + struct IAction { + virtual void Run() = 0; + virtual ~IAction() = default; + }; + template + struct Action : IAction { + explicit Action(F&& aAction) : mAction(std::move(aAction)) {} + void Run() override { mAction(); } + F mAction; + }; + Mutex& mMutex; - AutoTArray, 4> mActions; + AutoTArray, 4> mActions; }; static void DoNotifyOnUnlock(DataPipeAutoLock& aLock, diff --git a/js/src/make-source-package.py b/js/src/make-source-package.py index 4e5eeeeb2f1d..19402912d476 100755 --- a/js/src/make-source-package.py +++ b/js/src/make-source-package.py @@ -176,7 +176,6 @@ rsync_filter_list = """ + /.cargo/config.in -+ /third_party/function2/** - /third_party/python/gyp + /third_party/python/** + /third_party/rust/** diff --git a/mfbt/MoveOnlyFunction.h b/mfbt/MoveOnlyFunction.h deleted file mode 100644 index 5cb09c34c8e8..000000000000 --- a/mfbt/MoveOnlyFunction.h +++ /dev/null @@ -1,43 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef mozilla_MoveOnlyFunction_h -#define mozilla_MoveOnlyFunction_h - -#include "function2/function2.hpp" - -namespace mozilla { - -/// A type like `std::function`, but with support for move-only callable -/// objects. -/// -/// A similar type is proposed to be added to the standard library as -/// `std::move_only_function` in C++23. -/// -/// Unlike `std::function`, the function signature may be given const or -/// reference qualifiers which will be applied to `operator()`. This can be used -/// to declare const qualified or move-only functions. -/// -/// The implementation this definition depends on (function2) also has support -/// for callables with overload sets, however support for this was not exposed -/// to align better with the proposed `std::move_only_function`, which does not -/// support overload sets. -/// -/// A custom typedef over `fu2::function_base` is used to control the size and -/// alignment of the inline storage to store 2 aligned pointers, and ensure the -/// type is compatible with `nsTArray`. -template -using MoveOnlyFunction = fu2::function_base< - /* IsOwning */ true, - /* IsCopyable */ false, - /* Capacity */ fu2::capacity_fixed<2 * sizeof(void*), alignof(void*)>, - /* IsThrowing */ false, - /* HasStrongExceptionGuarantee */ false, - /* Signature */ Signature>; - -} // namespace mozilla - -#endif // mozilla_MoveOnlyFunction_h diff --git a/mfbt/moz.build b/mfbt/moz.build index a04cbc0c5fb6..cb8b5515999a 100644 --- a/mfbt/moz.build +++ b/mfbt/moz.build @@ -71,7 +71,6 @@ EXPORTS.mozilla = [ "MaybeStorageBase.h", "MemoryChecking.h", "MemoryReporting.h", - "MoveOnlyFunction.h", "NonDereferenceable.h", "NotNull.h", "Opaque.h", @@ -134,10 +133,6 @@ EXPORTS["double-conversion"] = [ "double-conversion/double-conversion/utils.h", ] -EXPORTS.function2 += [ - "/third_party/function2/include/function2/function2.hpp", -] - LOCAL_INCLUDES += [ "/mfbt/double-conversion", ] diff --git a/python/mozbuild/mozbuild/vendor/moz_yaml.py b/python/mozbuild/mozbuild/vendor/moz_yaml.py index c9f760d8cdbb..8e3176585c1e 100644 --- a/python/mozbuild/mozbuild/vendor/moz_yaml.py +++ b/python/mozbuild/mozbuild/vendor/moz_yaml.py @@ -37,7 +37,6 @@ VALID_LICENSES = [ "BSD-2-Clause", "BSD-3-Clause", "BSD-3-Clause-Clear", - "BSL-1.0", "CC0-1.0", "ISC", "ICU", diff --git a/third_party/function2/.clang-format b/third_party/function2/.clang-format deleted file mode 100644 index 822564901aa0..000000000000 --- a/third_party/function2/.clang-format +++ /dev/null @@ -1,9 +0,0 @@ -BasedOnStyle: LLVM - -PointerAlignment: Left -IndentCaseLabels: true -AllowShortFunctionsOnASingleLine: false -AllowShortCaseLabelsOnASingleLine: false -AlwaysBreakTemplateDeclarations: true -BinPackArguments: true -FixNamespaceComments: true diff --git a/third_party/function2/.editorconfig b/third_party/function2/.editorconfig deleted file mode 100644 index a148dfe07243..000000000000 --- a/third_party/function2/.editorconfig +++ /dev/null @@ -1,11 +0,0 @@ -[*] -charset = utf-8 -indent_size = 2 -tab_width = 2 -indent_style = space -insert_final_newline = true -trim_trailing_whitespace = true -max_line_length = 80 - -[*.{cpp,hpp}] -charset = latin1 diff --git a/third_party/function2/.travis.yml b/third_party/function2/.travis.yml deleted file mode 100644 index f3917101cb5d..000000000000 --- a/third_party/function2/.travis.yml +++ /dev/null @@ -1,93 +0,0 @@ -sudo: true -dist: trusty -language: cpp -cache: apt - -git: - depth: 1 - -matrix: - include: - - os: linux - compiler: gcc - addons: - apt: - sources: - - ubuntu-toolchain-r-test - packages: - - g++-5 - - valgrind - - ninja-build - env: - - COMPILER=g++-5 - - NO_EXCEPTIONS=OFF - - - os: linux - compiler: gcc - addons: - apt: - sources: - - ubuntu-toolchain-r-test - packages: - - g++-6 - - valgrind - - ninja-build - env: - - COMPILER=g++-6 - - NO_EXCEPTIONS=OFF - - - os: linux - compiler: gcc - addons: - apt: - sources: - - ubuntu-toolchain-r-test - packages: - - g++-6 - - valgrind - - ninja-build - env: - - COMPILER=g++-6 - - NO_EXCEPTIONS=ON - - - os: linux - compiler: clang - addons: - apt: - sources: - - ubuntu-toolchain-r-test - - llvm-toolchain-trusty-5.0 - packages: - - g++-6 - - clang-5.0 - - ninja-build - env: - - COMPILER=clang++-5.0 - - NO_EXCEPTIONS=OFF - - - os: linux - compiler: clang - addons: - apt: - sources: - - ubuntu-toolchain-r-test - - llvm-toolchain-trusty-5.0 - packages: - - g++-6 - - clang-5.0 - - ninja-build - env: - - COMPILER=clang++-5.0 - - NO_EXCEPTIONS=ON - - -install: - - export CXX=$COMPILER - - $CXX --version - - chmod +x tools/travis-ci.sh - -script: - - ./tools/travis-ci.sh - -notifications: - email: false diff --git a/third_party/function2/CMakeLists.txt b/third_party/function2/CMakeLists.txt deleted file mode 100644 index 51ed79691267..000000000000 --- a/third_party/function2/CMakeLists.txt +++ /dev/null @@ -1,130 +0,0 @@ -cmake_minimum_required(VERSION 3.11) -project(function2 VERSION 4.2.0 LANGUAGES CXX) - -if (NOT FU2_IS_FIND_INCLUDED) - string(COMPARE EQUAL ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_SOURCE_DIR} - FU2_IS_TOP_LEVEL_PROJECT) -endif() - -if (FU2_IS_TOP_LEVEL_PROJECT) - add_library(function2 INTERFACE) -else() - add_library(function2 INTERFACE IMPORTED GLOBAL) -endif() - -add_library(function2::function2 ALIAS function2) - -target_include_directories(function2 - INTERFACE - $ - $) - -target_compile_features(function2 - INTERFACE - cxx_alias_templates - cxx_auto_type - cxx_constexpr - cxx_decltype - cxx_decltype_auto - cxx_final - cxx_lambdas - cxx_lambda_init_captures - cxx_generic_lambdas - cxx_variadic_templates - cxx_defaulted_functions - cxx_nullptr - cxx_trailing_return_types - cxx_return_type_deduction) - -if (FU2_IS_TOP_LEVEL_PROJECT) - include(ExternalProject) - include(GNUInstallDirs) - include(CMakePackageConfigHelpers) - - # Create an install target: - # Headers and license files - install(DIRECTORY "${PROJECT_SOURCE_DIR}/include/function2" - DESTINATION "include") - install(FILES "LICENSE.txt" DESTINATION .) - install(FILES "Readme.md" DESTINATION .) - - # Config.cmake - write_basic_package_version_file( - "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake" - VERSION ${PROJECT_VERSION} - COMPATIBILITY SameMajorVersion) - install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake" - DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}") - - # ConfigVersion.cmake - configure_package_config_file("cmake/config.cmake.in" - "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake" - INSTALL_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}" - # PATH_VARS INCLUDE_INSTALL_DIR SYSCONFIG_INSTALL_DIR - ) - install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake" - DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}") - - # Targets.cmake - export(TARGETS ${PROJECT_NAME} - NAMESPACE ${PROJECT_NAME}:: - FILE "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Targets.cmake") - install(TARGETS ${PROJECT_NAME} - EXPORT "${PROJECT_NAME}Targets" - INCLUDES DESTINATION "include") - install(EXPORT "${PROJECT_NAME}Targets" - NAMESPACE ${PROJECT_NAME}:: - DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}") - - # Setup CPack for bundling - set(CPACK_GENERATOR "ZIP") - set(CPACK_PACKAGE_VERSION_MAJOR ${PROJECT_VERSION_MAJOR}) - set(CPACK_PACKAGE_VERSION_MINOR ${PROJECT_VERSION_MINOR}) - set(CPACK_PACKAGE_VERSION_PATCH ${PROJECT_VERSION_PATCH}) - - # Since the header only library is platform independent - # we name the packages after the native line feed - if(WIN32) - set(CPACK_SYSTEM_NAME "crlf") - else() - set(CPACK_SYSTEM_NAME "lf") - endif() - - include(CPack) - - if (MSVC) - set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) - string(REGEX REPLACE "/W[0-4]" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /permissive-") - endif() - - include(cmake/CMakeLists.txt) - - include(CTest) - - option(FU2_WITH_NO_EXCEPTIONS - "Test without exceptions" - OFF) - option(FU2_WITH_NO_DEATH_TESTS - "Test without death tests" - OFF) - option(FU2_WITH_CPP_LATEST - "Enable the highest C++ standard available for testing polyfills" - OFF) - - if (BUILD_TESTING) - if (FU2_WITH_NO_EXCEPTIONS) - message(STATUS "Testing with exceptions disabled") - add_definitions(-DTESTS_NO_EXCEPTIONS) - endif() - - if (FU2_WITH_NO_DEATH_TESTS) - message(STATUS "Testing without death tests") - add_definitions(-DTESTS_NO_DEATH_TESTS) - endif() - - add_subdirectory(test) - endif() -endif () diff --git a/third_party/function2/Findfunction2.cmake b/third_party/function2/Findfunction2.cmake deleted file mode 100644 index ca1fc3e41f41..000000000000 --- a/third_party/function2/Findfunction2.cmake +++ /dev/null @@ -1,10 +0,0 @@ -# Makes it possible to find function2 through find_package(function2 REQUIRED) -# when this source directory was added to the CMake module path. -# For instance it could be done through adding this to the CMakeLists.txt -# file in the parent directory: -# ```cmake -# list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/function2") -# ``` - -set(FU2_IS_FIND_INCLUDED ON) -include("${CMAKE_CURRENT_LIST_DIR}/CMakeLists.txt") diff --git a/third_party/function2/LICENSE.txt b/third_party/function2/LICENSE.txt deleted file mode 100644 index 36b7cd93cdfb..000000000000 --- a/third_party/function2/LICENSE.txt +++ /dev/null @@ -1,23 +0,0 @@ -Boost Software License - Version 1.0 - August 17th, 2003 - -Permission is hereby granted, free of charge, to any person or organization -obtaining a copy of the software and accompanying documentation covered by -this license (the "Software") to use, reproduce, display, distribute, -execute, and transmit the Software, and to prepare derivative works of the -Software, and to permit third-parties to whom the Software is furnished to -do so, all subject to the following: - -The copyright notices in the Software and this entire statement, including -the above license grant, this restriction and the following disclaimer, -must be included in all copies of the Software, in whole or in part, and -all derivative works of the Software, unless such copies or derivative -works are solely in the form of machine-executable object code generated by -a source language processor. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT -SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE -FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. diff --git a/third_party/function2/Readme.md b/third_party/function2/Readme.md deleted file mode 100644 index 7556e83e8ee5..000000000000 --- a/third_party/function2/Readme.md +++ /dev/null @@ -1,260 +0,0 @@ - -# fu2::function an improved drop-in replacement to std::function - -![](https://img.shields.io/badge/Version-4.0.0-0091EA.svg) ![](https://img.shields.io/badge/License-Boost-blue.svg) [![Build Status](https://travis-ci.org/Naios/function2.svg?branch=master)](https://travis-ci.org/Naios/function2) [![Build status](https://ci.appveyor.com/api/projects/status/1tl0vqpg8ndccats/branch/master?svg=true)](https://ci.appveyor.com/project/Naios/function2/branch/master) - -Provides improved implementations of `std::function`: - -- **copyable** `fu2::function` -- **move-only** `fu2::unique_function` (capable of holding move only types) -- **non-owning** `fu2::function_view` (capable of referencing callables in a non owning way) - -that provide many benefits and improvements over `std::function`: - -- [x] **const**, **volatile**, **reference** and **noexcept** correct (qualifiers are part of the `operator()` signature) -- [x] **convertible** to and from `std::function` as well as other callable types -- [x] **adaptable** through `fu2::function_base` (internal capacity, copyable and exception guarantees) -- [x] **overloadable** with an arbitrary count of signatures (`fu2::function`) -- [x] **full allocator support** in contrast to `std::function`, which doesn't provide support anymore -- [x] **covered** by many unit tests and continuous integration services (*GCC*, *Clang* and *MSVC*) -- [x] **header only**, just copy and include `function.hpp` in your project -- [x] **permissively licensed** under the **boost** license - - -## Table of Contents - -* **[Documentation](#documentation)** - * **[How to use](#how-to-use)** - * **[Constructing a function](#constructing-a-function)** - * **[Non copyable unique functions](#non-copyable-unique-functions)** - * **[Convertibility of functions](#convertibility-of-functions)** - * **[Adapt function2](#adapt-function2)** -* **[Performance and optimization](#performance-and-optimization)** - * **[Small functor optimization](#small-functor-optimization)** - * **[Compiler optimization](#compiler-optimization)** - * **[std::function vs fu2::function](#stdfunction-vs-fu2function)** -* **[Coverage and runtime checks](#coverage-and-runtime-checks)** -* **[Compatibility](#compatibility)** -* **[License](#licence)** -* **[Similar implementations](#similar-implementations)** - -## Documentation - -### How to use - -**function2** is implemented in one header (`function.hpp`), no compilation is required. -Just copy the `function.hpp` header in your project and include it to start. -It's recommended to import the library as git submodule using CMake: - -```sh -# Shell: -git submodule add https://github.com/Naios/function2.git -``` - -```cmake -# CMake file: -add_subdirectory(function2) -# function2 provides an interface target which makes it's -# headers available to all projects using function2 -target_link_libraries(my_project function2) -``` - -Use `fu2::function` as a wrapper for copyable function wrappers and `fu2::unique_function` for move only types. -The standard implementation `std::function` and `fu2::function` are convertible to each other, see [the chapter convertibility of functions](#convertibility-of-functions) for details. - -A function wrapper is declared as following: -```c++ -fu2::function -// Return type ~^ ^ ^ ^ -// Parameters ~~~~~|~~~~~| ^ -// Qualifier ~~~~~~~~~~~~~~~~~~~| -``` - -* **Return type**: The return type of the function to wrap. -* **Arguments**: The argument types of the function to wrap. - Any argument types are allowed. -* **Qualifiers**: There are several qualifiers allowed: - - **no qualifier** provides `ReturnType operator() (Args...)` - - Can be assigned from const and no const objects (*mutable lambdas* for example). - - **const** provides `ReturnType operator() (Args...) const` - - Requires that the assigned functor is const callable (won't work with *mutable lambdas*), - - **volatile** provides `ReturnType operator() (Args...) volatile` - - Can only be assigned from volatile qualified functors. - - **const volatile** provides `ReturnType operator() (Args...) const volatile` - - Same as const and volatile together. - - **r-value (one-shot) functions** `ReturnType operator() (Args...) &&` - - one-shot functions which are invalidated after the first call (can be mixed with `const`, `volatile` and `noexcept`). Can only wrap callable objects which call operator is also qualified as `&&` (r-value callable). Normal (*C*) functions are considered to be r-value callable by default. - - **noexcept functions** `ReturnType operator() (Args...) noexcept` - - such functions are guaranteed not to throw an exception (can be mixed with `const`, `volatile` and `&&`). Can only wrap functions or callable objects which call operator is also qualified as `noexcept`. Requires enabled C++17 compilation to work (support is detected automatically). Empty function calls to such a wrapped function will lead to a call to `std::abort` regardless the wrapper is configured to support exceptions or not (see [adapt function2](#adapt-function2)). -* **Multiple overloads**: The library is capable of providing multiple overloads: - ```cpp - fu2::function const&), - int(std::set const&) const> fn = [] (auto const& container) { - return container.size()); - }; - ``` - -### Constructing a function - -`fu2::function` and `fu2::unique_function` (non copyable) are easy to use: - -```c++ -fu2::function fun = [] { - // ... -}; - -// fun provides void operator()() const now -fun(); -``` - -### Non copyable unique functions - -`fu2::unique_function` also works with non copyable functors/ lambdas. - -```c++ -fu2::unique_function fun = [ptr = std::make_unique(true)] { - return *ptr; -}; - -// unique functions are move only -fu2::unique_function otherfun = std::move(fun): - -otherfun(); -``` - - -### Non owning functions - -A `fu2::function_view` can be used to create a non owning view on a persistent object. Note that the view is only valid as long as the object lives. - -```c++ -auto callable = [ptr = std::make_unique(true)] { - return *ptr; -}; - -fu2::function_view view(callable); -``` - -### Convertibility of functions - -`fu2::function`, `fu2::unique_function` and `std::function` are convertible to each other when: - -- The return type and parameter type match. -- The functions are both volatile or not. -- The functions are const correct: - - `noconst = const` - - `const = const` - - `noconst = noconst` -- The functions are copyable correct when: - - `unique = unique` - - `unique = copyable` - - `copyable = copyable` -- The functions are reference correct when: - - `lvalue = lvalue` - - `lvalue = rvalue` - - `rvalue = rvalue` -- The functions are `noexcept` correct when: - - `callable = callable` - - `callable = noexcept callable ` - - `noexcept callable = noexcept callable` - -| Convertibility from \ to | fu2::function | fu2::unique_function | std::function | -| ------------------------ | ------------- | -------------------- | ------------- | -| fu2::function | Yes | Yes | Yes | -| fu2::unique_function | No | Yes | No | -| std::function | Yes | Yes | Yes | - -```c++ -fu2::function fun = []{}; -// OK -std::function std_fun = fun; -// OK -fu2::unique_function un_fun = fun; - -// Error (non copyable -> copyable) -fun = un_fun; -// Error (non copyable -> copyable) -fun = un_fun; - -``` - -### Adapt function2 - -function2 is adaptable through `fu2::function_base` which allows you to set: - -- **IsOwning**: defines whether the function owns its contained object -- **Copyable:** defines if the function is copyable or not. -- **Capacity:** defines the internal capacity used for [sfo optimization](#small-functor-optimization): -```cpp -struct my_capacity { - static constexpr std::size_t capacity = sizeof(my_type); - static constexpr std::size_t alignment = alignof(my_type); -}; -``` -- **IsThrowing** defines if empty function calls throw an `fu2::bad_function_call` exception, otherwise `std::abort` is called. -- **HasStrongExceptGuarantee** defines whether the strong exception guarantees shall be met. -- **Signatures:** defines the signatures of the function. - -The following code defines an owning function with a variadic signature which is copyable and sfo optimization is disabled: - -```c++ -template -using my_function = fu2::function_base; -``` - -The following code defines a non copyable function which just takes 1 argument, and has a huge capacity for internal sfo optimization. Also it must be called as r-value. - -```c++ -template -using my_consumer = fu2::function_base, - true, false, void(Arg)&&>; - -// Example -my_consumer consumer = [](int, float) { } -std::move(consumer)(44, 1.7363f); -``` - -## Performance and optimization - -### Small functor optimization - -function2 uses small functor optimization like the most common `std::function` implementations which means it allocates a small internal capacity to evade heap allocation for small functors. - -Smart heap allocation moves the inplace allocated functor automatically to the heap to speed up moving between objects. - -It's possible to disable small functor optimization through setting the internal capacity to 0. - - -## Coverage and runtime checks - -Function2 is checked with unit tests and valgrind (for memory leaks), where the unit tests provide coverage for all possible template parameter assignments. - -## Compatibility - -Tested with: - -- Visual Studio 2017+ Update 3 -- Clang 3.8+ -- GCC 5.4+ - -Every compiler with modern C++14 support should work. -*function2* only depends on the standard library. - -## License -*function2* is licensed under the very permissive Boost 1.0 License. - -## Similar implementations - -There are similar implementations of a function wrapper: - -- [pmed/fixed_size_function](https://github.com/pmed/fixed_size_function) -- stdex::function - A multi-signature function implementation. -- multifunction - Example from [Boost.TypeErasure](http://www.boost.org/doc/html/boost_typeerasure/examples.html#boost_typeerasure.examples.multifunction), another multi-signature function. -- std::function - [Standard](http://en.cppreference.com/w/cpp/utility/functional/function). -- boost::function - The one from [Boost](http://www.boost.org/doc/libs/1_55_0/doc/html/function.html). -- func::function - From this [blog](http://probablydance.com/2013/01/13/a-faster-implementation-of-stdfunction/). -- generic::delegate - [Fast delegate in C++11](http://codereview.stackexchange.com/questions/14730/impossibly-fast-delegate-in-c11), also see [here](https://code.google.com/p/cpppractice/source/browse/trunk/). -- ssvu::FastFunc - Another Don Clugston's FastDelegate, as shown [here](https://groups.google.com/a/isocpp.org/forum/#!topic/std-discussion/QgvHF7YMi3o). -- [cxx_function::function](https://github.com/potswa/cxx_function) - By David Krauss - -Also check out the amazing [**CxxFunctionBenchmark**](https://github.com/jamboree/CxxFunctionBenchmark) which compares several implementations. diff --git a/third_party/function2/appveyor.yml b/third_party/function2/appveyor.yml deleted file mode 100644 index acd6dc21731f..000000000000 --- a/third_party/function2/appveyor.yml +++ /dev/null @@ -1,44 +0,0 @@ -image: - - Visual Studio 2017 - - Visual Studio 2019 - -environment: - matrix: - - FU2_WITH_NO_EXCEPTIONS: OFF - FU2_WITH_CPP_LATEST: OFF - - FU2_WITH_NO_EXCEPTIONS: ON - FU2_WITH_CPP_LATEST: OFF - - FU2_WITH_NO_EXCEPTIONS: OFF - FU2_WITH_CPP_LATEST: ON - - FU2_WITH_NO_EXCEPTIONS: ON - FU2_WITH_CPP_LATEST: ON - -platform: - - x64 - -clone_script: - - cmd: git clone -q --branch=%APPVEYOR_REPO_BRANCH% https://github.com/%APPVEYOR_REPO_NAME%.git %APPVEYOR_BUILD_FOLDER% - - cmd: cd %APPVEYOR_BUILD_FOLDER% - - cmd: git checkout -qf %APPVEYOR_REPO_COMMIT% - - cmd: git submodule update --init --recursive - -before_build: - - cmd: > - cmake -H. -Bbuild -A%PLATFORM% - -DFU2_WITH_NO_EXCEPTIONS=%FU2_WITH_NO_EXCEPTIONS% - -DFU2_WITH_CPP_LATEST=%FU2_WITH_CPP_LATEST% - -build_script: - - cmd: > - cmake --build build --config Debug --target ALL_BUILD - -- /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" - /verbosity:minimal /maxcpucount:2 /nologo - - cmd: > - cmake --build build --config Release --target ALL_BUILD - -- /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" - /verbosity:minimal /maxcpucount:2 /nologo - -test_script: - - cmd: cd build - - cmd: ctest -C Debug -V . - - cmd: ctest -C Release -V . diff --git a/third_party/function2/conanfile.py b/third_party/function2/conanfile.py deleted file mode 100644 index 06dfdfe166a9..000000000000 --- a/third_party/function2/conanfile.py +++ /dev/null @@ -1,33 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- - -from conans import ConanFile, tools - -def get_version(): - git = tools.Git() - try: - return git.run("describe --tags --abbrev=0") - except: - return None - -class Function2Conan(ConanFile): - name = "function2" - version = get_version() - license = "boost" - url = "https://github.com/Naios/function2" - author = "Denis Blank (denis.blank@outlook.com)" - description = "Improved and configurable drop-in replacement to std::function" - homepage = "http://naios.github.io/function2" - no_copy_source = True - scm = { - "type": "git", - "url": "auto", - "revision": "auto" - } - - def package(self): - self.copy("LICENSE.txt", "licenses") - self.copy("include/function2/function2.hpp") - - def package_id(self): - self.info.header_only() diff --git a/third_party/function2/include/function2/function2.hpp b/third_party/function2/include/function2/function2.hpp deleted file mode 100644 index a45cb580fe94..000000000000 --- a/third_party/function2/include/function2/function2.hpp +++ /dev/null @@ -1,1792 +0,0 @@ - -// Copyright 2015-2020 Denis Blank -// Distributed under the Boost Software License, Version 1.0 -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#ifndef FU2_INCLUDED_FUNCTION2_HPP_ -#define FU2_INCLUDED_FUNCTION2_HPP_ - -#include -#include -#include -#include -#include -#include -#include - -// Defines: -// - FU2_HAS_DISABLED_EXCEPTIONS -#if defined(FU2_WITH_DISABLED_EXCEPTIONS) || \ - defined(FU2_MACRO_DISABLE_EXCEPTIONS) -#define FU2_HAS_DISABLED_EXCEPTIONS -#else // FU2_WITH_DISABLED_EXCEPTIONS -#if defined(_MSC_VER) -#if !defined(_HAS_EXCEPTIONS) || (_HAS_EXCEPTIONS == 0) -#define FU2_HAS_DISABLED_EXCEPTIONS -#endif -#elif defined(__clang__) -#if !(__EXCEPTIONS && __has_feature(cxx_exceptions)) -#define FU2_HAS_DISABLED_EXCEPTIONS -#endif -#elif defined(__GNUC__) -#if !__EXCEPTIONS -#define FU2_HAS_DISABLED_EXCEPTIONS -#endif -#endif -#endif // FU2_WITH_DISABLED_EXCEPTIONS -// - FU2_HAS_NO_FUNCTIONAL_HEADER -#if !defined(FU2_WITH_NO_FUNCTIONAL_HEADER) && \ - !defined(FU2_NO_FUNCTIONAL_HEADER) && \ - !defined(FU2_HAS_DISABLED_EXCEPTIONS) -#include -#else -#define FU2_HAS_NO_FUNCTIONAL_HEADER -#endif -// - FU2_HAS_CXX17_NOEXCEPT_FUNCTION_TYPE -#if defined(FU2_WITH_CXX17_NOEXCEPT_FUNCTION_TYPE) -#define FU2_HAS_CXX17_NOEXCEPT_FUNCTION_TYPE -#else // FU2_WITH_CXX17_NOEXCEPT_FUNCTION_TYPE -#if defined(_MSC_VER) -#if defined(_HAS_CXX17) && _HAS_CXX17 -#define FU2_HAS_CXX17_NOEXCEPT_FUNCTION_TYPE -#endif -#elif defined(__cpp_noexcept_function_type) -#define FU2_HAS_CXX17_NOEXCEPT_FUNCTION_TYPE -#elif defined(__cplusplus) && (__cplusplus >= 201703L) -#define FU2_HAS_CXX17_NOEXCEPT_FUNCTION_TYPE -#endif -#endif // FU2_WITH_CXX17_NOEXCEPT_FUNCTION_TYPE - -// - FU2_HAS_NO_EMPTY_PROPAGATION -#if defined(FU2_WITH_NO_EMPTY_PROPAGATION) -#define FU2_HAS_NO_EMPTY_PROPAGATION -#endif // FU2_WITH_NO_EMPTY_PROPAGATION - -#if !defined(FU2_HAS_DISABLED_EXCEPTIONS) -#include -#endif - -#if defined(__cpp_constexpr) && (__cpp_constexpr >= 201304) -#define FU2_DETAIL_CXX14_CONSTEXPR constexpr -#elif defined(__clang__) && defined(__has_feature) -#if __has_feature(__cxx_generic_lambdas__) && \ - __has_feature(__cxx_relaxed_constexpr__) -#define FU2_DETAIL_CXX14_CONSTEXPR constexpr -#endif -#elif defined(_MSC_VER) && (_MSC_VER >= 1915) && (_MSVC_LANG >= 201402) -#define FU2_DETAIL_CXX14_CONSTEXPR constexpr -#endif -#ifndef FU2_DETAIL_CXX14_CONSTEXPR -#define FU2_DETAIL_CXX14_CONSTEXPR -#endif - -/// Hint for the compiler that this point should be unreachable -#if defined(_MSC_VER) -// NOLINTNEXTLINE(cppcoreguidelines-macro-usage) -#define FU2_DETAIL_UNREACHABLE_INTRINSIC() __assume(false) -#elif defined(__GNUC__) -// NOLINTNEXTLINE(cppcoreguidelines-macro-usage) -#define FU2_DETAIL_UNREACHABLE_INTRINSIC() __builtin_unreachable() -#elif defined(__has_builtin) -#if __has_builtin(__builtin_unreachable) -// NOLINTNEXTLINE(cppcoreguidelines-macro-usage) -#define FU2_DETAIL_UNREACHABLE_INTRINSIC() __builtin_unreachable() -#endif -#endif -#ifndef FU2_DETAIL_UNREACHABLE_INTRINSIC -// NOLINTNEXTLINE(cppcoreguidelines-macro-usage) -#define FU2_DETAIL_UNREACHABLE_INTRINSIC() abort() -#endif - -/// Causes the application to exit abnormally -#if defined(_MSC_VER) -// NOLINTNEXTLINE(cppcoreguidelines-macro-usage) -#define FU2_DETAIL_TRAP() __debugbreak() -#elif defined(__GNUC__) -// NOLINTNEXTLINE(cppcoreguidelines-macro-usage) -#define FU2_DETAIL_TRAP() __builtin_trap() -#elif defined(__has_builtin) -#if __has_builtin(__builtin_trap) -// NOLINTNEXTLINE(cppcoreguidelines-macro-usage) -#define FU2_DETAIL_TRAP() __builtin_trap() -#endif -#endif -#ifndef FU2_DETAIL_TRAP -// NOLINTNEXTLINE(cppcoreguidelines-macro-usage) -#define FU2_DETAIL_TRAP() *(volatile int*)0x11 = 0 -#endif - -#ifndef NDEBUG -// NOLINTNEXTLINE(cppcoreguidelines-macro-usage) -#define FU2_DETAIL_UNREACHABLE() ::fu2::detail::unreachable_debug() -#else -// NOLINTNEXTLINE(cppcoreguidelines-macro-usage) -#define FU2_DETAIL_UNREACHABLE() FU2_DETAIL_UNREACHABLE_INTRINSIC() -#endif - -namespace fu2 { -inline namespace abi_400 { -namespace detail { -template -class function; - -template -struct identity {}; - -// Equivalent to C++17's std::void_t which targets a bug in GCC, -// that prevents correct SFINAE behavior. -// See http://stackoverflow.com/questions/35753920 for details. -template -struct deduce_to_void : std::common_type {}; - -template -using void_t = typename deduce_to_void::type; - -template -using unrefcv_t = std::remove_cv_t>; - -// Copy enabler helper class -template -struct copyable {}; -template <> -struct copyable { - copyable() = default; - ~copyable() = default; - copyable(copyable const&) = delete; - copyable(copyable&&) = default; - copyable& operator=(copyable const&) = delete; - copyable& operator=(copyable&&) = default; -}; - -/// Configuration trait to configure the function_base class. -template -struct config { - // Is true if the function is owning. - static constexpr auto const is_owning = Owning; - - // Is true if the function is copyable. - static constexpr auto const is_copyable = Copyable; - - // The internal capacity of the function - // used in small functor optimization. - // The object shall expose the real capacity through Capacity::capacity - // and the intended alignment through Capacity::alignment. - using capacity = Capacity; -}; - -/// A config which isn't compatible to other configs -template -struct property { - // Is true when the function throws an exception on empty invocation. - static constexpr auto const is_throwing = Throws; - - // Is true when the function throws an exception on empty invocation. - static constexpr auto const is_strong_exception_guaranteed = - HasStrongExceptGuarantee; -}; - -#ifndef NDEBUG -[[noreturn]] inline void unreachable_debug() { - FU2_DETAIL_TRAP(); - std::abort(); -} -#endif - -/// Provides utilities for invocing callable objects -namespace invocation { -/// Invokes the given callable object with the given arguments -template -constexpr auto invoke(Callable&& callable, Args&&... args) noexcept( - noexcept(std::forward(callable)(std::forward(args)...))) - -> decltype(std::forward(callable)(std::forward(args)...)) { - - return std::forward(callable)(std::forward(args)...); -} -/// Invokes the given member function pointer by reference -template -constexpr auto invoke(Type T::*member, Self&& self, Args&&... args) noexcept( - noexcept((std::forward(self).*member)(std::forward(args)...))) - -> decltype((std::forward(self).* - member)(std::forward(args)...)) { - return (std::forward(self).*member)(std::forward(args)...); -} -/// Invokes the given member function pointer by pointer -template -constexpr auto invoke(Type T::*member, Self&& self, Args&&... args) noexcept( - noexcept((std::forward(self)->*member)(std::forward(args)...))) - -> decltype( - (std::forward(self)->*member)(std::forward(args)...)) { - return (std::forward(self)->*member)(std::forward(args)...); -} -/// Invokes the given pointer to a scalar member by reference -template -constexpr auto -invoke(Type T::*member, - Self&& self) noexcept(noexcept(std::forward(self).*member)) - -> decltype(std::forward(self).*member) { - return (std::forward(self).*member); -} -/// Invokes the given pointer to a scalar member by pointer -template -constexpr auto -invoke(Type T::*member, - Self&& self) noexcept(noexcept(std::forward(self)->*member)) - -> decltype(std::forward(self)->*member) { - return std::forward(self)->*member; -} - -/// Deduces to a true type if the callable object can be invoked with -/// the given arguments. -/// We don't use invoke here because MSVC can't evaluate the nested expression -/// SFINAE here. -template -struct can_invoke : std::false_type {}; -template -struct can_invoke, - decltype((void)std::declval()(std::declval()...))> - : std::true_type {}; -template -struct can_invoke, - decltype((void)((std::declval().*std::declval())( - std::declval()...)))> : std::true_type {}; -template -struct can_invoke, - decltype( - (void)((std::declval().*std::declval())( - std::declval()...)))> : std::true_type {}; -template -struct can_invoke, - decltype( - (void)((std::declval()->*std::declval())( - std::declval()...)))> : std::true_type {}; -template -struct can_invoke, - decltype((void)(std::declval().*std::declval()))> - : std::true_type {}; -template -struct can_invoke, - decltype( - (void)(std::declval().*std::declval()))> - : std::true_type {}; -template -struct can_invoke, - decltype( - (void)(std::declval()->*std::declval()))> - : std::true_type {}; - -template -struct is_noexcept_correct : std::true_type {}; -template -struct is_noexcept_correct> - : std::integral_constant(), std::declval()...))> { -}; -} // end namespace invocation - -namespace overloading { -template -struct overload_impl; -template -struct overload_impl : Current, - overload_impl { - explicit overload_impl(Current current, Next next, Rest... rest) - : Current(std::move(current)), overload_impl( - std::move(next), std::move(rest)...) { - } - - using Current::operator(); - using overload_impl::operator(); -}; -template -struct overload_impl : Current { - explicit overload_impl(Current current) : Current(std::move(current)) { - } - - using Current::operator(); -}; - -template -constexpr auto overload(T&&... callables) { - return overload_impl...>{std::forward(callables)...}; -} -} // namespace overloading - -/// Declares the namespace which provides the functionality to work with a -/// type-erased object. -namespace type_erasure { -/// Specialization to work with addresses of callable objects -template -struct address_taker { - template - static void* take(O&& obj) { - return std::addressof(obj); - } - static T& restore(void* ptr) { - return *static_cast(ptr); - } - static T const& restore(void const* ptr) { - return *static_cast(ptr); - } - static T volatile& restore(void volatile* ptr) { - return *static_cast(ptr); - } - static T const volatile& restore(void const volatile* ptr) { - return *static_cast(ptr); - } -}; -/// Specialization to work with addresses of raw function pointers -template -struct address_taker::value>> { - template - static void* take(O&& obj) { - return reinterpret_cast(obj); - } - template - static T restore(O ptr) { - return reinterpret_cast(const_cast(ptr)); - } -}; - -template -struct box_factory; -/// Store the allocator inside the box -template -struct box : private Allocator { - friend box_factory; - - T value_; - - explicit box(T value, Allocator allocator) - : Allocator(std::move(allocator)), value_(std::move(value)) { - } - - box(box&&) = default; - box(box const&) = default; - box& operator=(box&&) = default; - box& operator=(box const&) = default; - ~box() = default; -}; -template -struct box : private Allocator { - friend box_factory; - - T value_; - - explicit box(T value, Allocator allocator) - : Allocator(std::move(allocator)), value_(std::move(value)) { - } - - box(box&&) = default; - box(box const&) = delete; - box& operator=(box&&) = default; - box& operator=(box const&) = delete; - ~box() = default; -}; - -template -struct box_factory> { - using real_allocator = - typename std::allocator_traits>:: - template rebind_alloc>; - - /// Allocates space through the boxed allocator - static box* - box_allocate(box const* me) { - real_allocator allocator(*static_cast(me)); - - return static_cast*>( - std::allocator_traits::allocate(allocator, 1U)); - } - - /// Destroys the box through the given allocator - static void box_deallocate(box* me) { - real_allocator allocator(*static_cast(me)); - - me->~box(); - std::allocator_traits::deallocate(allocator, me, 1U); - } -}; - -/// Creates a box containing the given value and allocator -template -auto make_box(std::integral_constant, T&& value, - Allocator&& allocator) { - return box, std::decay_t>( - std::forward(value), std::forward(allocator)); -} - -template -struct is_box : std::false_type {}; -template -struct is_box> : std::true_type {}; - -/// Provides access to the pointer to a heal allocated erased object -/// as well to the inplace storage. -union data_accessor { - data_accessor() = default; - explicit constexpr data_accessor(std::nullptr_t) noexcept : ptr_(nullptr) { - } - explicit constexpr data_accessor(void* ptr) noexcept : ptr_(ptr) { - } - - /// The pointer we use if the object is on the heap - void* ptr_; - /// The first field of the inplace storage - std::size_t inplace_storage_; -}; - -/// See opcode::op_fetch_empty -static FU2_DETAIL_CXX14_CONSTEXPR void write_empty(data_accessor* accessor, - bool empty) noexcept { - accessor->inplace_storage_ = std::size_t(empty); -} - -template -using transfer_const_t = - std::conditional_t>::value, - std::add_const_t, To>; -template -using transfer_volatile_t = - std::conditional_t>::value, - std::add_volatile_t, To>; - -/// The retriever when the object is allocated inplace -template -FU2_DETAIL_CXX14_CONSTEXPR auto retrieve(std::true_type /*is_inplace*/, - Accessor from, - std::size_t from_capacity) { - using type = transfer_const_t>*; - - /// Process the command by using the data inside the internal capacity - auto storage = &(from->inplace_storage_); - auto inplace = const_cast(static_cast(storage)); - return type(std::align(alignof(T), sizeof(T), inplace, from_capacity)); -} - -/// The retriever which is used when the object is allocated -/// through the allocator -template -constexpr auto retrieve(std::false_type /*is_inplace*/, Accessor from, - std::size_t /*from_capacity*/) { - - return from->ptr_; -} - -namespace invocation_table { -#if !defined(FU2_HAS_DISABLED_EXCEPTIONS) -#if defined(FU2_HAS_NO_FUNCTIONAL_HEADER) -struct bad_function_call : std::exception { - bad_function_call() noexcept { - } - - char const* what() const noexcept override { - return "bad function call"; - } -}; -#else -using std::bad_function_call; -#endif -#endif - -#ifdef FU2_HAS_CXX17_NOEXCEPT_FUNCTION_TYPE -#define FU2_DETAIL_EXPAND_QUALIFIERS_NOEXCEPT(F) \ - F(, , noexcept, , &) \ - F(const, , noexcept, , &) \ - F(, volatile, noexcept, , &) \ - F(const, volatile, noexcept, , &) \ - F(, , noexcept, &, &) \ - F(const, , noexcept, &, &) \ - F(, volatile, noexcept, &, &) \ - F(const, volatile, noexcept, &, &) \ - F(, , noexcept, &&, &&) \ - F(const, , noexcept, &&, &&) \ - F(, volatile, noexcept, &&, &&) \ - F(const, volatile, noexcept, &&, &&) -#define FU2_DETAIL_EXPAND_CV_NOEXCEPT(F) \ - F(, , noexcept) \ - F(const, , noexcept) \ - F(, volatile, noexcept) \ - F(const, volatile, noexcept) -#else // FU2_HAS_CXX17_NOEXCEPT_FUNCTION_TYPE -#define FU2_DETAIL_EXPAND_QUALIFIERS_NOEXCEPT(F) -#define FU2_DETAIL_EXPAND_CV_NOEXCEPT(F) -#endif // FU2_HAS_CXX17_NOEXCEPT_FUNCTION_TYPE - -#define FU2_DETAIL_EXPAND_QUALIFIERS(F) \ - F(, , , , &) \ - F(const, , , , &) \ - F(, volatile, , , &) \ - F(const, volatile, , , &) \ - F(, , , &, &) \ - F(const, , , &, &) \ - F(, volatile, , &, &) \ - F(const, volatile, , &, &) \ - F(, , , &&, &&) \ - F(const, , , &&, &&) \ - F(, volatile, , &&, &&) \ - F(const, volatile, , &&, &&) \ - FU2_DETAIL_EXPAND_QUALIFIERS_NOEXCEPT(F) -#define FU2_DETAIL_EXPAND_CV(F) \ - F(, , ) \ - F(const, , ) \ - F(, volatile, ) \ - F(const, volatile, ) \ - FU2_DETAIL_EXPAND_CV_NOEXCEPT(F) - -/// If the function is qualified as noexcept, the call will never throw -template -[[noreturn]] void throw_or_abortnoexcept( - std::integral_constant /*is_throwing*/) noexcept { - std::abort(); -} -/// Calls std::abort on empty function calls -[[noreturn]] inline void -throw_or_abort(std::false_type /*is_throwing*/) noexcept { - std::abort(); -} -/// Throws bad_function_call on empty funciton calls -[[noreturn]] inline void throw_or_abort(std::true_type /*is_throwing*/) { -#ifdef FU2_HAS_DISABLED_EXCEPTIONS - throw_or_abort(std::false_type{}); -#else - throw bad_function_call{}; -#endif -} - -template -struct function_trait; - -using is_noexcept_ = std::false_type; -using is_noexcept_noexcept = std::true_type; - -#define FU2_DEFINE_FUNCTION_TRAIT(CONST, VOLATILE, NOEXCEPT, OVL_REF, REF) \ - template \ - struct function_trait { \ - using pointer_type = Ret (*)(data_accessor CONST VOLATILE*, \ - std::size_t capacity, Args...); \ - template \ - struct internal_invoker { \ - static Ret invoke(data_accessor CONST VOLATILE* data, \ - std::size_t capacity, Args... args) NOEXCEPT { \ - auto obj = retrieve(std::integral_constant{}, \ - data, capacity); \ - auto box = static_cast(obj); \ - return invocation::invoke( \ - static_castvalue_)> CONST VOLATILE \ - REF>(box->value_), \ - std::forward(args)...); \ - } \ - }; \ - \ - template \ - struct view_invoker { \ - static Ret invoke(data_accessor CONST VOLATILE* data, std::size_t, \ - Args... args) NOEXCEPT { \ - \ - auto ptr = static_cast(data->ptr_); \ - return invocation::invoke(address_taker::restore(ptr), \ - std::forward(args)...); \ - } \ - }; \ - \ - template \ - using callable = T CONST VOLATILE REF; \ - \ - using arguments = identity; \ - \ - using is_noexcept = is_noexcept_##NOEXCEPT; \ - \ - template \ - struct empty_invoker { \ - static Ret invoke(data_accessor CONST VOLATILE* /*data*/, \ - std::size_t /*capacity*/, Args... /*args*/) NOEXCEPT { \ - throw_or_abort##NOEXCEPT(std::integral_constant{}); \ - } \ - }; \ - }; - -FU2_DETAIL_EXPAND_QUALIFIERS(FU2_DEFINE_FUNCTION_TRAIT) -#undef FU2_DEFINE_FUNCTION_TRAIT - -/// Deduces to the function pointer to the given signature -template -using function_pointer_of = typename function_trait::pointer_type; - -template -struct invoke_table; - -/// We optimize the vtable_t in case there is a single function overload -template -struct invoke_table { - using type = function_pointer_of; - - /// Return the function pointer itself - template - static constexpr auto fetch(type pointer) noexcept { - static_assert(Index == 0U, "The index should be 0 here!"); - return pointer; - } - - /// Returns the thunk of an single overloaded callable - template - static constexpr type get_invocation_table_of() noexcept { - return &function_trait::template internal_invoker::invoke; - } - /// Returns the thunk of an single overloaded callable - template - static constexpr type get_invocation_view_table_of() noexcept { - return &function_trait::template view_invoker::invoke; - } - /// Returns the thunk of an empty single overloaded callable - template - static constexpr type get_empty_invocation_table() noexcept { - return &function_trait::template empty_invoker::invoke; - } -}; -/// We generate a table in case of multiple function overloads -template -struct invoke_table { - using type = - std::tuple, function_pointer_of, - function_pointer_of...> const*; - - /// Return the function pointer at the particular index - template - static constexpr auto fetch(type table) noexcept { - return std::get(*table); - } - - /// The invocation vtable for a present object - template - struct invocation_vtable : public std::tuple, - function_pointer_of, - function_pointer_of...> { - constexpr invocation_vtable() noexcept - : std::tuple, function_pointer_of, - function_pointer_of...>(std::make_tuple( - &function_trait::template internal_invoker< - T, IsInplace>::invoke, - &function_trait::template internal_invoker< - T, IsInplace>::invoke, - &function_trait::template internal_invoker< - T, IsInplace>::invoke...)) { - } - }; - - /// Returns the thunk of an multi overloaded callable - template - static type get_invocation_table_of() noexcept { - static invocation_vtable const table; - return &table; - } - - /// The invocation vtable for a present object - template - struct invocation_view_vtable - : public std::tuple, - function_pointer_of, - function_pointer_of...> { - constexpr invocation_view_vtable() noexcept - : std::tuple, function_pointer_of, - function_pointer_of...>(std::make_tuple( - &function_trait::template view_invoker::invoke, - &function_trait::template view_invoker::invoke, - &function_trait::template view_invoker::invoke...)) { - } - }; - - /// Returns the thunk of an multi overloaded callable - template - static type get_invocation_view_table_of() noexcept { - static invocation_view_vtable const table; - return &table; - } - - /// The invocation table for an empty wrapper - template - struct empty_vtable : public std::tuple, - function_pointer_of, - function_pointer_of...> { - constexpr empty_vtable() noexcept - : std::tuple, function_pointer_of, - function_pointer_of...>( - std::make_tuple(&function_trait::template empty_invoker< - IsThrowing>::invoke, - &function_trait::template empty_invoker< - IsThrowing>::invoke, - &function_trait::template empty_invoker< - IsThrowing>::invoke...)) { - } - }; - - /// Returns the thunk of an multi single overloaded callable - template - static type get_empty_invocation_table() noexcept { - static empty_vtable const table; - return &table; - } -}; - -template -class operator_impl; - -#define FU2_DEFINE_FUNCTION_TRAIT(CONST, VOLATILE, NOEXCEPT, OVL_REF, REF) \ - template \ - class operator_impl \ - : operator_impl { \ - \ - template \ - friend class operator_impl; \ - \ - protected: \ - operator_impl() = default; \ - ~operator_impl() = default; \ - operator_impl(operator_impl const&) = default; \ - operator_impl(operator_impl&&) = default; \ - operator_impl& operator=(operator_impl const&) = default; \ - operator_impl& operator=(operator_impl&&) = default; \ - \ - using operator_impl::operator(); \ - \ - Ret operator()(Args... args) CONST VOLATILE OVL_REF NOEXCEPT { \ - auto parent = static_cast(this); \ - using erasure_t = std::decay_terasure_)>; \ - \ - /* `std::decay_terasure_)>` is a workaround for a */ \ - /* compiler regression of MSVC 16.3.1, see #29 for details. */ \ - return std::decay_terasure_)>::template invoke( \ - static_cast(parent->erasure_), \ - std::forward(args)...); \ - } \ - }; \ - template \ - class operator_impl, \ - Ret(Args...) CONST VOLATILE OVL_REF NOEXCEPT> \ - : copyable { \ - \ - template \ - friend class operator_impl; \ - \ - protected: \ - operator_impl() = default; \ - ~operator_impl() = default; \ - operator_impl(operator_impl const&) = default; \ - operator_impl(operator_impl&&) = default; \ - operator_impl& operator=(operator_impl const&) = default; \ - operator_impl& operator=(operator_impl&&) = default; \ - \ - Ret operator()(Args... args) CONST VOLATILE OVL_REF NOEXCEPT { \ - auto parent = \ - static_cast CONST VOLATILE*>(this); \ - using erasure_t = std::decay_terasure_)>; \ - \ - /* `std::decay_terasure_)>` is a workaround for a */ \ - /* compiler regression of MSVC 16.3.1, see #29 for details. */ \ - return std::decay_terasure_)>::template invoke( \ - static_cast(parent->erasure_), \ - std::forward(args)...); \ - } \ - }; - -FU2_DETAIL_EXPAND_QUALIFIERS(FU2_DEFINE_FUNCTION_TRAIT) -#undef FU2_DEFINE_FUNCTION_TRAIT -} // namespace invocation_table - -namespace tables { -/// Identifies the action which is dispatched on the erased object -enum class opcode { - op_move, ///< Move the object and set the vtable - op_copy, ///< Copy the object and set the vtable - op_destroy, ///< Destroy the object and reset the vtable - op_weak_destroy, ///< Destroy the object without resetting the vtable - op_fetch_empty, ///< Stores true or false into the to storage - ///< to indicate emptiness -}; - -/// Abstraction for a vtable together with a command table -/// TODO Add optimization for a single formal argument -/// TODO Add optimization to merge both tables if the function is size -/// optimized -template -class vtable; -template -class vtable> { - using command_function_t = void (*)(vtable* /*this*/, opcode /*op*/, - data_accessor* /*from*/, - std::size_t /*from_capacity*/, - data_accessor* /*to*/, - std::size_t /*to_capacity*/); - - using invoke_table_t = invocation_table::invoke_table; - - command_function_t cmd_; - typename invoke_table_t::type vtable_; - - template - struct trait { - static_assert(is_box::value, - "The trait must be specialized with a box!"); - - /// The command table - template - static void process_cmd(vtable* to_table, opcode op, data_accessor* from, - std::size_t from_capacity, data_accessor* to, - std::size_t to_capacity) { - - switch (op) { - case opcode::op_move: { - /// Retrieve the pointer to the object - auto box = static_cast(retrieve( - std::integral_constant{}, from, from_capacity)); - assert(box && "The object must not be over aligned or null!"); - - if (!IsInplace) { - // Just swap both pointers if we allocated on the heap - to->ptr_ = from->ptr_; - -#ifndef NDEBUG - // We don't need to null the pointer since we know that - // we don't own the data anymore through the vtable - // which is set to empty. - from->ptr_ = nullptr; -#endif - - to_table->template set_allocated(); - - } - // The object is allocated inplace - else { - construct(std::true_type{}, std::move(*box), to_table, to, - to_capacity); - box->~T(); - } - return; - } - case opcode::op_copy: { - auto box = static_cast(retrieve( - std::integral_constant{}, from, from_capacity)); - assert(box && "The object must not be over aligned or null!"); - - assert(std::is_copy_constructible::value && - "The box is required to be copyable here!"); - - // Try to allocate the object inplace - construct(std::is_copy_constructible{}, *box, to_table, to, - to_capacity); - return; - } - case opcode::op_destroy: - case opcode::op_weak_destroy: { - - assert(!to && !to_capacity && "Arg overflow!"); - auto box = static_cast(retrieve( - std::integral_constant{}, from, from_capacity)); - - if (IsInplace) { - box->~T(); - } else { - box_factory::box_deallocate(box); - } - - if (op == opcode::op_destroy) { - to_table->set_empty(); - } - return; - } - case opcode::op_fetch_empty: { - write_empty(to, false); - return; - } - } - - FU2_DETAIL_UNREACHABLE(); - } - - template - static void - construct(std::true_type /*apply*/, Box&& box, vtable* to_table, - data_accessor* to, - std::size_t to_capacity) noexcept(HasStrongExceptGuarantee) { - // Try to allocate the object inplace - void* storage = retrieve(std::true_type{}, to, to_capacity); - if (storage) { - to_table->template set_inplace(); - } else { - // Allocate the object through the allocator - to->ptr_ = storage = - box_factory>::box_allocate(std::addressof(box)); - to_table->template set_allocated(); - } - new (storage) T(std::forward(box)); - } - - template - static void - construct(std::false_type /*apply*/, Box&& /*box*/, vtable* /*to_table*/, - data_accessor* /*to*/, - std::size_t /*to_capacity*/) noexcept(HasStrongExceptGuarantee) { - } - }; - - /// The command table - static void empty_cmd(vtable* to_table, opcode op, data_accessor* /*from*/, - std::size_t /*from_capacity*/, data_accessor* to, - std::size_t /*to_capacity*/) { - - switch (op) { - case opcode::op_move: - case opcode::op_copy: { - to_table->set_empty(); - break; - } - case opcode::op_destroy: - case opcode::op_weak_destroy: { - // Do nothing - break; - } - case opcode::op_fetch_empty: { - write_empty(to, true); - break; - } - default: { - FU2_DETAIL_UNREACHABLE(); - } - } - } - -public: - vtable() noexcept = default; - - /// Initialize an object at the given position - template - static void init(vtable& table, T&& object, data_accessor* to, - std::size_t to_capacity) { - - trait>::construct(std::true_type{}, std::forward(object), - &table, to, to_capacity); - } - - /// Moves the object at the given position - void move(vtable& to_table, data_accessor* from, std::size_t from_capacity, - data_accessor* to, - std::size_t to_capacity) noexcept(HasStrongExceptGuarantee) { - cmd_(&to_table, opcode::op_move, from, from_capacity, to, to_capacity); - set_empty(); - } - - /// Destroys the object at the given position - void copy(vtable& to_table, data_accessor const* from, - std::size_t from_capacity, data_accessor* to, - std::size_t to_capacity) const { - cmd_(&to_table, opcode::op_copy, const_cast(from), - from_capacity, to, to_capacity); - } - - /// Destroys the object at the given position - void destroy(data_accessor* from, - std::size_t from_capacity) noexcept(HasStrongExceptGuarantee) { - cmd_(this, opcode::op_destroy, from, from_capacity, nullptr, 0U); - } - - /// Destroys the object at the given position without invalidating the - /// vtable - void - weak_destroy(data_accessor* from, - std::size_t from_capacity) noexcept(HasStrongExceptGuarantee) { - cmd_(this, opcode::op_weak_destroy, from, from_capacity, nullptr, 0U); - } - - /// Returns true when the vtable doesn't hold any erased object - bool empty() const noexcept { - data_accessor data; - cmd_(nullptr, opcode::op_fetch_empty, nullptr, 0U, &data, 0U); - return bool(data.inplace_storage_); - } - - /// Invoke the function at the given index - template - constexpr decltype(auto) invoke(Args&&... args) const { - auto thunk = invoke_table_t::template fetch(vtable_); - return thunk(std::forward(args)...); - } - /// Invoke the function at the given index - template - constexpr decltype(auto) invoke(Args&&... args) const volatile { - auto thunk = invoke_table_t::template fetch(vtable_); - return thunk(std::forward(args)...); - } - - template - void set_inplace() noexcept { - using type = std::decay_t; - vtable_ = invoke_table_t::template get_invocation_table_of(); - cmd_ = &trait::template process_cmd; - } - - template - void set_allocated() noexcept { - using type = std::decay_t; - vtable_ = invoke_table_t::template get_invocation_table_of(); - cmd_ = &trait::template process_cmd; - } - - void set_empty() noexcept { - vtable_ = invoke_table_t::template get_empty_invocation_table(); - cmd_ = &empty_cmd; - } -}; -} // namespace tables - -/// A union which makes the pointer to the heap object share the -/// same space with the internal capacity. -/// The storage type is distinguished by multiple versions of the -/// control and vtable. -template -struct internal_capacity { - /// We extend the union through a technique similar to the tail object hack - typedef union { - /// Tag to access the structure in a type-safe way - data_accessor accessor_; - /// The internal capacity we use to allocate in-place - std::aligned_storage_t capacity_; - } type; -}; -template -struct internal_capacity< - Capacity, std::enable_if_t<(Capacity::capacity < sizeof(void*))>> { - typedef struct { - /// Tag to access the structure in a type-safe way - data_accessor accessor_; - } type; -}; - -template -class internal_capacity_holder { - // Tag to access the structure in a type-safe way - typename internal_capacity::type storage_; - -public: - constexpr internal_capacity_holder() = default; - - FU2_DETAIL_CXX14_CONSTEXPR data_accessor* opaque_ptr() noexcept { - return &storage_.accessor_; - } - constexpr data_accessor const* opaque_ptr() const noexcept { - return &storage_.accessor_; - } - FU2_DETAIL_CXX14_CONSTEXPR data_accessor volatile* - opaque_ptr() volatile noexcept { - return &storage_.accessor_; - } - constexpr data_accessor const volatile* opaque_ptr() const volatile noexcept { - return &storage_.accessor_; - } - - static constexpr std::size_t capacity() noexcept { - return sizeof(storage_); - } -}; - -/// An owning erasure -template -class erasure : internal_capacity_holder { - template - friend class erasure; - template - friend class operator_impl; - - using vtable_t = tables::vtable; - - vtable_t vtable_; - -public: - /// Returns the capacity of this erasure - static constexpr std::size_t capacity() noexcept { - return internal_capacity_holder::capacity(); - } - - FU2_DETAIL_CXX14_CONSTEXPR erasure() noexcept { - vtable_.set_empty(); - } - - FU2_DETAIL_CXX14_CONSTEXPR erasure(std::nullptr_t) noexcept { - vtable_.set_empty(); - } - - FU2_DETAIL_CXX14_CONSTEXPR - erasure(erasure&& right) noexcept(Property::is_strong_exception_guaranteed) { - right.vtable_.move(vtable_, right.opaque_ptr(), right.capacity(), - this->opaque_ptr(), capacity()); - } - - FU2_DETAIL_CXX14_CONSTEXPR erasure(erasure const& right) { - right.vtable_.copy(vtable_, right.opaque_ptr(), right.capacity(), - this->opaque_ptr(), capacity()); - } - - template - FU2_DETAIL_CXX14_CONSTEXPR - erasure(erasure right) noexcept( - Property::is_strong_exception_guaranteed) { - right.vtable_.move(vtable_, right.opaque_ptr(), right.capacity(), - this->opaque_ptr(), capacity()); - } - - template >> - FU2_DETAIL_CXX14_CONSTEXPR erasure(std::false_type /*use_bool_op*/, - T&& callable, - Allocator&& allocator = Allocator{}) { - vtable_t::init(vtable_, - type_erasure::make_box( - std::integral_constant{}, - std::forward(callable), - std::forward(allocator)), - this->opaque_ptr(), capacity()); - } - template >> - FU2_DETAIL_CXX14_CONSTEXPR erasure(std::true_type /*use_bool_op*/, - T&& callable, - Allocator&& allocator = Allocator{}) { - if (bool(callable)) { - vtable_t::init(vtable_, - type_erasure::make_box( - std::integral_constant{}, - std::forward(callable), - std::forward(allocator)), - this->opaque_ptr(), capacity()); - } else { - vtable_.set_empty(); - } - } - - ~erasure() { - vtable_.weak_destroy(this->opaque_ptr(), capacity()); - } - - FU2_DETAIL_CXX14_CONSTEXPR erasure& - operator=(std::nullptr_t) noexcept(Property::is_strong_exception_guaranteed) { - vtable_.destroy(this->opaque_ptr(), capacity()); - return *this; - } - - FU2_DETAIL_CXX14_CONSTEXPR erasure& operator=(erasure&& right) noexcept( - Property::is_strong_exception_guaranteed) { - vtable_.weak_destroy(this->opaque_ptr(), capacity()); - right.vtable_.move(vtable_, right.opaque_ptr(), right.capacity(), - this->opaque_ptr(), capacity()); - return *this; - } - - FU2_DETAIL_CXX14_CONSTEXPR erasure& operator=(erasure const& right) { - vtable_.weak_destroy(this->opaque_ptr(), capacity()); - right.vtable_.copy(vtable_, right.opaque_ptr(), right.capacity(), - this->opaque_ptr(), capacity()); - return *this; - } - - template - FU2_DETAIL_CXX14_CONSTEXPR erasure& - operator=(erasure right) noexcept( - Property::is_strong_exception_guaranteed) { - vtable_.weak_destroy(this->opaque_ptr(), capacity()); - right.vtable_.move(vtable_, right.opaque_ptr(), right.capacity(), - this->opaque_ptr(), capacity()); - return *this; - } - - template >> - void assign(std::false_type /*use_bool_op*/, T&& callable, - Allocator&& allocator = {}) { - vtable_.weak_destroy(this->opaque_ptr(), capacity()); - vtable_t::init(vtable_, - type_erasure::make_box( - std::integral_constant{}, - std::forward(callable), - std::forward(allocator)), - this->opaque_ptr(), capacity()); - } - - template >> - void assign(std::true_type /*use_bool_op*/, T&& callable, - Allocator&& allocator = {}) { - if (bool(callable)) { - assign(std::false_type{}, std::forward(callable), - std::forward(allocator)); - } else { - operator=(nullptr); - } - } - - /// Returns true when the erasure doesn't hold any erased object - constexpr bool empty() const noexcept { - return vtable_.empty(); - } - - /// Invoke the function of the erasure at the given index - /// - /// We define this out of class to be able to forward the qualified - /// erasure correctly. - template - static constexpr decltype(auto) invoke(Erasure&& erasure, Args&&... args) { - auto const capacity = erasure.capacity(); - return erasure.vtable_.template invoke( - std::forward(erasure).opaque_ptr(), capacity, - std::forward(args)...); - } -}; - -// A non owning erasure -template -class erasure> { - template - friend class erasure; - template - friend class operator_impl; - - using property_t = property; - - using invoke_table_t = invocation_table::invoke_table; - typename invoke_table_t::type invoke_table_; - - /// The internal pointer to the non owned object - data_accessor view_; - -public: - // NOLINTNEXTLINE(cppcoreguidlines-pro-type-member-init) - constexpr erasure() noexcept - : invoke_table_( - invoke_table_t::template get_empty_invocation_table()), - view_(nullptr) { - } - - // NOLINTNEXTLINE(cppcoreguidlines-pro-type-member-init) - constexpr erasure(std::nullptr_t) noexcept - : invoke_table_( - invoke_table_t::template get_empty_invocation_table()), - view_(nullptr) { - } - - // NOLINTNEXTLINE(cppcoreguidlines-pro-type-member-init) - constexpr erasure(erasure&& right) noexcept - : invoke_table_(right.invoke_table_), view_(right.view_) { - } - - constexpr erasure(erasure const& /*right*/) = default; - - template - // NOLINTNEXTLINE(cppcoreguidlines-pro-type-member-init) - constexpr erasure(erasure right) noexcept - : invoke_table_(right.invoke_table_), view_(right.view_) { - } - - template - // NOLINTNEXTLINE(cppcoreguidlines-pro-type-member-init) - constexpr erasure(std::false_type /*use_bool_op*/, T&& object) - : invoke_table_(invoke_table_t::template get_invocation_view_table_of< - std::decay_t>()), - view_(address_taker>::take(std::forward(object))) { - } - template - // NOLINTNEXTLINE(cppcoreguidlines-pro-type-member-init) - FU2_DETAIL_CXX14_CONSTEXPR erasure(std::true_type use_bool_op, T&& object) { - this->assign(use_bool_op, std::forward(object)); - } - - ~erasure() = default; - - constexpr erasure& - operator=(std::nullptr_t) noexcept(HasStrongExceptGuarantee) { - invoke_table_ = - invoke_table_t::template get_empty_invocation_table(); - view_.ptr_ = nullptr; - return *this; - } - - constexpr erasure& operator=(erasure&& right) noexcept { - invoke_table_ = right.invoke_table_; - view_ = right.view_; - right = nullptr; - return *this; - } - - constexpr erasure& operator=(erasure const& /*right*/) = default; - - template - constexpr erasure& - operator=(erasure right) noexcept { - invoke_table_ = right.invoke_table_; - view_ = right.view_; - return *this; - } - - template - constexpr void assign(std::false_type /*use_bool_op*/, T&& callable) { - invoke_table_ = invoke_table_t::template get_invocation_view_table_of< - std::decay_t>(); - view_.ptr_ = - address_taker>::take(std::forward(callable)); - } - template - constexpr void assign(std::true_type /*use_bool_op*/, T&& callable) { - if (bool(callable)) { - assign(std::false_type{}, std::forward(callable)); - } else { - operator=(nullptr); - } - } - - /// Returns true when the erasure doesn't hold any erased object - constexpr bool empty() const noexcept { - return view_.ptr_ == nullptr; - } - - template - static constexpr decltype(auto) invoke(Erasure&& erasure, T&&... args) { - auto thunk = invoke_table_t::template fetch(erasure.invoke_table_); - return thunk(&(erasure.view_), 0UL, std::forward(args)...); - } -}; -} // namespace type_erasure - -/// Deduces to a true_type if the type T provides the given signature and the -/// signature is noexcept correct callable. -template > -struct accepts_one - : std::integral_constant< - bool, invocation::can_invoke, - typename Trait::arguments>::value && - invocation::is_noexcept_correct< - Trait::is_noexcept::value, - typename Trait::template callable, - typename Trait::arguments>::value> {}; - -/// Deduces to a true_type if the type T provides all signatures -template -struct accepts_all : std::false_type {}; -template -struct accepts_all< - T, identity, - void_t::value>...>> - : std::true_type {}; - -/// Deduces to a true_type if the type T is implementing operator bool() -/// or if the type is convertible to bool directly, this also implements an -/// optimizations for function references `void(&)()` which are can never -/// be null and for such a conversion to bool would never return false. -#if defined(FU2_HAS_NO_EMPTY_PROPAGATION) -template -struct use_bool_op : std::false_type {}; -#else -template -struct has_bool_op : std::false_type {}; -template -struct has_bool_op()))>> - : std::true_type { -#ifndef NDEBUG - static_assert(!std::is_pointer::value, - "Missing deduction for function pointer!"); -#endif -}; - -template -struct use_bool_op : has_bool_op {}; - -#define FU2_DEFINE_USE_OP_TRAIT(CONST, VOLATILE, NOEXCEPT) \ - template \ - struct use_bool_op \ - : std::true_type {}; - -FU2_DETAIL_EXPAND_CV(FU2_DEFINE_USE_OP_TRAIT) -#undef FU2_DEFINE_USE_OP_TRAIT - -template -struct use_bool_op : std::false_type {}; - -#if defined(FU2_HAS_CXX17_NOEXCEPT_FUNCTION_TYPE) -template -struct use_bool_op : std::false_type {}; -#endif -#endif // FU2_HAS_NO_EMPTY_PROPAGATION - -template -struct assert_wrong_copy_assign { - static_assert(!Config::is_owning || !Config::is_copyable || - std::is_copy_constructible>::value, - "Can't wrap a non copyable object into a unique function!"); - - using type = void; -}; - -template -struct assert_no_strong_except_guarantee { - static_assert( - !IsStrongExceptGuaranteed || - (std::is_nothrow_move_constructible::value && - std::is_nothrow_destructible::value), - "Can't wrap a object an object that has no strong exception guarantees " - "if this is required by the wrapper!"); - - using type = void; -}; - -/// SFINAES out if the given callable is not copyable correct to the left one. -template -using enable_if_copyable_correct_t = - std::enable_if_t<(!LeftConfig::is_copyable || RightConfig::is_copyable)>; - -template -using is_owning_correct = - std::integral_constant; - -/// SFINAES out if the given function2 is not owning correct to this one -template -using enable_if_owning_correct_t = - std::enable_if_t::value>; - -template -class function> - : type_erasure::invocation_table::operator_impl< - 0U, - function>, - Args...> { - - template - friend class function; - - template - friend class type_erasure::invocation_table::operator_impl; - - using property_t = property; - using erasure_t = - type_erasure::erasure; - - template - using enable_if_can_accept_all_t = - std::enable_if_t, identity>::value>; - - template - struct is_convertible_to_this : std::false_type {}; - template - struct is_convertible_to_this< - function, - void_t, - enable_if_owning_correct_t>> - : std::true_type {}; - - template - using enable_if_not_convertible_to_this = - std::enable_if_t>::value>; - - template - using enable_if_owning_t = - std::enable_if_t::value && Config::is_owning>; - - template - using assert_wrong_copy_assign_t = - typename assert_wrong_copy_assign>::type; - - template - using assert_no_strong_except_guarantee_t = - typename assert_no_strong_except_guarantee>::type; - - erasure_t erasure_; - -public: - /// Default constructor which empty constructs the function - function() = default; - ~function() = default; - - explicit FU2_DETAIL_CXX14_CONSTEXPR - function(function const& /*right*/) = default; - explicit FU2_DETAIL_CXX14_CONSTEXPR function(function&& /*right*/) = default; - - /// Copy construction from another copyable function - template * = nullptr, - enable_if_copyable_correct_t* = nullptr, - enable_if_owning_correct_t* = nullptr> - FU2_DETAIL_CXX14_CONSTEXPR - function(function const& right) - : erasure_(right.erasure_) { - } - - /// Move construction from another function - template * = nullptr, - enable_if_owning_correct_t* = nullptr> - FU2_DETAIL_CXX14_CONSTEXPR function(function&& right) - : erasure_(std::move(right.erasure_)) { - } - - /// Construction from a callable object which overloads the `()` operator - template * = nullptr, - enable_if_can_accept_all_t* = nullptr, - assert_wrong_copy_assign_t* = nullptr, - assert_no_strong_except_guarantee_t* = nullptr> - FU2_DETAIL_CXX14_CONSTEXPR function(T&& callable) - : erasure_(use_bool_op>{}, std::forward(callable)) { - } - template * = nullptr, - enable_if_can_accept_all_t* = nullptr, - enable_if_owning_t* = nullptr, - assert_wrong_copy_assign_t* = nullptr, - assert_no_strong_except_guarantee_t* = nullptr> - FU2_DETAIL_CXX14_CONSTEXPR function(T&& callable, Allocator&& allocator) - : erasure_(use_bool_op>{}, std::forward(callable), - std::forward(allocator)) { - } - - /// Empty constructs the function - FU2_DETAIL_CXX14_CONSTEXPR function(std::nullptr_t np) : erasure_(np) { - } - - function& operator=(function const& /*right*/) = default; - function& operator=(function&& /*right*/) = default; - - /// Copy assigning from another copyable function - template * = nullptr, - enable_if_copyable_correct_t* = nullptr, - enable_if_owning_correct_t* = nullptr> - function& operator=(function const& right) { - erasure_ = right.erasure_; - return *this; - } - - /// Move assigning from another function - template * = nullptr, - enable_if_owning_correct_t* = nullptr> - function& operator=(function&& right) { - erasure_ = std::move(right.erasure_); - return *this; - } - - /// Move assigning from a callable object - template * = nullptr, - enable_if_can_accept_all_t* = nullptr, - assert_wrong_copy_assign_t* = nullptr, - assert_no_strong_except_guarantee_t* = nullptr> - function& operator=(T&& callable) { - erasure_.assign(use_bool_op>{}, std::forward(callable)); - return *this; - } - - /// Clears the function - function& operator=(std::nullptr_t np) { - erasure_ = np; - return *this; - } - - /// Returns true when the function is empty - bool empty() const noexcept { - return erasure_.empty(); - } - - /// Returns true when the function isn't empty - explicit operator bool() const noexcept { - return !empty(); - } - - /// Assigns a new target with an optional allocator - template >, - enable_if_not_convertible_to_this* = nullptr, - enable_if_can_accept_all_t* = nullptr, - assert_wrong_copy_assign_t* = nullptr, - assert_no_strong_except_guarantee_t* = nullptr> - void assign(T&& callable, Allocator&& allocator = Allocator{}) { - erasure_.assign(use_bool_op>{}, std::forward(callable), - std::forward(allocator)); - } - - /// Swaps this function with the given function - void swap(function& other) noexcept(HasStrongExceptGuarantee) { - if (&other == this) { - return; - } - - function cache = std::move(other); - other = std::move(*this); - *this = std::move(cache); - } - - /// Swaps the left function with the right one - friend void swap(function& left, - function& right) noexcept(HasStrongExceptGuarantee) { - left.swap(right); - } - - /// Calls the wrapped callable object - using type_erasure::invocation_table::operator_impl< - 0U, function, Args...>::operator(); -}; - -template -bool operator==(function const& f, std::nullptr_t) { - return !bool(f); -} - -template -bool operator!=(function const& f, std::nullptr_t) { - return bool(f); -} - -template -bool operator==(std::nullptr_t, function const& f) { - return !bool(f); -} - -template -bool operator!=(std::nullptr_t, function const& f) { - return bool(f); -} - -// Default intended object size of the function -using object_size = std::integral_constant; -} // namespace detail -} // namespace abi_400 - -/// Can be passed to function_base as template argument which causes -/// the internal small buffer to be sized according to the given size, -/// and aligned with the given alignment. -template -struct capacity_fixed { - static constexpr std::size_t capacity = Capacity; - static constexpr std::size_t alignment = Alignment; -}; - -/// Default capacity for small functor optimization -struct capacity_default - : capacity_fixed {}; - -/// Can be passed to function_base as template argument which causes -/// the internal small buffer to be removed from the callable wrapper. -/// The owning function_base will then allocate memory for every object -/// it applies a type erasure on. -struct capacity_none : capacity_fixed<0UL> {}; - -/// Can be passed to function_base as template argument which causes -/// the internal small buffer to be sized such that it can hold -/// the given object without allocating memory for an applied type erasure. -template -struct capacity_can_hold { - static constexpr std::size_t capacity = sizeof(T); - static constexpr std::size_t alignment = alignof(T); -}; - -/// An adaptable function wrapper base for arbitrary functional types. -/// -/// \tparam IsOwning Is true when the type erasure shall be owning the object. -/// -/// \tparam IsCopyable Defines whether the function is copyable or not -/// -/// \tparam Capacity Defines the internal capacity of the function -/// for small functor optimization. -/// The size of the whole function object will be the capacity -/// plus the size of two pointers. If the capacity is zero, -/// the size will increase through one additional pointer -/// so the whole object has the size of 3 * sizeof(void*). -/// The type which is passed to the Capacity template parameter -/// shall provide a capacity and alignment member which -/// looks like the following example: -/// ```cpp -/// struct my_capacity { -/// static constexpr std::size_t capacity = sizeof(my_type); -/// static constexpr std::size_t alignment = alignof(my_type); -/// }; -/// ``` -/// -/// \tparam IsThrowing Defines whether the function throws an exception on -/// empty function call, `std::abort` is called otherwise. -/// -/// \tparam HasStrongExceptGuarantee Defines whether all objects satisfy the -/// strong exception guarantees, -/// which means the function type will satisfy -/// the strong exception guarantees too. -/// -/// \tparam Signatures Defines the signature of the callable wrapper -/// -template -using function_base = detail::function< - detail::config, - detail::property>; - -/// An owning copyable function wrapper for arbitrary callable types. -template -using function = function_base; - -/// An owning non copyable function wrapper for arbitrary callable types. -template -using unique_function = function_base; - -/// A non owning copyable function wrapper for arbitrary callable types. -template -using function_view = function_base; - -#if !defined(FU2_HAS_DISABLED_EXCEPTIONS) -/// Exception type that is thrown when invoking empty function objects -/// and exception support isn't disabled. -/// -/// Exception support is enabled if -/// the template parameter 'Throwing' is set to true (default). -/// -/// This type will default to std::bad_function_call if the -/// functional header is used, otherwise the library provides its own type. -/// -/// You may disable the inclusion of the functional header -/// through defining `FU2_WITH_NO_FUNCTIONAL_HEADER`. -/// -using detail::type_erasure::invocation_table::bad_function_call; -#endif - -/// Returns a callable object, which unifies all callable objects -/// that were passed to this function. -/// -/// ```cpp -/// auto overloaded = fu2::overload([](std::true_type) { return true; }, -/// [](std::false_type) { return false; }); -/// ``` -/// -/// \param callables A pack of callable objects with arbitrary signatures. -/// -/// \returns A callable object which exposes the -/// -template -constexpr auto overload(T&&... callables) { - return detail::overloading::overload(std::forward(callables)...); -} -} // namespace fu2 - -#undef FU2_DETAIL_EXPAND_QUALIFIERS -#undef FU2_DETAIL_EXPAND_QUALIFIERS_NOEXCEPT -#undef FU2_DETAIL_EXPAND_CV -#undef FU2_DETAIL_EXPAND_CV_NOEXCEPT -#undef FU2_DETAIL_UNREACHABLE_INTRINSIC -#undef FU2_DETAIL_TRAP -#undef FU2_DETAIL_CXX14_CONSTEXPR - -#endif // FU2_INCLUDED_FUNCTION2_HPP_ diff --git a/third_party/function2/moz.yaml b/third_party/function2/moz.yaml deleted file mode 100644 index 6e142ed30a0f..000000000000 --- a/third_party/function2/moz.yaml +++ /dev/null @@ -1,38 +0,0 @@ -schema: 1 - -bugzilla: - product: Core - component: MFBT - -origin: - name: function2 - description: Improved and configurable drop-in replacement to std::function - - url: https://naios.github.io/function2/ - - release: 02ca99831de59c7c3a4b834789260253cace0ced (2021-06-16T17:21:46Z). - - revision: 02ca99831de59c7c3a4b834789260253cace0ced - - license: BSL-1.0 - license-file: LICENSE.txt - -updatebot: - maintainer-phab: nika - maintainer-bz: nika@thelayzells.com - tasks: - - type: vendoring - branch: master - enabled: True - frequency: every - -vendoring: - url: https://github.com/Naios/function2 - source-hosting: github - tracking: commit - - exclude: - - .github/ - - cmake/ - - test/ - - tools/ diff --git a/third_party/moz.build b/third_party/moz.build index cc5c07786531..8cf6f5d9f62f 100644 --- a/third_party/moz.build +++ b/third_party/moz.build @@ -13,9 +13,6 @@ with Files('cups/**'): with Files('dav1d/**'): BUG_COMPONENT = ('Core', 'Audio/Video: Playback') -with Files('function2/**'): - BUG_COMPONENT = ('Core', 'MFBT') - with Files('googletest/**'): BUG_COMPONENT = ('Testing', 'GTest') diff --git a/toolkit/content/license.html b/toolkit/content/license.html index c274dc7cef16..b213750f69d3 100644 --- a/toolkit/content/license.html +++ b/toolkit/content/license.html @@ -72,7 +72,6 @@
  • Babel License
  • Babylon License
  • bincode License
  • -
  • boost License
  • BSD 2-Clause License
  • BSD 3-Clause License
  • bspatch License
  • @@ -2149,40 +2148,6 @@ SOFTWARE. -
    - -

    boost License

    - -

    This license applies to files in the directory - third_party/function2.

    - -
    -Boost Software License - Version 1.0 - August 17th, 2003
    -
    -Permission is hereby granted, free of charge, to any person or organization
    -obtaining a copy of the software and accompanying documentation covered by
    -this license (the "Software") to use, reproduce, display, distribute,
    -execute, and transmit the Software, and to prepare derivative works of the
    -Software, and to permit third-parties to whom the Software is furnished to
    -do so, all subject to the following:
    -
    -The copyright notices in the Software and this entire statement, including
    -the above license grant, this restriction and the following disclaimer,
    -must be included in all copies of the Software, in whole or in part, and
    -all derivative works of the Software, unless such copies or derivative
    -works are solely in the form of machine-executable object code generated by
    -a source language processor.
    -
    -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    -FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
    -SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
    -FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
    -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
    -DEALINGS IN THE SOFTWARE.
    -
    - -

    BSD 2-Clause License

    diff --git a/tools/rewriting/ThirdPartyPaths.txt b/tools/rewriting/ThirdPartyPaths.txt index 6e80d3de1ac5..2cedc9f4f6bd 100644 --- a/tools/rewriting/ThirdPartyPaths.txt +++ b/tools/rewriting/ThirdPartyPaths.txt @@ -54,7 +54,6 @@ dom/webauthn/tests/pkijs/ editor/libeditor/tests/browserscope/lib/richtext/ editor/libeditor/tests/browserscope/lib/richtext2/ extensions/spellcheck/hunspell/src/ -function2/ gfx/angle/checkout/ gfx/cairo/ gfx/graphite2/