]> https://gitweb.dealii.org/ - dealii.git/commitdiff
Bundled: remove bundled taskflow 15511/head
authorMatthias Maier <tamiko@43-1.org>
Tue, 27 Jun 2023 21:20:26 +0000 (16:20 -0500)
committerMatthias Maier <tamiko@43-1.org>
Tue, 27 Jun 2023 21:21:35 +0000 (16:21 -0500)
31 files changed:
bundled/CMakeLists.txt
bundled/setup_bundled.cmake
bundled/taskflow-2.5.0/LICENSE [deleted file]
bundled/taskflow-2.5.0/README.md [deleted file]
bundled/taskflow-2.5.0/include/taskflow/core/error.hpp [deleted file]
bundled/taskflow-2.5.0/include/taskflow/core/executor.hpp [deleted file]
bundled/taskflow-2.5.0/include/taskflow/core/flow_builder.hpp [deleted file]
bundled/taskflow-2.5.0/include/taskflow/core/graph.hpp [deleted file]
bundled/taskflow-2.5.0/include/taskflow/core/notifier.hpp [deleted file]
bundled/taskflow-2.5.0/include/taskflow/core/observer.hpp [deleted file]
bundled/taskflow-2.5.0/include/taskflow/core/task.hpp [deleted file]
bundled/taskflow-2.5.0/include/taskflow/core/taskflow.hpp [deleted file]
bundled/taskflow-2.5.0/include/taskflow/core/topology.hpp [deleted file]
bundled/taskflow-2.5.0/include/taskflow/core/tsq.hpp [deleted file]
bundled/taskflow-2.5.0/include/taskflow/cuda/cuda_device.hpp [deleted file]
bundled/taskflow-2.5.0/include/taskflow/cuda/cuda_error.hpp [deleted file]
bundled/taskflow-2.5.0/include/taskflow/cuda/cuda_flow.hpp [deleted file]
bundled/taskflow-2.5.0/include/taskflow/cuda/cuda_graph.hpp [deleted file]
bundled/taskflow-2.5.0/include/taskflow/cuda/cuda_task.hpp [deleted file]
bundled/taskflow-2.5.0/include/taskflow/declarations.hpp [deleted file]
bundled/taskflow-2.5.0/include/taskflow/nstd/any.hpp [deleted file]
bundled/taskflow-2.5.0/include/taskflow/nstd/optional.hpp [deleted file]
bundled/taskflow-2.5.0/include/taskflow/nstd/variant.hpp [deleted file]
bundled/taskflow-2.5.0/include/taskflow/taskflow.hpp [deleted file]
bundled/taskflow-2.5.0/include/taskflow/utility/object_pool.hpp [deleted file]
bundled/taskflow-2.5.0/include/taskflow/utility/os.hpp [deleted file]
bundled/taskflow-2.5.0/include/taskflow/utility/passive_vector.hpp [deleted file]
bundled/taskflow-2.5.0/include/taskflow/utility/singleton.hpp [deleted file]
bundled/taskflow-2.5.0/include/taskflow/utility/stringify.hpp [deleted file]
bundled/taskflow-2.5.0/include/taskflow/utility/traits.hpp [deleted file]
bundled/taskflow-2.5.0/include/taskflow/utility/uuid.hpp [deleted file]

index 43194180f722ada08bfba6e6dfba0301548dfd36..18a3b19f1bcc9d592dc1719cee6d8a1db461a6a8 100644 (file)
@@ -54,14 +54,6 @@ if(DEAL_II_FEATURE_KOKKOS_BUNDLED_CONFIGURED)
 endif()
 
 
-if(DEAL_II_FEATURE_TASKFLOW_BUNDLED_CONFIGURED)
-  install(DIRECTORY ${TASKFLOW_FOLDER}/include/taskflow
-    DESTINATION ${DEAL_II_INCLUDE_RELDIR}/deal.II/bundled
-    COMPONENT library
-    )
-endif()
-
-
 if(DEAL_II_FEATURE_TBB_BUNDLED_CONFIGURED)
   add_subdirectory(${TBB_FOLDER}/src)
 
index 2b0fb9d5f0cd03a943ec2819c8d4d9dee4e60e51..d6594379c538bfec4fc294c10400bae9926d227e 100644 (file)
@@ -90,25 +90,6 @@ macro(feature_kokkos_configure_bundled)
 endmacro()
 
 
-#
-# Taskflow
-#
-
-set(FEATURE_TASKFLOW_HAVE_BUNDLED TRUE)
-
-option(DEAL_II_FORCE_BUNDLED_TASKFLOW
-  "Always use the bundled taskflow header library instead of an external one."
-  OFF)
-
-set(TASKFLOW_FOLDER "${CMAKE_SOURCE_DIR}/bundled/taskflow-2.5.0")
-
-macro(feature_taskflow_configure_bundled)
-  set(TASKFLOW_VERSION "2.5.0")
-
-  list(APPEND DEAL_II_BUNDLED_INCLUDE_DIRS ${TASKFLOW_FOLDER}/include)
-endmacro()
-
-
 #
 # Threading Building Blocks library
 #
diff --git a/bundled/taskflow-2.5.0/LICENSE b/bundled/taskflow-2.5.0/LICENSE
deleted file mode 100644 (file)
index 871f579..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-Taskflow LICENSE
-
-Copyright (c) 2018-2020 T.-W. Huang, C.-X. Lin, G. Guo, and M. Wong
-
-University of Utah, Salt Lake City, UT, USA
-University of Illinois at Urbana-Champaign, IL, USA
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-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 AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF 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/bundled/taskflow-2.5.0/README.md b/bundled/taskflow-2.5.0/README.md
deleted file mode 100644 (file)
index 780f4df..0000000
+++ /dev/null
@@ -1,747 +0,0 @@
-# Taskflow <img align="right" width="10%" src="image/taskflow_logo.png">
-
-[![Codacy Badge](https://api.codacy.com/project/badge/Grade/3bbdc89f9a7a41eaa17559fab8a64cde)](https://app.codacy.com/gh/taskflow/taskflow?utm_source=github.com&utm_medium=referral&utm_content=taskflow/taskflow&utm_campaign=Badge_Grade_Dashboard)
-[![Linux Build Status](https://travis-ci.com/taskflow/taskflow.svg?branch=master)](https://travis-ci.com/taskflow/taskflow)
-[![Windows Build status](https://ci.appveyor.com/api/projects/status/rbjl16i6c9ahxr16?svg=true)](https://ci.appveyor.com/project/tsung-wei-huang/taskflow)
-[![Wiki](image/api-doc.svg)][wiki]
-[![TFProf](image/tfprof.svg)](https://taskflow.github.io/tfprof/)
-[![Cite](image/cite-arXiv.svg)](https://arxiv.org/abs/2004.10908v2)
-
-Taskflow helps you quickly write parallel tasks programs in modern C++
-
-:exclamation: Starting from [v2.5.0](https://github.com/taskflow/taskflow/releases/tag/2.5.0), we have renamed cpp-taskflow to ***taskflow*** to broaden its support and future application scopes. The core codebase remains *unchanged*. You may only need to [change the remote URL](https://help.github.com/en/github/using-git/changing-a-remotes-url) to this new repository. Thank your for the support!
-
-# Why Taskflow?
-
-Taskflow is faster, more expressive, and easier for drop-in integration
-than many of existing task programming frameworks
-in handling complex parallel workloads.
-
-![](image/performance.png)
-
-Taskflow lets you quickly implement task decomposition strategies
-that incorporate both regular and irregular compute patterns,
-together with an efficient *work-stealing* scheduler to optimize your multithreaded performance.
-
-| [Static Tasking](#get-started-with-taskflow) | [Dynamic Tasking](#dynamic-tasking) |
-| :------------: | :-------------: |
-| ![](image/static_graph.svg) | <img align="right" src="image/dynamic_graph.svg" width="100%"> |
-
-Taskflow supports conditional tasking for you to make rapid control-flow decisions
-across dependent tasks to implement cycles and conditions that were otherwise difficult to do
-with existing tools.
-
-| [Conditional Tasking](#conditional-tasking) |
-| :-----------------: |
-| ![](image/condition.svg) |
-
-Taskflow is composable. You can create large parallel graphs through
-composition of modular and reusable blocks that are easier to optimize
-at an individual scope.
-
-| [Taskflow Composition](#composable-tasking) |
-| :---------------: |
-|![](image/framework.svg)|
-
-Taskflow supports heterogeneous tasking for you to 
-accelerate a wide range of scientific computing applications
-by harnessing the power of CPU-GPU collaborative computing.
-
-| [Concurrent CPU-GPU Tasking](#concurrent-cpu-gpu-tasking) |
-| :-----------------: |
-| ![](image/cudaflow.svg) |
-
-
-Taskflow provides visualization and tooling needed for profiling Taskflow programs.
-
-| [Taskflow Profiler](https://taskflow.github.io/tfprof) |
-| :-----------------: |
-| ![](image/tfprof.png) |
-
-We are committed to support trustworthy developments for both academic and industrial research projects 
-in parallel computing. Check out [Who is Using Taskflow](#who-is-using-taskflow) and what our users say:
-
-+ *"Taskflow is the cleanest Task API I've ever seen." [Damien Hocking @Corelium Inc](http://coreliuminc.com)*
-+ *"Taskflow has a very simple and elegant tasking interface. The performance also scales very well." [Glen Fraser][totalgee]*
-+ *"Taskflow lets me handle parallel processing in a smart way." [Hayabusa @Learning](https://cpp-learning.com/cpp-taskflow/)*
-+ *"Taskflow improves the throughput of our graph engine in just a few hours of coding." [Jean-Michaël @KDAB](https://ossia.io/)*
-+ *"Best poster award for open-source parallel programming library." [Cpp Conference 2018][Cpp Conference 2018]*
-+ *"Second Prize of Open-source Software Competition." [ACM Multimedia Conference 2019](https://tsung-wei-huang.github.io/img/mm19-ossc-award.jpg)*
-
-See a quick [presentation][Presentation] and 
-visit the [documentation][wiki] to learn more about Taskflow.
-Technical details can be referred to our [arXiv paper](https://arxiv.org/abs/2004.10908v2).
-
-# Table of Contents
-
-* [Get Started with Taskflow](#get-started-with-taskflow)
-* [Create a Taskflow Application](#create-a-taskflow-application)
-   * [Step 1: Create a Taskflow](#step-1-create-a-taskflow)
-   * [Step 2: Define Task Dependencies](#step-2-define-task-dependencies)
-   * [Step 3: Execute a Taskflow](#step-3-execute-a-taskflow)
-* [Dynamic Tasking](#dynamic-tasking)
-* [Conditional Tasking](#conditional-tasking)
-* [Composable Tasking](#composable-tasking)
-* [Concurrent CPU-GPU Tasking](#concurrent-cpu-gpu-tasking)
-   * [Step 1: Create a cudaFlow](#step-1-create-a-cudaflow)
-   * [Step 2: Compile and Execute a cudaFlow](#step-2-compile-and-execute-a-cudaflow)
-* [Visualize a Taskflow Graph](#visualize-a-taskflow-graph)
-* [API Reference](#api-reference)
-* [System Requirements](#system-requirements)
-* [Compile Unit Tests, Examples, and Benchmarks](#compile-unit-tests-examples-and-benchmarks)
-* [Who is Using Taskflow?](#who-is-using-taskflow)
-
-
-# Get Started with Taskflow
-
-The following example [simple.cpp](./examples/simple.cpp) shows the basic Taskflow API
-you need in most applications.
-
-```cpp
-#include <taskflow/taskflow.hpp>  // Taskflow is header-only
-
-int main(){
-  
-  tf::Executor executor;
-  tf::Taskflow taskflow;
-
-  auto [A, B, C, D] = taskflow.emplace(
-    [] () { std::cout << "TaskA\n"; },               //  task dependency graph
-    [] () { std::cout << "TaskB\n"; },               // 
-    [] () { std::cout << "TaskC\n"; },               //          +---+          
-    [] () { std::cout << "TaskD\n"; }                //    +---->| B |-----+   
-  );                                                 //    |     +---+     |
-                                                     //  +---+           +-v-+ 
-  A.precede(B);  // A runs before B                  //  | A |           | D | 
-  A.precede(C);  // A runs before C                  //  +---+           +-^-+ 
-  B.precede(D);  // B runs before D                  //    |     +---+     |    
-  C.precede(D);  // C runs before D                  //    +---->| C |-----+    
-                                                     //          +---+          
-  executor.run(taskflow).wait();
-
-  return 0;
-}
-```
-
-Compile and run the code with the following commands:
-
-```bash
-~$ g++ simple.cpp -I path/to/include/taskflow/ -std=c++17 -O2 -lpthread -o simple
-~$ ./simple
-TaskA
-TaskC  <-- concurrent with TaskB
-TaskB  <-- concurrent with TaskC
-TaskD
-```
-
-# Create a Taskflow Application
-
-Taskflow defines a very expressive API to create task dependency graphs.
-Most applications are developed through the following three steps:
-
-## Step 1: Create a Taskflow
-
-Create a taskflow object to build a task dependency graph:
-
-```cpp
-tf::Taskflow taskflow;
-```
-
-A task is a callable object for which [std::invoke][std::invoke] is applicable.
-Use the method `emplace` to create a task:
-
-```cpp
-tf::Task A = taskflow.emplace([](){ std::cout << "Task A\n"; });
-```
-
-## Step 2: Define Task Dependencies
-
-You can add dependency links between tasks to enforce one task to run before or 
-after another.
-
-```cpp
-A.precede(B);  // A runs before B.
-```
-
-## Step 3: Execute a Taskflow
-
-To execute a taskflow, you need to create an *executor*.
-An executor manages a set of worker threads to execute a taskflow
-through an efficient *work-stealing* algorithm.
-
-```cpp
-tf::Executor executor;
-```
-
-The executor provides a rich set of methods to run a taskflow. 
-You can run a taskflow multiple times, or until a stopping criteria is met.
-These methods are non-blocking with a [std::future][std::future] return
-to let you query the execution status.
-Executor is *thread-safe*.
-
-```cpp 
-executor.run(taskflow);       // runs the taskflow once
-executor.run_n(taskflow, 4);  // runs the taskflow four times
-
-// keeps running the taskflow until the predicate becomes true
-executor.run_until(taskflow, [counter=4](){ return --counter == 0; } );
-```
-
-
-You can call `wait_for_all` to block the executor until all associated taskflows complete.
-
-```cpp
-executor.wait_for_all();  // block until all associated tasks finish
-```
-
-Notice that the executor does not own any taskflow. 
-It is your responsibility to keep a taskflow alive during its execution,
-or it can result in undefined behavior.
-In most applications, you need only one executor to run multiple taskflows
-each representing a specific part of your parallel decomposition.
-
-<div align="right"><b><a href="#table-of-contents">[↑]</a></b></div>
-
-# Dynamic Tasking 
-
-Another powerful feature of Taskflow is *dynamic* tasking.
-Dynamic tasks are those tasks created during the execution of a taskflow.
-These tasks are spawned by a parent task and are grouped together to a *subflow* graph.
-To create a subflow for dynamic tasking, 
-emplace a callable with one argument of type `tf::Subflow`.
-
-<img align="right" src="image/subflow_join.svg" width="30%">
-
-```cpp
-// create three regular tasks
-tf::Task A = tf.emplace([](){}).name("A");
-tf::Task C = tf.emplace([](){}).name("C");
-tf::Task D = tf.emplace([](){}).name("D");
-
-// create a subflow graph (dynamic tasking)
-tf::Task B = tf.emplace([] (tf::Subflow& subflow) {
-  tf::Task B1 = subflow.emplace([](){}).name("B1");
-  tf::Task B2 = subflow.emplace([](){}).name("B2");
-  tf::Task B3 = subflow.emplace([](){}).name("B3");
-  B1.precede(B3);
-  B2.precede(B3);
-}).name("B");
-            
-A.precede(B);  // B runs after A 
-A.precede(C);  // C runs after A 
-B.precede(D);  // D runs after B 
-C.precede(D);  // D runs after C 
-```
-
-By default, a subflow graph joins its parent node. 
-This ensures a subflow graph finishes before the successors of 
-its parent task.
-You can disable this feature by calling `subflow.detach()`.
-For example, detaching the above subflow will result in the following execution flow:
-
-<img align="right" src="image/subflow_detach.svg" width="35%">
-
-```cpp
-// create a "detached" subflow graph (dynamic tasking)
-tf::Task B = tf.emplace([] (tf::Subflow& subflow) {
-  tf::Task B1 = subflow.emplace([](){}).name("B1");
-  tf::Task B2 = subflow.emplace([](){}).name("B2");
-  tf::Task B3 = subflow.emplace([](){}).name("B3");
-
-  B1.precede(B3);
-  B2.precede(B3);
-
-  // detach the subflow to form a parallel execution line
-  subflow.detach();
-}).name("B");
-```
-
-A subflow can be nested or recursive. You can create another subflow from
-the execution of a subflow and so on.
-
-<div align="right"><b><a href="#table-of-contents">[↑]</a></b></div>
-
-# Conditional Tasking
-
-Taskflow supports *conditional tasking* for users to implement *general* control flow with cycles and conditionals.
-A *condition task* evalutes a set of instructions and returns an integer index
-of the next immediate successor to execute.
-The index is defined with respect to the order of its successor construction.
-
-<img align="right" src="image/condition-2.svg" width="20%">
-
-```cpp
-tf::Task init = tf.emplace([](){ }).name("init");
-tf::Task stop = tf.emplace([](){ }).name("stop");
-
-// creates a condition task that returns 0 or 1
-tf::Task cond = tf.emplace([](){
-  std::cout << "flipping a coin\n";
-  return rand() % 2;
-}).name("cond");
-
-// creates a feedback loop
-init.precede(cond);
-cond.precede(cond, stop);  // cond--0-->cond, cond--1-->stop
-
-executor.run(tf).wait();
-```
-
-<div align="right"><b><a href="#table-of-contents">[↑]</a></b></div>
-
-
-
-# Composable Tasking
-
-A powerful feature of `tf::Taskflow` is composability. 
-You can create multiple task graphs from different parts of your workload
-and use them to compose a large graph through the `composed_of` method. 
-
-
-<img align="right" src="image/composition.svg" width="50%">
-
-```cpp 
-tf::Taskflow f1, f2;
-
-auto [f1A, f1B] = f1.emplace( 
-  []() { std::cout << "Task f1A\n"; },
-  []() { std::cout << "Task f1B\n"; }
-);
-auto [f2A, f2B, f2C] = f2.emplace( 
-  []() { std::cout << "Task f2A\n"; },
-  []() { std::cout << "Task f2B\n"; },
-  []() { std::cout << "Task f2C\n"; }
-);
-auto f1_module_task = f2.composed_of(f1);
-
-f1_module_task.succeed(f2A, f2B)
-              .precede(f2C);
-```
-
-Similarly, `composed_of` returns a task handle and you can use 
-`precede` to create dependencies. 
-You can compose a taskflow from multiple taskflows and use the result
-to compose a larger taskflow and so on.
-
-<div align="right"><b><a href="#table-of-contents">[↑]</a></b></div>
-
-# Concurrent CPU-GPU Tasking
-
-Taskflow enables concurrent CPU-GPU tasking by leveraging
-[Nvidia CUDA Toolkit][cuda-toolkit].
-You can harness the power of CPU-GPU collaborative computing 
-to implement heterogeneous decomposition algorithms.
-
-## Step 1: Create a cudaFlow
-
-A `tf::cudaFlow` is a graph object created at runtime 
-similar to dynamic tasking.
-It manages a task node in a taskflow and associates it
-with a [CUDA Graph][cudaGraph].
-To create a cudaFlow, emplace a callable with an argument 
-of type `tf::cudaFlow`.
-
-
-
-```cpp
-tf::Taskflow taskflow;
-tf::Executor executor;
-
-const unsigned N = 1<<20;                            // size of the vector
-std::vector<float> hx(N, 1.0f), hy(N, 2.0f);         // x and y vectors at host
-float *dx{nullptr}, *dy{nullptr};                    // x and y vectors at device
-
-tf::Task allocate_x = taskflow.emplace([&](){ cudaMalloc(&dx, N*sizeof(float));});
-tf::Task allocate_y = taskflow.emplace([&](){ cudaMalloc(&dy, N*sizeof(float));});
-tf::Task cudaflow = taskflow.emplace([&](tf::cudaFlow& cf) {
-  tf::cudaTask h2d_x = cf.copy(dx, hx.data(), N);    // host-to-device x data transfer
-  tf::cudaTask h2d_y = cf.copy(dy, hy.data(), N);    // host-to-device y data transfer
-  tf::cudaTask d2h_x = cf.copy(hx.data(), dx, N);    // device-to-host x data transfer
-  tf::cudaTask d2h_y = cf.copy(hy.data(), dy, N);    // device-to-host y data transfer
-  // launch saxpy<<<(N+255)/256, 256, 0>>>(N, 2.0f, dx, dy)
-  tf::cudaTask kernel = cf.kernel((N+255)/256, 256, 0, saxpy, N, 2.0f, dx, dy);
-  kernel.succeed(h2d_x, h2d_y)
-        .precede(d2h_x, d2h_y);
-});
-cudaflow.succeed(allocate_x, allocate_y);            // overlap data allocations
-
-executor.run(taskflow).wait();
-```
-
-Assume our kernel implements the canonical saxpy operation 
-(single-precision A·X Plus Y) using the CUDA syntax.
-
-<img align="right" src="image/saxpy.svg" width="50%">
-
-```cpp
-// saxpy (single-precision A·X Plus Y) kernel
-__global__ void saxpy(
-  int n, float a, float *x, float *y
-) {
-  // get the thread index
-  int i = blockIdx.x*blockDim.x + threadIdx.x;
-
-  if (i < n) {
-    y[i] = a*x[i] + y[i];
-  }
-}
-```
-
-
-
-## Step 2: Compile and Execute a cudaFlow
-
-Name you source with the extension `.cu`, let's say `saxpy.cu`,
-and compile it through [nvcc][nvcc]:
-
-```bash
-~$ nvcc saxpy.cu -I path/to/include/taskflow -O2 -o saxpy
-~$ ./saxpy
-```
-
-Our source autonomously enables cudaFlow for compilers that support
-CUDA.
-
-<div align="right"><b><a href="#table-of-contents">[↑]</a></b></div>
-
-# Visualize a Taskflow Graph
-
-You can dump a taskflow through a `std::ostream` 
-in [GraphViz][GraphViz] format using the method `dump`.
-There are a number of free [GraphViz tools][AwesomeGraphViz] you could find online to visualize your Taskflow graph.
-
-<img align="right" src="image/graphviz.svg" width="25%">
-
-```cpp
-tf::Taskflow taskflow;
-tf::Task A = taskflow.emplace([] () {}).name("A");
-tf::Task B = taskflow.emplace([] () {}).name("B");
-tf::Task C = taskflow.emplace([] () {}).name("C");
-tf::Task D = taskflow.emplace([] () {}).name("D");
-tf::Task E = taskflow.emplace([] () {}).name("E");
-A.precede(B, C, E); 
-C.precede(D);
-B.precede(D, E); 
-
-taskflow.dump(std::cout);  // dump the graph in DOT to std::cout
-```
-
-When you have tasks that are created at runtime (e.g., subflow, cudaFlow),
-you need to execute the graph first to spawn these tasks
-and dump the entire graph.
-
-<img align="right" src="image/debug_subflow.svg" width="25%">
-
-```cpp
-tf::Executor executor;
-tf::Taskflow taskflow;
-
-tf::Task A = taskflow.emplace([](){}).name("A");
-
-// create a subflow of two tasks B1->B2
-tf::Task B = taskflow.emplace([] (tf::Subflow& subflow) {
-  tf::Task B1 = subflow.emplace([](){}).name("B1");
-  tf::Task B2 = subflow.emplace([](){}).name("B2");
-  B1.precede(B2);
-}).name("B");
-
-A.precede(B);
-
-executor.run(tf).wait();  // run the taskflow to spawn subflows
-tf.dump(std::cout);       // dump the graph including dynamic tasks
-```
-
-<div align="right"><b><a href="#table-of-contents">[↑]</a></b></div>
-
-
-
-
-# API Reference
-
-The official [documentation][wiki] explains a complete list of 
-Taskflow API. 
-Here, we highlight commonly used methods.
-
-## Taskflow API
-
-The class `tf::Taskflow` is the main place to create a task dependency graph.
-
-### *emplace/placeholder*
-
-You can use `emplace` to create a task from a target callable.
-
-```cpp
-tf::Task task = taskflow.emplace([] () { std::cout << "my task\n"; });
-```
-
-When a task cannot be determined beforehand, you can create a placeholder and assign the callable later.
-
-```cpp
-tf::Task A = taskflow.emplace([](){});
-tf::Task B = taskflow.placeholder();
-A.precede(B);
-B.work([](){ /* do something */ });
-```
-
-### *parallel_for*
-
-The method `parallel_for` creates a subgraph that applies the callable to each item in the given range of a container.
-
-<img align="right" width="35%" src="image/parallel_for.svg">
-
-```cpp
-auto v = {'A', 'B', 'C', 'D'};
-auto [S, T] = taskflow.parallel_for(
-  v.begin(),    // iterator to the beginning
-  v.end(),      // iterator to the end
-  [] (int i) { 
-    std::cout << "parallel " << i << '\n';
-  }
-);
-// add dependencies via S and T.
-```
-
-You can specify a *chunk* size (default one) in the last argument to force a task to include a certain number of items.
-
-<img align="right" width="18%" src="image/parallel_for_2.svg">
-
-```cpp
-auto v = {'A', 'B', 'C', 'D'};
-auto [S, T] = taskflow.parallel_for(
-  v.begin(),    // iterator to the beginning
-  v.end(),      // iterator to the end
-  [] (int i) { 
-    std::cout << "AB and CD run in parallel" << '\n';
-  },
-  2  // at least two items at a time
-);
-```
-
-In addition to iterator-based construction, 
-`parallel_for` has another overload of index-based loop.
-The first three argument of this overload indicates 
-starting index, ending index (exclusive), and step size.
-
-```cpp
-// [0, 11) with a step size of 2
-auto [S, T] = taskflow.parallel_for(
-  0, 11, 2, 
-  [] (int i) {
-    std::cout << "parallel_for on index " << i << std::endl;
-  }, 
-  2  // at least two items at a time
-);
-// will print 0, 2, 4, 6, 8, 10 (three partitions, {0, 2}, {4, 6}, {8, 10})
-```
-
-## Task API
-
-Each time you create a task, the taskflow object adds a node to the present task dependency graph
-and return a *task handle* to you.
-You can access or modify the attributes of the associated task node.
-
-### *name*
-
-The method `name` lets you assign a human-readable string to a task.
-
-```cpp
-A.name("my name is A");
-```
-
-### *work*
-
-The method `work` lets you assign a callable to a task.
-
-```cpp
-A.work([] () { std::cout << "hello world!"; });
-```
-
-### *precede/succeed*
-
-The method `precede/succedd` lets you add a preceding/succeeding link between tasks.
-
-<img align="right" width="30%" src="image/broadcast.svg">
-
-```cpp
-// A runs before B, C, D, and E
-A.precede(B, C, D, E);
-```
-
-The method `succeed` is similar to `precede` but operates in the opposite direction.
-
-### *empty/has_work*
-
-A task is empty if it is not associated with any graph node.
-
-```cpp
-tf::Task task;  // assert(task.empty());
-```
-
-A placeholder task is associated with a graph node but has no work assigned yet.
-
-```
-tf::Task task = taskflow.placeholder();  // assert(!task.has_work());
-```
-
-## Executor API
-
-The class `tf::Executor` is used for executing one or multiple taskflow objects.
-
-### *run/run_n/run_until*
-
-The run series are *thread-safe* and *non-blocking* calls to execute a taskflow.
-Issuing multiple runs on the same taskflow will automatically synchronize 
-to a sequential chain of executions.
-
-```cpp
-executor.run(taskflow);                 // runs a graph once
-executor.run_n(taskflow, 5);            // runs a graph five times
-executor.run_until(taskflow, my_pred);  // keeps running until the my_pred becomes true
-executor.wait_for_all();                // blocks until all tasks finish
-```
-
-The first run finishes before the second run, and the second run finishes before the third run.
- <div align="right"><b><a href="#table-of-contents">[↑]</a></b></div>
-
-# System Requirements
-
-To use the latest [Taskflow](https://github.com/taskflow/taskflow/archive/master.zip), you only need a [C++14][C++14] compiler.
-
-+ GNU C++ Compiler at least v5.0 with -std=c++14
-+ Clang C++ Compiler at least v4.0 with -std=c++14
-+ Microsoft Visual Studio at least v15.7 (MSVC++ 19.14); see [vcpkg guide](https://github.com/taskflow/taskflow/issues/143)
-+ AppleClang Xode Version at least v8
-+ Nvidia CUDA Toolkit and Compiler ([nvcc][nvcc]) at least v10.0 with -std=c++14
-
-Taskflow works on Linux, Windows, and Mac OS X. See the [C++ compiler support](https://en.cppreference.com/w/cpp/compiler_support) status.
-
-<div align="right"><b><a href="#table-of-contents">[↑]</a></b></div>
-
-# Compile Unit Tests, Examples, and Benchmarks
-
-Taskflow uses [CMake](https://cmake.org/) to build examples and unit tests.
-We recommend using out-of-source build.
-
-```bash
-~$ cmake --version   # must be at least 3.9 or higher
-~$ mkdir build
-~$ cd build
-~$ cmake ../ 
-~$ make & make test  # run all unit tests
-```
-
-## Examples
-
-The folder `examples/` contains several examples and is a great place to learn to use Taskflow.
-
-| Example |  Description |
-| ------- |  ----------- | 
-| [simple.cpp](./examples/simple.cpp) | uses basic task building blocks to create a trivial taskflow  graph |
-| [debug.cpp](./examples/debug.cpp)| inspects a taskflow through the dump method |
-| [parallel_for.cpp](./examples/parallel_for.cpp)| parallelizes a for loop with unbalanced workload |
-| [subflow.cpp](./examples/subflow.cpp)| demonstrates how to create a subflow graph that spawns three dynamic tasks |
-| [run_variants.cpp](./examples/run_variants.cpp)| shows multiple ways to run a taskflow graph |
-| [composition.cpp](./examples/composition.cpp)| demonstrates the decomposable interface of taskflow |
-| [observer.cpp](./examples/observer.cpp)| demonstrates how to monitor the thread activities in scheduling and running tasks |
-| [condition.cpp](./examples/condition.cpp) | creates a conditional tasking graph with a feedback loop control flow |
-| [cuda/saxpy.cu](./examples/cuda/saxpy.cu) | uses cudaFlow to create a saxpy (single-precision A·X Plus Y) task graph |
-| [cuda/matmul.cu](./examples/cuda/matmul.cu) | uses cudaFlow to create a matrix multiplication workload and compares it with a CPU basline |
-
-## Benchmarks
-
-Please visit [benchmarks](benchmarks/benchmarks.md) to learn to
-compile the benchmarks.
-
-<div align="right"><b><a href="#table-of-contents">[↑]</a></b></div>
-
-# Who is Using Taskflow?
-
-Taskflow is being used in both industry and academic projects to scale up existing workloads 
-that incorporate complex task dependencies. 
-
-- [OpenTimer][OpenTimer]: A High-performance Timing Analysis Tool for Very Large Scale Integration (VLSI) Systems
-- [DtCraft][DtCraft]: A General-purpose Distributed Programming Systems using Data-parallel Streams
-- [Firestorm][Firestorm]: Fighting Game Engine with Asynchronous Resource Loaders (developed by [ForgeMistress][ForgeMistress])
-- [Shiva][Shiva]: An extensible engine via an entity component system through scripts, DLLs, and header-only (C++)
-- [PID Framework][PID Framework]: A Global Development Methodology Supported by a CMake API and Dedicated C++ Projects 
-- [NovusCore][NovusCore]: An emulating project for World of Warraft (Wrath of the Lich King 3.3.5a 12340 client build)
-- [SA-PCB][SA-PCB]: Annealing-based Printed Circuit Board (PCB) Placement Tool
-- [LPMP](https://github.com/LPMP/LPMP): A C++ framework for developing scalable Lagrangian decomposition solvers for discrete optimization problems
-- [Heteroflow](https://github.com/Heteroflow/Heteroflow): A Modern C++ Parallel CPU-GPU Task Programming Library
-- [OpenPhySyn](https://github.com/The-OpenROAD-Project/OpenPhySyn): A plugin-based physical synthesis optimization kit as part of the OpenRoad flow
-- [OSSIA](https://ossia.io/): Open-source Software System for Interactive Applications
-- [deal.II](https://github.com/dealii/dealii): A C++ software library to support the creation of finite element code
-
-[More...](https://github.com/search?q=taskflow&type=Code)
-
-<div align="right"><b><a href="#table-of-contents">[↑]</a></b></div>
-
-# Contributors
-
-Taskflow is being actively developed and contributed by the 
-[these people](https://github.com/taskflow/taskflow/graphs/contributors).
-Meanwhile, we appreciate the support from many organizations for our developments.
-
-
-| [<img src="image/utah.png" width="100px">][UofU] | [<img src="image/uiuc.png" width="100px">][UIUC] | [<img src="image/csl.png" width="100px">][CSL] | [<img src="image/nsf.png" width="100px">][NSF] | [<img src="image/darpa.png" width="100px">][DARPA IDEA] |
-| :---: | :---: | :---: | :---: | :---: |
-
-# License
-
-Taskflow is licensed under the [MIT License](./LICENSE).
-
-* * *
-
-[Tsung-Wei Huang]:       https://tsung-wei-huang.github.io/
-[Chun-Xun Lin]:          https://github.com/clin99
-[Martin Wong]:           https://ece.illinois.edu/directory/profile/mdfwong
-[Gitter badge]:          ./image/gitter_badge.svg
-[GitHub releases]:       https://github.com/taskflow/taskflow/releases
-[GitHub issues]:         https://github.com/taskflow/taskflow/issues
-[GitHub insights]:       https://github.com/taskflow/taskflow/pulse
-[GitHub pull requests]:  https://github.com/taskflow/taskflow/pulls
-[GitHub contributors]:   https://github.com/taskflow/taskflow/graphs/contributors
-[GraphViz]:              https://www.graphviz.org/
-[AwesomeGraphViz]:       https://dreampuf.github.io/GraphvizOnline/
-[OpenMP Tasking]:        https://www.openmp.org/spec-html/5.0/openmpsu99.html 
-[TBB FlowGraph]:         https://www.threadingbuildingblocks.org/tutorial-intel-tbb-flow-graph
-[OpenTimer]:             https://github.com/OpenTimer/OpenTimer
-[DtCraft]:               https://github.com/tsung-wei-huang/DtCraft
-[totalgee]:              https://github.com/totalgee
-[damienhocking]:         https://github.com/damienhocking
-[ForgeMistress]:         https://github.com/ForgeMistress
-[Patrik Huber]:          https://github.com/patrikhuber
-[DARPA IDEA]:            https://www.darpa.mil/news-events/2017-09-13
-[KingDuckZ]:             https://github.com/KingDuckZ
-[NSF]:                   https://www.nsf.gov/
-[UIUC]:                  https://illinois.edu/
-[CSL]:                   https://csl.illinois.edu/
-[UofU]:                  https://www.utah.edu/
-[wiki]:                  https://taskflow.github.io/taskflow/index.html
-[release notes]:         https://taskflow.github.io/taskflow/Releases.html
-[PayMe]:                 https://www.paypal.me/twhuang/10
-[C++17]:                 https://en.wikipedia.org/wiki/C%2B%2B17
-[C++14]:                 https://en.wikipedia.org/wiki/C%2B%2B14
-[email me]:              mailto:twh760812@gmail.com
-[Cpp Conference 2018]:   https://github.com/CppCon/CppCon2018
-[ChromeTracing]:         https://www.chromium.org/developers/how-tos/trace-event-profiling-tool
-[IPDPS19]:               https://tsung-wei-huang.github.io/papers/ipdps19.pdf
-[WorkStealing Wiki]:     https://en.wikipedia.org/wiki/Work_stealing
-
-[std::invoke]:           https://en.cppreference.com/w/cpp/utility/functional/invoke
-[std::future]:           https://en.cppreference.com/w/cpp/thread/future
-
-[cuda-zone]:             https://developer.nvidia.com/cuda-zone
-[nvcc]:                  https://developer.nvidia.com/cuda-llvm-compiler
-[cuda-toolkit]:          https://developer.nvidia.com/cuda-toolkit
-[cudaGraph]:             https://docs.nvidia.com/cuda/cuda-runtime-api/group__CUDART__GRAPH.html
-
-[Firestorm]:             https://github.com/ForgeMistress/Firestorm
-[Shiva]:                 https://shiva.gitbook.io/project/shiva
-[PID Framework]:         http://pid.lirmm.net/pid-framework/index.html
-[NovusCore]:             https://github.com/novuscore/NovusCore
-[SA-PCB]:                https://github.com/choltz95/SA-PCB
-
-[Presentation]:          https://taskflow.github.io/
-[chrome://tracing]:      chrome://tracing
-
diff --git a/bundled/taskflow-2.5.0/include/taskflow/core/error.hpp b/bundled/taskflow-2.5.0/include/taskflow/core/error.hpp
deleted file mode 100644 (file)
index 6739121..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-#pragma once
-
-#include <iostream>
-#include <sstream>
-#include <exception>
-
-#include "../utility/stringify.hpp"
-
-namespace tf {
-
-// Procedure: throw_se
-// Throws the system error under a given error code.
-template <typename... ArgsT>
-//void throw_se(const char* fname, const size_t line, Error::Code c, ArgsT&&... args) {
-void throw_re(const char* fname, const size_t line, ArgsT&&... args) {
-  std::ostringstream oss;
-  oss << "[" << fname << ":" << line << "] ";
-  ostreamize(oss, std::forward<ArgsT>(args)...);
-  //(oss << ... << args);
-  throw std::runtime_error(oss.str());
-}
-
-}  // ------------------------------------------------------------------------
-
-#define TF_THROW(...) tf::throw_re(__FILE__, __LINE__, __VA_ARGS__);
-
diff --git a/bundled/taskflow-2.5.0/include/taskflow/core/executor.hpp b/bundled/taskflow-2.5.0/include/taskflow/core/executor.hpp
deleted file mode 100644 (file)
index 8c47499..0000000
+++ /dev/null
@@ -1,1236 +0,0 @@
-#pragma once
-
-#include "tsq.hpp"
-#include "notifier.hpp"
-#include "observer.hpp"
-#include "taskflow.hpp"
-
-namespace tf {
-
-
-/** @class WorkerView
-
-@brief class to access worker information from the observer interface
-
-*/
-//class WorkerView {
-//
-//  friend class Executor;
-//
-//  public:
-//
-//
-//  private:
-//
-//    Worker* _worker;
-//
-//};
-
-
-// ----------------------------------------------------------------------------
-// Executor Definition
-// ----------------------------------------------------------------------------
-
-
-/** @class Executor
-
-@brief execution interface for running a taskflow graph
-
-An executor object manages a set of worker threads and internalements 
-an efficient work-stealing scheduling algorithm to run a taskflow.
-
-*/
-class Executor {
-
-  friend class Subflow;
-
-  struct Worker {
-    size_t id;
-    size_t victim;
-    Domain domain;
-    Executor* executor;
-    Notifier::Waiter* waiter;
-    std::mt19937 rdgen { std::random_device{}() };
-    TaskQueue<Node*> wsq[NUM_DOMAINS];
-  };
-    
-  struct PerThread {
-    Worker* worker {nullptr};
-  };
-
-#ifdef TF_ENABLE_CUDA
-  struct cudaDevice {
-    std::vector<cudaStream_t> streams;
-  };
-#endif
-
-  public:
-
-#ifdef TF_ENABLE_CUDA    
-    /**
-    @brief constructs the executor with N/M cpu/gpu worker threads
-    */
-    explicit Executor(
-      size_t N = std::thread::hardware_concurrency(),
-      size_t M = cuda_num_devices()
-    );
-#else
-    /**
-    @brief constructs the executor with N worker threads
-    */
-    explicit Executor(size_t N = std::thread::hardware_concurrency());
-#endif
-    
-    /**
-    @brief destructs the executor 
-    */
-    ~Executor();
-
-    /**
-    @brief runs the taskflow once
-    
-    @param taskflow a tf::Taskflow object
-
-    @return a std::future to access the execution status of the taskflow
-    */
-    std::future<void> run(Taskflow& taskflow);
-
-    /**
-    @brief runs the taskflow once and invoke a callback upon completion
-
-    @param taskflow a tf::Taskflow object 
-    @param callable a callable object to be invoked after this run
-
-    @return a std::future to access the execution status of the taskflow
-    */
-    template<typename C>
-    std::future<void> run(Taskflow& taskflow, C&& callable);
-
-    /**
-    @brief runs the taskflow for N times
-    
-    @param taskflow a tf::Taskflow object
-    @param N number of runs
-
-    @return a std::future to access the execution status of the taskflow
-    */
-    std::future<void> run_n(Taskflow& taskflow, size_t N);
-
-    /**
-    @brief runs the taskflow for N times and then invokes a callback
-
-    @param taskflow a tf::Taskflow 
-    @param N number of runs
-    @param callable a callable object to be invoked after this run
-
-    @return a std::future to access the execution status of the taskflow
-    */
-    template<typename C>
-    std::future<void> run_n(Taskflow& taskflow, size_t N, C&& callable);
-
-    /**
-    @brief runs the taskflow multiple times until the predicate becomes true and 
-           then invokes a callback
-
-    @param taskflow a tf::Taskflow 
-    @param pred a boolean predicate to return true for stop
-
-    @return a std::future to access the execution status of the taskflow
-    */
-    template<typename P>
-    std::future<void> run_until(Taskflow& taskflow, P&& pred);
-
-    /**
-    @brief runs the taskflow multiple times until the predicate becomes true and 
-           then invokes the callback
-
-    @param taskflow a tf::Taskflow 
-    @param pred a boolean predicate to return true for stop
-    @param callable a callable object to be invoked after this run
-
-    @return a std::future to access the execution status of the taskflow
-    */
-    template<typename P, typename C>
-    std::future<void> run_until(Taskflow& taskflow, P&& pred, C&& callable);
-    
-    /**
-    @brief wait for all pending graphs to complete
-    */
-    void wait_for_all();
-
-    /**
-    @brief queries the number of worker threads (can be zero)
-    */
-    size_t num_workers() const;
-    
-    /**
-    @brief queries the number of running topologies at the time of this call
-
-    When a taskflow is submitted to an executor, a topology is created to store
-    runtime metadata of the running taskflow.
-    */
-    size_t num_topologies() const;
-
-    /**
-    @brief queries the number of worker domains 
-
-    Each domain manages a subset of worker threads to execute domain-specific tasks,
-    for example, HOST tasks and CUDA tasks.
-    */
-    size_t num_domains() const;
-
-    /**
-    @brief queries the id of the caller thread in this executor
-
-    Each worker has an unique id from 0 to N-1 exclusive to the associated executor.
-    If the caller thread does not belong to the executor, -1 is returned.
-    */
-    int this_worker_id() const;
-    
-    /**
-    @brief constructs an observer to inspect the activities of worker threads
-
-    Each executor manage a list of observers in shared ownership with callers.
-    
-    @tparam Observer observer type derived from tf::ObserverInterface
-    @tparam ArgsT... argument parameter pack
-
-    @param args arguments to forward to the constructor of the observer
-    
-    @return a shared pointer to the created observer
-    */
-    template <typename Observer, typename... Args>
-    std::shared_ptr<Observer> make_observer(Args&&... args);
-    
-    /**
-    @brief removes the associated observer
-    */
-    template <typename Observer>
-    void remove_observer(std::shared_ptr<Observer> observer);
-
-    /**
-    @brief queries the number of observers
-    */
-    size_t num_observers() const;
-
-  private:
-    
-    const size_t _VICTIM_BEG;
-    const size_t _VICTIM_END;
-    const size_t _MAX_STEALS;
-    const size_t _MAX_YIELDS;
-   
-    std::condition_variable _topology_cv;
-    std::mutex _topology_mutex;
-    std::mutex _wsq_mutex;
-
-    size_t _num_topologies {0};
-    
-    std::vector<Worker> _workers;
-    std::vector<std::thread> _threads;
-
-#ifdef TF_ENABLE_CUDA
-    std::vector<cudaDevice> _cuda_devices;
-#endif
-    
-    Notifier _notifier[NUM_DOMAINS];
-
-    TaskQueue<Node*> _wsq[NUM_DOMAINS];
-
-    size_t _id_offset[NUM_DOMAINS] = {0};
-
-    std::atomic<size_t> _num_actives[NUM_DOMAINS];
-    std::atomic<size_t> _num_thieves[NUM_DOMAINS];
-    std::atomic<bool>   _done {0};
-    
-    std::unordered_set<std::shared_ptr<ObserverInterface>> _observers;
-
-    TFProfObserver* _tfprof;
-    
-    PerThread& _per_thread() const;
-
-    bool _wait_for_task(Worker&, Node*&);
-    
-    void _instantiate_tfprof();
-    void _flush_tfprof();
-    void _observer_prologue(Worker&, Node*);
-    void _observer_epilogue(Worker&, Node*);
-    void _spawn(size_t, Domain);
-    void _worker_loop(Worker&);
-    void _exploit_task(Worker&, Node*&);
-    void _explore_task(Worker&, Node*&);
-    void _schedule(Node*);
-    void _schedule(PassiveVector<Node*>&);
-    void _invoke(Worker&, Node*);
-    void _invoke_static_work(Worker&, Node*);
-    void _invoke_dynamic_work(Worker&, Node*);
-    void _invoke_dynamic_work_internal(Worker&, Node*, Graph&, bool);
-    void _invoke_dynamic_work_external(Graph&, Node*);
-    void _invoke_condition_work(Worker&, Node*);
-    void _invoke_module_work(Worker&, Node*);
-
-#ifdef TF_ENABLE_CUDA
-    void _invoke_cudaflow_work(Worker&, Node*);
-    void _invoke_cudaflow_work_internal(Worker&, Node*);
-#endif
-
-    void _set_up_topology(Topology*);
-    void _tear_down_topology(Topology*); 
-    void _increment_topology();
-    void _decrement_topology();
-    void _decrement_topology_and_notify();
-};
-
-
-#ifdef TF_ENABLE_CUDA
-// Constructor
-inline Executor::Executor(size_t N, size_t M) :
-  _VICTIM_BEG   {0},
-  _VICTIM_END   {N + M - 1},
-  _MAX_STEALS   {(N + M + 1) << 1},
-  _MAX_YIELDS   {100},
-  _workers      {N + M},
-  _cuda_devices {cuda_num_devices()},
-  _notifier     {Notifier(N), Notifier(M)} {
-
-  if(N == 0) {
-    TF_THROW("no cpu workers to execute taskflows");
-  }
-
-  if(M == 0) {
-    TF_THROW("no gpu workers to execute cudaflows");
-  }
-
-  for(int i=0; i<NUM_DOMAINS; ++i) {
-    _num_actives[i].store(0, std::memory_order_relaxed);
-    _num_thieves[i].store(0, std::memory_order_relaxed); 
-  }
-  
-  // create a per-worker stream on each cuda device
-  for(size_t i=0; i<_cuda_devices.size(); ++i) {
-    _cuda_devices[i].streams.resize(M);
-    cudaScopedDevice ctx(i);
-    for(size_t m=0; m<M; ++m) {
-      TF_CHECK_CUDA(
-        cudaStreamCreate(&(_cuda_devices[i].streams[m])),
-        "failed to create a cudaStream for worker ", m, " on device ", i
-      );
-    }
-  }
-
-  _spawn(N, HOST);
-  _spawn(M, CUDA);
-
-  // initiate the observer if requested
-  _instantiate_tfprof();
-}
-
-#else
-// Constructor
-inline Executor::Executor(size_t N) : 
-  _VICTIM_BEG {0},
-  _VICTIM_END {N - 1},
-  _MAX_STEALS {(N + 1) << 1},
-  _MAX_YIELDS {100},
-  _workers    {N},
-  _notifier   {Notifier(N)} {
-  
-  if(N == 0) {
-    TF_THROW("no cpu workers to execute taskflows");
-  }
-  
-  for(int i=0; i<NUM_DOMAINS; ++i) {
-    _num_actives[i].store(0, std::memory_order_relaxed);
-    _num_thieves[i].store(0, std::memory_order_relaxed); 
-  }
-
-  _spawn(N, HOST);
-
-  // instantite the default observer if requested
-  _instantiate_tfprof();
-}
-#endif
-
-// Destructor
-inline Executor::~Executor() {
-  
-  // wait for all topologies to complete
-  wait_for_all();
-  
-  // shut down the scheduler
-  _done = true;
-
-  for(int i=0; i<NUM_DOMAINS; ++i) {
-    _notifier[i].notify(true);
-  }
-  
-  for(auto& t : _threads){
-    t.join();
-  } 
-  
-#ifdef TF_ENABLE_CUDA  
-  // clean up the cuda streams
-  for(size_t i=0; i<_cuda_devices.size(); ++i) {
-    cudaScopedDevice ctx(i);
-    for(size_t m=0; m<_cuda_devices[i].streams.size(); ++m) {
-      cudaStreamDestroy(_cuda_devices[i].streams[m]);
-    }
-  }
-#endif
-  
-  // flush the default observer
-  _flush_tfprof();
-}
-
-// Procedure: _instantiate_tfprof
-inline void Executor::_instantiate_tfprof() {
-  // TF_OBSERVER_TYPE
-  _tfprof = get_env("TF_ENABLE_PROFILER").empty() ? 
-    nullptr : make_observer<TFProfObserver>().get();
-}
-
-// Procedure: _flush_tfprof
-inline void Executor::_flush_tfprof() {
-  if(_tfprof) {
-    std::ostringstream fpath;
-    fpath << get_env("TF_ENABLE_PROFILER") << _tfprof->_uuid << ".tfp";
-    std::ofstream ofs(fpath.str());
-    _tfprof->dump(ofs);
-  }
-}
-
-// Function: num_workers
-inline size_t Executor::num_workers() const {
-  return _workers.size();
-}
-
-// Function: num_domains
-inline size_t Executor::num_domains() const {
-  return NUM_DOMAINS;
-}
-
-// Function: num_topologies
-inline size_t Executor::num_topologies() const {
-  return _num_topologies;
-}
-
-// Function: _per_thread
-inline Executor::PerThread& Executor::_per_thread() const {
-  thread_local PerThread pt;
-  return pt;
-}
-
-// Function: this_worker_id
-inline int Executor::this_worker_id() const {
-  auto worker = _per_thread().worker;
-  return worker ? static_cast<int>(worker->id) : -1;
-}
-
-// Procedure: _spawn
-inline void Executor::_spawn(size_t N, Domain d) {
-  
-  auto id = _threads.size();
-
-  _id_offset[d] = id;
-
-  for(size_t i=0; i<N; ++i, ++id) {
-
-    _workers[id].id = id;
-    _workers[id].victim = id;
-    _workers[id].domain = d;
-    _workers[id].executor = this;
-    _workers[id].waiter = &_notifier[d]._waiters[i];
-    
-    _threads.emplace_back([this] (Worker& w) -> void {
-
-      PerThread& pt = _per_thread();  
-      pt.worker = &w;
-
-      Node* t = nullptr;
-
-      // must use 1 as condition instead of !done
-      while(1) {
-        
-        // execute the tasks.
-        _exploit_task(w, t);
-
-        // wait for tasks
-        if(_wait_for_task(w, t) == false) {
-          break;
-        }
-      }
-      
-    }, std::ref(_workers[id]));     
-  }
-
-}
-
-// Function: _explore_task
-inline void Executor::_explore_task(Worker& w, Node*& t) {
-  
-  //assert(_workers[w].wsq.empty());
-  assert(!t);
-
-  const auto d = w.domain;
-
-  size_t num_steals = 0;
-  size_t num_yields = 0;
-
-  std::uniform_int_distribution<size_t> rdvtm(_VICTIM_BEG, _VICTIM_END);
-
-  //while(!_done) {
-  //
-  //  size_t vtm = rdvtm(w.rdgen);
-  //    
-  //  t = (vtm == w.id) ? _wsq[d].steal() : _workers[vtm].wsq[d].steal();
-
-  //  if(t) {
-  //    break;
-  //  }
-
-  //  if(num_steal++ > _MAX_STEALS) {
-  //    std::this_thread::yield();
-  //    if(num_yields++ > _MAX_YIELDS) {
-  //      break;
-  //    }
-  //  }
-  //}
-
-  do {
-    t = (w.id == w.victim) ? _wsq[d].steal() : _workers[w.victim].wsq[d].steal();
-
-    if(t) {
-      break;
-    }
-    
-    if(num_steals++ > _MAX_STEALS) {
-      std::this_thread::yield();
-      if(num_yields++ > _MAX_YIELDS) {
-        break;
-      }
-    }
-    
-    w.victim = rdvtm(w.rdgen);
-  } while(!_done);
-
-}
-
-// Procedure: _exploit_task
-inline void Executor::_exploit_task(Worker& w, Node*& t) {
-  
-  if(t) {
-
-    const auto d = w.domain;
-
-    if(_num_actives[d].fetch_add(1) == 0 && _num_thieves[d] == 0) {
-      _notifier[d].notify(false);
-    }
-
-    do {
-
-      _invoke(w, t);
-      
-      if(t->_parent == nullptr) {
-        if(t->_topology->_join_counter.fetch_sub(1) == 1) {
-          _tear_down_topology(t->_topology);
-        }
-      }
-      else {  // joined subflow
-        t->_parent->_join_counter.fetch_sub(1);
-      }
-
-      t = w.wsq[d].pop();
-
-    } while(t);
-
-    --_num_actives[d];
-  }
-}
-
-// Function: _wait_for_task
-inline bool Executor::_wait_for_task(Worker& worker, Node*& t) {
-
-  const auto d = worker.domain;
-
-  wait_for_task:
-
-  assert(!t);
-
-  ++_num_thieves[d];
-
-  explore_task:
-
-  _explore_task(worker, t);
-
-  if(t) {
-    if(_num_thieves[d].fetch_sub(1) == 1) {
-      _notifier[d].notify(false);
-    }
-    return true;
-  }
-
-  _notifier[d].prepare_wait(worker.waiter);
-  
-  //if(auto vtm = _find_victim(me); vtm != _workers.size()) {
-  if(!_wsq[d].empty()) {
-
-    _notifier[d].cancel_wait(worker.waiter);
-    //t = (vtm == me) ? _wsq.steal() : _workers[vtm].wsq.steal();
-    
-    t = _wsq[d].steal();
-    if(t) {
-      if(_num_thieves[d].fetch_sub(1) == 1) {
-        _notifier[d].notify(false);
-      }
-      return true;
-    }
-    else {
-      worker.victim = worker.id;
-      goto explore_task;
-    }
-  }
-
-  if(_done) {
-    _notifier[d].cancel_wait(worker.waiter);
-    for(int i=0; i<NUM_DOMAINS; ++i) {
-      _notifier[i].notify(true);
-    }
-    --_num_thieves[d];
-    return false;
-  }
-
-  if(_num_thieves[d].fetch_sub(1) == 1) {
-    if(_num_actives[d]) {
-      _notifier[d].cancel_wait(worker.waiter);
-      goto wait_for_task;
-    }
-    // check all domain queue again
-    for(auto& w : _workers) {
-      if(!w.wsq[d].empty()) {
-        worker.victim = w.id;
-        _notifier[d].cancel_wait(worker.waiter);
-        goto wait_for_task;
-      }
-    }
-  }
-    
-  // Now I really need to relinguish my self to others
-  _notifier[d].commit_wait(worker.waiter);
-
-  return true;
-}
-
-// Function: make_observer    
-template<typename Observer, typename... Args>
-std::shared_ptr<Observer> Executor::make_observer(Args&&... args) {
-
-  static_assert(
-    std::is_base_of<ObserverInterface, Observer>::value,
-    "Observer must be derived from ObserverInterface"
-  );
-  
-  // use a local variable to mimic the constructor 
-  auto ptr = std::make_shared<Observer>(std::forward<Args>(args)...);
-  
-  ptr->set_up(_workers.size());
-
-  _observers.emplace(std::static_pointer_cast<ObserverInterface>(ptr));
-
-  return ptr;
-}
-
-// Procedure: remove_observer
-template <typename Observer>
-void Executor::remove_observer(std::shared_ptr<Observer> ptr) {
-  
-  static_assert(
-    std::is_base_of<ObserverInterface, Observer>::value,
-    "Observer must be derived from ObserverInterface"
-  );
-
-  _observers.erase(std::static_pointer_cast<ObserverInterface>(ptr));
-}
-
-// Function: num_observers
-inline size_t Executor::num_observers() const {
-  return _observers.size();
-}
-
-// Procedure: _schedule
-// The main procedure to schedule a give task node.
-// Each task node has two types of tasks - regular and subflow.
-inline void Executor::_schedule(Node* node) {
-  
-  //assert(_workers.size() != 0);
-
-  const auto d = node->domain();
-  
-  // caller is a worker to this pool
-  auto worker = _per_thread().worker;
-
-  if(worker != nullptr && worker->executor == this) {
-    worker->wsq[d].push(node);
-    if(worker->domain != d) {
-      if(_num_actives[d] == 0 && _num_thieves[d] == 0) {
-        _notifier[d].notify(false);
-      }
-    }
-    return;
-  }
-
-  // other threads
-  {
-    std::lock_guard<std::mutex> lock(_wsq_mutex);
-    _wsq[d].push(node);
-  }
-
-  _notifier[d].notify(false);
-}
-
-// Procedure: _schedule
-// The main procedure to schedule a set of task nodes.
-// Each task node has two types of tasks - regular and subflow.
-inline void Executor::_schedule(PassiveVector<Node*>& nodes) {
-
-  //assert(_workers.size() != 0);
-  
-  // We need to cacth the node count to avoid accessing the nodes
-  // vector while the parent topology is removed!
-  const auto num_nodes = nodes.size();
-  
-  if(num_nodes == 0) {
-    return;
-  }
-
-  // worker thread
-  auto worker = _per_thread().worker;
-
-  // task counts
-  size_t tcount[NUM_DOMAINS] = {0};
-
-  if(worker != nullptr && worker->executor == this) {
-    for(size_t i=0; i<num_nodes; ++i) {
-      const auto d = nodes[i]->domain();
-      worker->wsq[d].push(nodes[i]);
-      tcount[d]++;
-    }
-    
-    for(int d=0; d<NUM_DOMAINS; ++d) {
-      if(tcount[d] && d != worker->domain) {
-        if(_num_actives[d] == 0 && _num_thieves[d] == 0) {
-          _notifier[d].notify_n(tcount[d]);
-        }
-      }
-    }
-
-    return;
-  }
-  
-  // other threads
-  {
-    std::lock_guard<std::mutex> lock(_wsq_mutex);
-    for(size_t k=0; k<num_nodes; ++k) {
-      const auto d = nodes[k]->domain();
-      _wsq[d].push(nodes[k]);
-      tcount[d]++;
-    }
-  }
-  
-  for(int d=0; d<NUM_DOMAINS; ++d) {
-    _notifier[d].notify_n(tcount[d]);
-  }
-}
-
-
-// Procedure: _invoke
-inline void Executor::_invoke(Worker& worker, Node* node) {
-
-  //assert(_workers.size() != 0);
-
-  // Here we need to fetch the num_successors first to avoid the invalid memory
-  // access caused by topology clear.
-  const auto num_successors = node->num_successors();
-  
-  // acquire the parent flow counter
-  auto& c = (node->_parent) ? node->_parent->_join_counter : 
-                              node->_topology->_join_counter;
-  
-  // switch is faster than nested if-else due to jump table
-  switch(node->_handle.index()) {
-    // static task
-    case Node::STATIC_WORK:{
-      _invoke_static_work(worker, node);
-    } 
-    break;
-
-    // module task
-    case Node::MODULE_WORK: {
-      _invoke_module_work(worker, node);
-    }
-    break;
-
-    // dynamic task
-    case Node::DYNAMIC_WORK: {
-      _invoke_dynamic_work(worker, node);
-    }
-    break;
-
-    // condition task
-    case Node::CONDITION_WORK: {
-      _invoke_condition_work(worker, node);
-      return ;
-    }  // no need to add a break here due to the immediate return
-
-    // cudaflow task
-#ifdef TF_ENABLE_CUDA
-    case Node::CUDAFLOW_WORK: {
-      _invoke_cudaflow_work(worker, node);
-    }
-    break; 
-#endif
-
-    // monostate
-    default:
-    break;
-  }
-
-  // We MUST recover the dependency since subflow may have  
-  // a condition node to go back (cyclic).
-  // This must be done before scheduling the successors, otherwise this might cause 
-  // race condition on the _dependents
-  if(node->_has_state(Node::BRANCH)) {
-    // If this is a case node, we need to deduct condition predecessors
-    node->_join_counter = node->num_strong_dependents();
-  }
-  else {
-    node->_join_counter = node->num_dependents();
-  }
-
-  // At this point, the node storage might be destructed.
-  for(size_t i=0; i<num_successors; ++i) {
-    if(--(node->_successors[i]->_join_counter) == 0) {
-      c.fetch_add(1);
-      _schedule(node->_successors[i]);
-    }
-  }
-}
-
-// Procedure: _observer_prologue
-inline void Executor::_observer_prologue(Worker& worker, Node* node) {
-  for(auto& observer : _observers) {
-    observer->on_entry(worker.id, TaskView(node));
-  }
-}
-
-// Procedure: _observer_epilogue
-inline void Executor::_observer_epilogue(Worker& worker, Node* node) {
-  for(auto& observer : _observers) {
-    observer->on_exit(worker.id, TaskView(node));
-  }
-}
-
-// Procedure: _invoke_static_work
-inline void Executor::_invoke_static_work(Worker& worker, Node* node) {
-  _observer_prologue(worker, node);
-  nstd::get<Node::StaticWork>(node->_handle).work();
-  _observer_epilogue(worker, node);
-}
-
-// Procedure: _invoke_dynamic_work
-inline void Executor::_invoke_dynamic_work(Worker& w, Node* node) {
-
-  _observer_prologue(w, node);
-
-  auto& handle = nstd::get<Node::DynamicWork>(node->_handle);
-
-  handle.subgraph.clear();
-
-  Subflow fb(*this, node, handle.subgraph); 
-
-  handle.work(fb);
-
-  if(!fb._joined) {
-    _invoke_dynamic_work_internal(w, node, handle.subgraph, fb._detach);
-  }
-  
-  // TODO 
-  _observer_epilogue(w, node);
-}
-
-// Procedure: _invoke_dynamic_work_external
-inline void Executor::_invoke_dynamic_work_external(Graph& g, Node* p) {
-
-  auto worker = _per_thread().worker;
-
-  assert(worker && worker->executor == this);
-  
-  _invoke_dynamic_work_internal(*worker, p, g, false);
-}
-
-// Procedure: _invoke_dynamic_work_internal
-inline void Executor::_invoke_dynamic_work_internal(Worker& w, Node* p, Graph& g, bool d) {
-
-  if(!g.empty()) {
-
-    PassiveVector<Node*> src; 
-
-    for(auto n : g._nodes) {
-
-      n->_topology = p->_topology;
-      n->_set_up_join_counter();
-      n->_parent = d ? nullptr : p;
-      
-      if(n->num_dependents() == 0) {
-        src.push_back(n);
-      }
-    }
-    
-    // detach here
-    if(d) { 
-      p->_topology->_join_counter.fetch_add(src.size());
-      _schedule(src);
-    }
-    // join here
-    else {  
-      p->_join_counter.fetch_add(src.size());
-      _schedule(src);
-      Node* t = nullptr;
-
-      do {
-        t = w.wsq[w.domain].pop();
-    
-        if(t) {
-          _invoke(w, t);
-          t->_parent ? t->_parent->_join_counter.fetch_sub(1) :
-                       t->_topology->_join_counter.fetch_sub(1);
-        }
-
-      } while(p->_join_counter != 0);
-    }
-  }
-}
-
-// Procedure: _invoke_condition_work
-inline void Executor::_invoke_condition_work(Worker& worker, Node* node) {
-
-  _observer_prologue(worker, node);
-  
-  if(node->_has_state(Node::BRANCH)) {
-    node->_join_counter = node->num_strong_dependents();
-  }
-  else {
-    node->_join_counter = node->num_dependents();
-  }
-  
-  auto id = nstd::get<Node::ConditionWork>(node->_handle).work();
-
-  if(id >= 0 && static_cast<size_t>(id) < node->num_successors()) {
-    auto s = node->_successors[id];
-    s->_join_counter.store(0);
-
-    node->_parent ? node->_parent->_join_counter.fetch_add(1) :
-                    node->_topology->_join_counter.fetch_add(1);
-    _schedule(s);
-
-
-    //if(s->domain() == worker.domain) {
-    //  _schedule(s, true);
-    //}
-    //else {
-    //  node->_parent ? node->_parent->_join_counter.fetch_add(1) :
-    //                  node->_topology->_join_counter.fetch_add(1);
-    //  _schedule(s, false);
-    //}
-  }
-
-  _observer_epilogue(worker, node);
-}
-
-#ifdef TF_ENABLE_CUDA
-// Procedure: _invoke_cudaflow_work
-inline void Executor::_invoke_cudaflow_work(Worker& worker, Node* node) {
-  _observer_prologue(worker, node);  
-  _invoke_cudaflow_work_internal(worker, node);
-  _observer_epilogue(worker, node);
-}
-
-// Procedure: _invoke_cudaflow_work_internal
-inline void Executor::_invoke_cudaflow_work_internal(Worker& w, Node* node) {
-  
-  assert(w.domain == node->domain());
-
-  auto& h = nstd::get<Node::cudaFlowWork>(node->_handle);
-
-  h.graph.clear();
-
-  cudaFlow cf(h.graph, [repeat=1] () mutable { return repeat-- == 0; });
-
-  h.work(cf); 
-
-  if(h.graph.empty()) {
-    return;
-  }
-  
-  // transforms cudaFlow to a native cudaGraph under the specified device
-  // and launches the graph through a given or an internal device stream
-  const int d = cf._device;
-
-  cudaScopedDevice ctx(d);
-  
-  auto s = cf._stream ? *(cf._stream) : 
-                        _cuda_devices[d].streams[w.id - _id_offset[w.domain]];
-
-  h.graph._make_native_graph();
-
-  cudaGraphExec_t exec;
-
-  TF_CHECK_CUDA(
-    cudaGraphInstantiate(&exec, h.graph._native_handle, nullptr, nullptr, 0),
-    "failed to create an executable cudaGraph"
-  );
-  
-  while(!cf._predicate()) {
-    TF_CHECK_CUDA(
-      cudaGraphLaunch(exec, s), "failed to launch cudaGraph on stream ", s
-    );
-
-    TF_CHECK_CUDA(
-      cudaStreamSynchronize(s), "failed to synchronize stream ", s
-    );
-  }
-
-  TF_CHECK_CUDA(
-    cudaGraphExecDestroy(exec), "failed to destroy an executable cudaGraph"
-  );
-}
-#endif
-
-// Procedure: _invoke_module_work
-inline void Executor::_invoke_module_work(Worker& w, Node* node) {
-
-  _observer_prologue(w, node);
-  
-  auto module = nstd::get<Node::ModuleWork>(node->_handle).module;
-  
-  _invoke_dynamic_work_internal(w, node, module->_graph, false);
-  
-  _observer_epilogue(w, node);  
-}
-
-// Function: run
-inline std::future<void> Executor::run(Taskflow& f) {
-  return run_n(f, 1, [](){});
-}
-
-// Function: run
-template <typename C>
-std::future<void> Executor::run(Taskflow& f, C&& c) {
-  return run_n(f, 1, std::forward<C>(c));
-}
-
-// Function: run_n
-inline std::future<void> Executor::run_n(Taskflow& f, size_t repeat) {
-  return run_n(f, repeat, [](){});
-}
-
-// Function: run_n
-template <typename C>
-std::future<void> Executor::run_n(Taskflow& f, size_t repeat, C&& c) {
-  return run_until(f, [repeat]() mutable { return repeat-- == 0; }, std::forward<C>(c));
-}
-
-// Function: run_until    
-template<typename P>
-std::future<void> Executor::run_until(Taskflow& f, P&& pred) {
-  return run_until(f, std::forward<P>(pred), [](){});
-}
-
-// Function: _set_up_topology
-inline void Executor::_set_up_topology(Topology* tpg) {
-
-  tpg->_sources.clear();
-  
-  // scan each node in the graph and build up the links
-  for(auto node : tpg->_taskflow._graph._nodes) {
-
-    node->_topology = tpg;
-    node->_clear_state();
-
-    if(node->num_dependents() == 0) {
-      tpg->_sources.push_back(node);
-    }
-
-    node->_set_up_join_counter();
-  }
-
-  tpg->_join_counter.store(tpg->_sources.size(), std::memory_order_relaxed);
-}
-
-// Function: _tear_down_topology
-inline void Executor::_tear_down_topology(Topology* tpg) {
-
-  auto &f = tpg->_taskflow;
-
-  //assert(&tpg == &(f._topologies.front()));
-
-  // case 1: we still need to run the topology again
-  if(! tpg->_pred() ) {
-    //tpg->_recover_num_sinks();
-
-    assert(tpg->_join_counter == 0);
-    tpg->_join_counter = tpg->_sources.size();
-
-    _schedule(tpg->_sources); 
-  }
-  // case 2: the final run of this topology
-  else {
-    
-    if(tpg->_call != nullptr) {
-      tpg->_call();
-    }
-
-    f._mtx.lock();
-
-    // If there is another run (interleave between lock)
-    if(f._topologies.size() > 1) {
-
-      assert(tpg->_join_counter == 0);
-
-      // Set the promise
-      tpg->_promise.set_value();
-      f._topologies.pop_front();
-      f._mtx.unlock();
-      
-      // decrement the topology but since this is not the last we don't notify
-      _decrement_topology();
-
-      tpg = &(f._topologies.front());
-
-      _set_up_topology(tpg);
-      _schedule(tpg->_sources);
-
-      //f._topologies.front()._bind(f._graph);
-      //*tpg = &(f._topologies.front());
-
-      //assert(f._topologies.front()._join_counter == 0);
-
-      //f._topologies.front()._join_counter = f._topologies.front()._sources.size();
-
-      //_schedule(f._topologies.front()._sources);
-    }
-    else {
-      assert(f._topologies.size() == 1);
-
-      // Need to back up the promise first here becuz taskflow might be 
-      // destroy before taskflow leaves
-      auto p {std::move(tpg->_promise)};
-
-      f._topologies.pop_front();
-
-      f._mtx.unlock();
-
-      // We set the promise in the end in case taskflow leaves before taskflow
-      p.set_value();
-
-      _decrement_topology_and_notify();
-    }
-  }
-}
-
-// Function: run_until
-template <typename P, typename C>
-std::future<void> Executor::run_until(Taskflow& f, P&& pred, C&& c) {
-
-  _increment_topology();
-
-  // Special case of predicate
-  if(f.empty() || pred()) {
-    std::promise<void> promise;
-    promise.set_value();
-    _decrement_topology_and_notify();
-    return promise.get_future();
-  }
-  
-  // Multi-threaded execution.
-  bool run_now {false};
-  Topology* tpg;
-  std::future<void> future;
-  
-  {
-    std::lock_guard<std::mutex> lock(f._mtx);
-
-    // create a topology for this run
-    //tpg = &(f._topologies.emplace_back(f, std::forward<P>(pred), std::forward<C>(c)));
-    f._topologies.emplace_back(f, std::forward<P>(pred), std::forward<C>(c));
-    tpg = &(f._topologies.back());
-    future = tpg->_promise.get_future();
-   
-    if(f._topologies.size() == 1) {
-      run_now = true;
-      //tpg->_bind(f._graph);
-      //_schedule(tpg->_sources);
-    }
-  }
-  
-  // Notice here calling schedule may cause the topology to be removed sonner 
-  // before the function leaves.
-  if(run_now) {
-    _set_up_topology(tpg);
-    _schedule(tpg->_sources);
-  }
-
-  return future;
-}
-
-// Procedure: _increment_topology
-inline void Executor::_increment_topology() {
-  std::lock_guard<std::mutex> lock(_topology_mutex);
-  ++_num_topologies;
-}
-
-// Procedure: _decrement_topology_and_notify
-inline void Executor::_decrement_topology_and_notify() {
-  std::lock_guard<std::mutex> lock(_topology_mutex);
-  if(--_num_topologies == 0) {
-    _topology_cv.notify_all();
-  }
-}
-
-// Procedure: _decrement_topology
-inline void Executor::_decrement_topology() {
-  std::lock_guard<std::mutex> lock(_topology_mutex);
-  --_num_topologies;
-}
-
-// Procedure: wait_for_all
-inline void Executor::wait_for_all() {
-  std::unique_lock<std::mutex> lock(_topology_mutex);
-  _topology_cv.wait(lock, [&](){ return _num_topologies == 0; });
-}
-
-// ----------------------------------------------------------------------------
-// Cyclic Dependency
-// ----------------------------------------------------------------------------
-
-inline void Subflow::join() {
-
-  if(_joined) {
-    TF_THROW("subflow already joined");
-  }
-
-  _executor._invoke_dynamic_work_external(_graph, _parent);
-  _joined = true;
-}
-
-}  // end of namespace tf -----------------------------------------------------
-
-
-
-
-
-
-
-
-
-
-
diff --git a/bundled/taskflow-2.5.0/include/taskflow/core/flow_builder.hpp b/bundled/taskflow-2.5.0/include/taskflow/core/flow_builder.hpp
deleted file mode 100644 (file)
index e554730..0000000
+++ /dev/null
@@ -1,949 +0,0 @@
-#pragma once
-
-#include "task.hpp"
-
-namespace tf {
-
-/** 
-@class FlowBuilder
-
-@brief building methods of a task dependency graph
-
-*/
-class FlowBuilder {
-
-  friend class Executor;
-
-  public:
-    
-    /**
-    @brief creates a static task from a given callable object
-    
-    @tparam C callable type
-    
-    @param callable a callable object constructible from std::function<void()>
-
-    @return Task handle
-    */
-    template <typename C>
-    std::enable_if_t<is_static_task_v<C>, Task> emplace(C&& callable);
-
-    /**
-    @brief creates a dynamic task from a given callable object
-    
-    @tparam C callable type
-    
-    @param callable a callable object constructible from std::function<void(Subflow&)>
-
-    @return Task handle
-    */
-    template <typename C>
-    std::enable_if_t<is_dynamic_task_v<C>, Task> emplace(C&& callable);
-
-    /**
-    @brief creates a condition task from a given callable object
-    
-    @tparam C callable type
-    
-    @param callable a callable object constructible from std::function<int()>
-
-    @return Task handle
-    */
-    template <typename C>
-    std::enable_if_t<is_condition_task_v<C>, Task> emplace(C&& callable);
-
-#ifdef TF_ENABLE_CUDA
-    /**
-    @brief creates a cudaflow task from a given callable object
-    
-    @tparam C callable type
-    
-    @param callable a callable object constructible from std::function<void(cudaFlow&)>
-
-    @return Task handle
-    */
-    template <typename C>
-    std::enable_if_t<is_cudaflow_task_v<C>, Task> emplace(C&& callable);
-#endif 
-
-    /**
-    @brief creates multiple tasks from a list of callable objects
-    
-    @tparam C... callable types
-
-    @param callables one or multiple callable objects constructible from each task category
-
-    @return a Task handle
-    */
-    template <typename... C, std::enable_if_t<(sizeof...(C)>1), void>* = nullptr>
-    auto emplace(C&&... callables);
-
-    /**
-    @brief creates a module task from a taskflow
-
-    @param taskflow a taskflow object for the module
-    @return a Task handle
-    */
-    Task composed_of(Taskflow& taskflow);
-    
-    /**
-    @brief constructs a task dependency graph of range-based parallel_for
-    
-    The task dependency graph applies the callable object
-    @p callable to each object obtained by dereferencing
-    every iterator in the range [beg, end). The range
-    is split into chunks of size @p chunk, where each of them
-    is processed by one Task.
-
-    The callable needs to accept a single argument, the object in the range.
-
-    @tparam I input iterator type
-    @tparam C callable type
-
-    @param beg iterator to the beginning (inclusive)
-    @param end iterator to the end (exclusive)
-    @param callable a callable object to be applied to 
-    @param chunk size (default 1)
-
-    @return a pair of Task handles to the beginning and the end of the graph
-    */
-    template <typename I, typename C>
-    std::pair<Task, Task> parallel_for(I beg, I end, C&& callable, size_t chunk=1);
-    
-    /**
-    @brief constructs a task dependency graph of integer index-based parallel_for
-    
-    The task dependency graph applies a callable object to every index 
-    in the range [beg, end) with a step size chunk by chunk.
-
-    @tparam I integer (arithmetic) index type
-    @tparam C callable type
-
-    @param beg index of the beginning (inclusive)
-    @param end index of the end (exclusive)
-    @param step step size 
-    @param callable a callable object to be applied to
-    @param chunk items per task
-
-    @return a pair of Task handles to the beginning and the end of the graph
-    */
-    template <
-      typename I, 
-      typename C, 
-      std::enable_if_t<std::is_integral<std::decay_t<I>>::value, void>* = nullptr
-    >
-    std::pair<Task, Task> parallel_for(
-      I beg, I end, I step, C&& callable, size_t chunk = 1
-    );
-
-    /**
-    @brief constructs a task dependency graph of floating index-based parallel_for
-    
-    The task dependency graph applies a callable object to every index 
-    in the range [beg, end) with a step size chunk by chunk.
-
-    @tparam I floating (arithmetic) index type
-    @tparam C callable type
-
-    @param beg index of the beginning (inclusive)
-    @param end index of the end (exclusive)
-    @param step step size 
-    @param callable a callable object to be applied to
-    @param chunk items per task
-
-    @return a pair of Task handles to the beginning and the end of the graph
-    */
-    template <
-      typename I, 
-      typename C, 
-      std::enable_if_t<std::is_floating_point<std::decay_t<I>>::value, void>* = nullptr
-    >
-    std::pair<Task, Task> parallel_for(
-      I beg, I end, I step, C&& callable, size_t chunk = 1
-    );
-    /**
-    @brief construct a task dependency graph of parallel reduction
-    
-    The task dependency graph reduces items in the range [beg, end) to a single result.
-    
-    @tparam I input iterator type
-    @tparam T data type
-    @tparam B binary operator type
-
-    @param beg    iterator to the beginning (inclusive)
-    @param end    iterator to the end (exclusive)
-    @param result reference variable to store the final result
-    @param bop    binary operator that will be applied in unspecified order to the result
-                  of dereferencing the input iterator
-    
-    @return a pair of Task handles to the beginning and the end of the graph
-    */
-    template <typename I, typename T, typename B>
-    std::pair<Task, Task> reduce(I beg, I end, T& result, B&& bop);
-    
-    /**
-    @brief constructs a task dependency graph of parallel reduction through @std_min
-    
-    The task dependency graph applies a parallel reduction
-    to find the minimum item in the range [beg, end) through @std_min reduction.
-
-    @tparam I input iterator type
-    @tparam T data type 
-
-    @param beg    iterator to the beginning (inclusive)
-    @param end    iterator to the end (exclusive)
-    @param result reference variable to store the final result
-
-    @return a pair of Task handles to the beginning and the end of the graph
-    */
-    template <typename I, typename T>
-    std::pair<Task, Task> reduce_min(I beg, I end, T& result);
-    
-    /**
-    @brief constructs a task dependency graph of parallel reduction through @std_max
-    
-    The task dependency graph applies a parallel reduction
-    to find the maximum item in the range [beg, end) through @std_max reduction.
-
-    @tparam I input iterator type
-    @tparam T data type 
-
-    @param beg    iterator to the beginning (inclusive)
-    @param end    iterator to the end (exclusive)
-    @param result reference variable to store the final result
-
-    @return a pair of Task handles to the beginning and the end of the graph
-    */
-    template <typename I, typename T>
-    std::pair<Task, Task> reduce_max(I beg, I end, T& result);
-    
-    /** 
-    @brief constructs a task dependency graph of parallel transformation and reduction
-    
-    The task dependency graph transforms each item in the range [beg, end) 
-    into a new data type and then reduce the results.
-
-    @tparam I input iterator type
-    @tparam T data type
-    @tparam B binary operator
-    @tparam U unary operator type
-
-    @param beg    iterator to the beginning (inclusive)
-    @param end    iterator to the end (exclusive)
-    @param result reference variable to store the final result
-    @param bop    binary function object that will be applied in unspecified order 
-                  to the results of @c uop; the return type must be @c T
-    @param uop    unary function object that transforms each element 
-                  in the input range; the return type must be acceptable as input to @c bop
-    
-    @return a pair of Task handles to the beginning and the end of the graph
-    */
-    template <typename I, typename T, typename B, typename U>
-    std::pair<Task, Task> transform_reduce(I beg, I end, T& result, B&& bop, U&& uop);
-    
-    /**
-    @brief constructs a task dependency graph of parallel transformation and reduction
-    
-    The task dependency graph transforms each item in the range [beg, end) 
-    into a new data type and then apply two-layer reductions to derive the result.
-
-    @tparam I input iterator type
-    @tparam T data type
-    @tparam B binary operator type
-    @tparam P binary operator type
-    @tparam U unary operator type
-
-    @param beg    iterator to the beginning (inclusive)
-    @param end    iterator to the end (exclusive)
-    @param result reference variable to store the final result
-    @param bop1   binary function object that will be applied in the second-layer reduction
-                  to the results of @c bop2
-    @param bop2   binary function object that will be applied in the first-layer reduction
-                  to the results of @c uop and the dereferencing of input iterators
-    @param uop    unary function object that will be applied to transform an item to a new 
-                  data type that is acceptable as input to @c bop2
-    
-    @return a pair of Task handles to the beginning and the end of the graph
-    */
-    template <typename I, typename T, typename B, typename P, typename U>
-    std::pair<Task, Task> transform_reduce(
-      I beg, I end, T& result, B&& bop1, P&& bop2, U&& uop
-    );
-    
-    /**
-    @brief creates an empty task
-
-    @return a Task handle
-    */
-    Task placeholder();
-    
-    /**
-    @brief adds a dependency link from task A to task B
-    
-    @param A task A
-    @param B task B
-    */
-    void precede(Task A, Task B);
-
-    /**
-    @brief adds adjacent dependency links to a linear list of tasks
-
-    @param tasks a vector of tasks
-    */
-    void linearize(std::vector<Task>& tasks);
-
-    /**
-    @brief adds adjacent dependency links to a linear list of tasks
-
-    @param tasks an initializer list of tasks
-    */
-    void linearize(std::initializer_list<Task> tasks);
-
-    /**
-    @brief adds dependency links from one task A to many tasks
-
-    @param A      task A
-    @param others a task set which A precedes
-    */
-    void broadcast(Task A, std::vector<Task>& others);
-
-    /**
-    @brief adds dependency links from one task A to many tasks
-
-    @param A      task A
-    @param others a task set which A precedes
-    */
-    void broadcast(Task A, std::initializer_list<Task> others);
-
-    /**
-    @brief adds dependency links from many tasks to one task A
-
-    @param others a task set to precede A
-    @param A task A
-    */
-    void succeed(std::vector<Task>& others, Task A);
-
-    /**
-    @brief adds dependency links from many tasks to one task A
-
-    @param others a task set to precede A
-    @param A task A
-    */
-    void succeed(std::initializer_list<Task> others, Task A);
-    
-  protected:
-    
-    /**
-    @brief constructs a flow builder with a graph
-    */
-    FlowBuilder(Graph& graph);
-    
-    /**
-    @brief associated graph object
-    */
-    Graph& _graph;
-
-  private:
-
-    template <typename L>
-    void _linearize(L&);
-};
-
-// Constructor
-inline FlowBuilder::FlowBuilder(Graph& graph) :
-  _graph {graph} {
-}
-
-// Function: emplace
-template <typename... C, std::enable_if_t<(sizeof...(C)>1), void>*>
-auto FlowBuilder::emplace(C&&... cs) {
-  return std::make_tuple(emplace(std::forward<C>(cs))...);
-}
-
-// Function: emplace
-// emplaces a static task
-template <typename C>
-std::enable_if_t<is_static_task_v<C>, Task> FlowBuilder::emplace(C&& c) {
-  auto n = _graph.emplace_back(
-    nstd::in_place_type_t<Node::StaticWork>{}, std::forward<C>(c)
-  );
-  return Task(n);
-}
-
-// Function: emplace
-// emplaces a dynamic task
-template <typename C>
-std::enable_if_t<is_dynamic_task_v<C>, Task> FlowBuilder::emplace(C&& c) {
-  auto n = _graph.emplace_back(
-    nstd::in_place_type_t<Node::DynamicWork>{}, std::forward<C>(c)
-  );
-  return Task(n);
-}
-
-// Function: emplace 
-// emplaces a condition task
-template <typename C>
-std::enable_if_t<is_condition_task_v<C>, Task> FlowBuilder::emplace(C&& c) {
-  auto n = _graph.emplace_back(
-    nstd::in_place_type_t<Node::ConditionWork>{}, std::forward<C>(c)
-  );
-  return Task(n);
-}
-
-#ifdef TF_ENABLE_CUDA
-// Function: emplace
-// emplaces a cudaflow task
-template <typename C>
-std::enable_if_t<is_cudaflow_task_v<C>, Task> FlowBuilder::emplace(C&& c) {
-  auto n = _graph.emplace_back(
-    nstd::in_place_type_t<Node::cudaFlowWork>{}, std::forward<C>(c)
-  );
-  return Task(n);
-}
-#endif
-
-// Function: composed_of    
-inline Task FlowBuilder::composed_of(Taskflow& taskflow) {
-  auto node = _graph.emplace_back(
-    nstd::in_place_type_t<Node::ModuleWork>{}, &taskflow
-  );
-  return Task(node);
-}
-
-// Procedure: precede
-inline void FlowBuilder::precede(Task from, Task to) {
-  from._node->_precede(to._node);
-}
-
-// Procedure: broadcast
-inline void FlowBuilder::broadcast(Task from, std::vector<Task>& tos) {
-  for(auto to : tos) {
-    from.precede(to);
-  }
-}
-
-// Procedure: broadcast
-inline void FlowBuilder::broadcast(Task from, std::initializer_list<Task> tos) {
-  for(auto to : tos) {
-    from.precede(to);
-  }
-}
-
-// Function: succeed
-inline void FlowBuilder::succeed(std::vector<Task>& froms, Task to) {
-  for(auto from : froms) {
-    to.succeed(from);
-  }
-}
-
-// Function: succeed
-inline void FlowBuilder::succeed(std::initializer_list<Task> froms, Task to) {
-  for(auto from : froms) {
-    to.succeed(from);
-  }
-}
-
-// Function: placeholder
-inline Task FlowBuilder::placeholder() {
-  auto node = _graph.emplace_back();
-  return Task(node);
-}
-
-// Function: parallel_for
-template <typename I, typename C>
-std::pair<Task, Task> FlowBuilder::parallel_for(
-  I beg, I end, C&& c, size_t chunk
-){
-  
-  //using category = typename std::iterator_traits<I>::iterator_category;
-  
-  auto S = placeholder();
-  auto T = placeholder();
-  
-  // default partition equals to the worker count
-  if(chunk == 0) {
-    chunk = 1;
-  }
-
-  size_t remain = std::distance(beg, end);
-
-  while(beg != end) {
-
-    auto e = beg;
-    
-    auto x = std::min(remain, chunk);
-    std::advance(e, x);
-    remain -= x;
-      
-    // Create a task
-    auto task = emplace([beg, e, c] () mutable {
-      std::for_each(beg, e, c);
-    });
-
-    S.precede(task);
-    task.precede(T);
-
-    // adjust the pointer
-    beg = e;
-  }
-  
-  // special case
-  if(S.num_successors() == 0) {
-    S.precede(T);
-  }
-  
-  return std::make_pair(S, T); 
-}
-
-// Function: parallel_for
-template <
-  typename I, 
-  typename C, 
-  std::enable_if_t<std::is_integral<std::decay_t<I>>::value, void>*
->
-std::pair<Task, Task> FlowBuilder::parallel_for(I beg, I end, I s, C&& c, size_t chunk) {
-  
-  if((s == 0) || (beg < end && s <= 0) || (beg > end && s >=0) ) {
-    TF_THROW("invalid range [", beg, ", ", end, ") with step size ", s);
-  }
-
-  // source and target 
-  auto source = placeholder();
-  auto target = placeholder();
-  
-  if(chunk == 0) {
-    chunk = 1;
-  }
-
-  // positive case
-  if(beg < end) {
-    while(beg != end) {
-      auto o = static_cast<I>(chunk) * s;
-      auto e = std::min(beg + o, end);
-      auto task = emplace([=] () mutable {
-        for(auto i=beg; i<e; i+=s) {
-          c(i);
-        }
-      });
-      source.precede(task);
-      task.precede(target);
-      beg = e;
-    }
-  }
-  // negative case
-  else if(beg > end) {
-    while(beg != end) {
-      auto o = static_cast<I>(chunk) * s;
-      auto e = std::max(beg + o, end);
-      auto task = emplace([=] () mutable {
-        for(auto i=beg; i>e; i+=s) {
-          c(i);
-        }
-      });
-      source.precede(task);
-      task.precede(target);
-      beg = e;
-    }
-  }
-
-  if(source.num_successors() == 0) {
-    source.precede(target);
-  }
-    
-  return std::make_pair(source, target);
-}
-
-// Function: parallel_for
-template <typename I, typename C, 
-  std::enable_if_t<std::is_floating_point<std::decay_t<I>>::value, void>*
->
-std::pair<Task, Task> FlowBuilder::parallel_for(I beg, I end, I s, C&& c, size_t chunk) {
-  
-  if((s == 0) || (beg < end && s <= 0) || (beg > end && s >=0) ) {
-    TF_THROW("invalid range [", beg, ", ", end, ") with step size ", s);
-  }
-
-  // source and target 
-  auto source = placeholder();
-  auto target = placeholder();
-  
-  if(chunk == 0) {
-    chunk = 1;
-  }
-
-  // positive case
-  if(beg < end) {
-    size_t N=0;
-    I b = beg;
-    for(I e=beg; e<end; e+=s) {
-      if(++N == chunk) {
-        auto task = emplace([=] () mutable {
-          for(size_t i=0; i<N; ++i, b+=s) {
-            c(b);
-          }
-        });
-        source.precede(task);
-        task.precede(target);
-        N = 0;
-        b = e;
-      }
-    }
-
-    if(N) {
-      auto task = emplace([=] () mutable {
-        for(size_t i=0; i<N; ++i, b+=s) {
-          c(b);
-        }
-      });
-      source.precede(task);
-      task.precede(target);
-    }
-  }
-  else if(beg > end) {
-    size_t N=0;
-    I b = beg;
-    for(I e=beg; e>end; e+=s) {
-      if(++N == chunk) {
-        auto task = emplace([=] () mutable {
-          for(size_t i=0; i<N; ++i, b+=s) {
-            c(b);
-          }
-        });
-        source.precede(task);
-        task.precede(target);
-        N = 0;
-        b = e;
-      }
-    }
-
-    if(N) {
-      auto task = emplace([=] () mutable {
-        for(size_t i=0; i<N; ++i, b+=s) {
-          c(b);
-        }
-      });
-      source.precede(task);
-      task.precede(target);
-    }
-  }
-
-  if(source.num_successors() == 0) {
-    source.precede(target);
-  }
-    
-  return std::make_pair(source, target);
-}
-
-// Function: reduce_min
-// Find the minimum element over a range of items.
-template <typename I, typename T>
-std::pair<Task, Task> FlowBuilder::reduce_min(I beg, I end, T& result) {
-  return reduce(beg, end, result, [] (const auto& l, const auto& r) {
-    return std::min(l, r);
-  });
-}
-
-// Function: reduce_max
-// Find the maximum element over a range of items.
-template <typename I, typename T>
-std::pair<Task, Task> FlowBuilder::reduce_max(I beg, I end, T& result) {
-  return reduce(beg, end, result, [] (const auto& l, const auto& r) {
-    return std::max(l, r);
-  });
-}
-
-// Function: transform_reduce    
-template <typename I, typename T, typename B, typename U>
-std::pair<Task, Task> FlowBuilder::transform_reduce(
-  I beg, I end, T& result, B&& bop, U&& uop
-) {
-
-  //using category = typename std::iterator_traits<I>::iterator_category;
-  
-  // Even partition
-  size_t d = std::distance(beg, end);
-  size_t w = std::max(unsigned{1}, std::thread::hardware_concurrency());
-  size_t g = std::max((d + w - 1) / w, size_t{2});
-
-  auto source = placeholder();
-  auto target = placeholder();
-
-  //std::vector<std::future<T>> futures;
-  auto g_results = std::make_unique<T[]>(w);
-  size_t id {0};
-
-  size_t remain = d;
-
-  while(beg != end) {
-
-    auto e = beg;
-    
-    size_t x = std::min(remain, g);
-    std::advance(e, x);
-    remain -= x;
-
-    // Create a task 
-    auto task = emplace([beg, e, bop, uop, res=&(g_results[id])] () mutable {
-      *res = uop(*beg);
-      for(++beg; beg != e; ++beg) {
-        *res = bop(std::move(*res), uop(*beg));          
-      }
-    });
-
-    source.precede(task);
-    task.precede(target);
-
-    // adjust the pointer
-    beg = e;
-    id ++;
-  }
-
-  // target synchronizer 
-  target.work([&result, bop, res=make_moc(std::move(g_results)), w=id] () {
-    for(auto i=0u; i<w; i++) {
-      result = bop(std::move(result), res.object[i]);
-    }
-  });
-
-  return std::make_pair(source, target); 
-}
-
-// Function: transform_reduce    
-template <typename I, typename T, typename B, typename P, typename U>
-std::pair<Task, Task> FlowBuilder::transform_reduce(
-  I beg, I end, T& result, B&& bop, P&& pop, U&& uop
-) {
-
-  //using category = typename std::iterator_traits<I>::iterator_category;
-  
-  // Even partition
-  size_t d = std::distance(beg, end);
-  size_t w = std::max(unsigned{1}, std::thread::hardware_concurrency());
-  size_t g = std::max((d + w - 1) / w, size_t{2});
-
-  auto source = placeholder();
-  auto target = placeholder();
-
-  auto g_results = std::make_unique<T[]>(w);
-
-  size_t id {0};
-  size_t remain = d;
-
-  while(beg != end) {
-
-    auto e = beg;
-    
-    size_t x = std::min(remain, g);
-    std::advance(e, x);
-    remain -= x;
-      
-    // Create a task 
-    auto task = emplace([beg, e, uop, pop,  res= &g_results[id]] () mutable {
-      *res = uop(*beg);
-      for(++beg; beg != e; ++beg) {
-        *res = pop(std::move(*res), *beg);
-      }
-    });
-    source.precede(task);
-    task.precede(target);
-
-    // adjust the pointer
-    beg = e;
-    id ++;
-  }
-
-  // target synchronizer 
-  target.work([&result, bop, g_results=make_moc(std::move(g_results)), w=id] () {
-    for(auto i=0u; i<w; i++) {
-      result = bop(std::move(result), std::move(g_results.object[i]));
-    }
-  });
-
-  return std::make_pair(source, target); 
-}
-
-// Procedure: _linearize
-template <typename L>
-void FlowBuilder::_linearize(L& keys) {
-
-  auto itr = keys.begin();
-  auto end = keys.end();
-
-  if(itr == end) {
-    return;
-  }
-
-  auto nxt = itr;
-
-  for(++nxt; nxt != end; ++nxt, ++itr) {
-    itr->_node->_precede(nxt->_node);
-  }
-}
-
-// Procedure: linearize
-inline void FlowBuilder::linearize(std::vector<Task>& keys) {
-  _linearize(keys); 
-}
-
-// Procedure: linearize
-inline void FlowBuilder::linearize(std::initializer_list<Task> keys) {
-  _linearize(keys);
-}
-
-// Proceduer: reduce
-template <typename I, typename T, typename B>
-std::pair<Task, Task> FlowBuilder::reduce(I beg, I end, T& result, B&& op) {
-  
-  //using category = typename std::iterator_traits<I>::iterator_category;
-  
-  size_t d = std::distance(beg, end);
-  size_t w = std::max(unsigned{1}, std::thread::hardware_concurrency());
-  size_t g = std::max((d + w - 1) / w, size_t{2});
-
-  auto source = placeholder();
-  auto target = placeholder();
-
-  //T* g_results = static_cast<T*>(malloc(sizeof(T)*w));
-  auto g_results = std::make_unique<T[]>(w);
-  //std::vector<std::future<T>> futures;
-  
-  size_t id {0};
-  size_t remain = d;
-
-  while(beg != end) {
-
-    auto e = beg;
-    
-    size_t x = std::min(remain, g);
-    std::advance(e, x);
-    remain -= x;
-    
-    // Create a task
-    //auto [task, future] = emplace([beg, e, op] () mutable {
-    auto task = emplace([beg, e, op, res = &g_results[id]] () mutable {
-      *res = *beg;
-      for(++beg; beg != e; ++beg) {
-        *res = op(std::move(*res), *beg);          
-      }
-      //auto init = *beg;
-      //for(++beg; beg != e; ++beg) {
-      //  init = op(std::move(init), *beg);          
-      //}
-      //return init;
-    });
-    source.precede(task);
-    task.precede(target);
-    //futures.push_back(std::move(future));
-
-    // adjust the pointer
-    beg = e;
-    id ++;
-  }
-  
-  // target synchronizer
-  //target.work([&result, futures=MoC{std::move(futures)}, op] () {
-  //  for(auto& fu : futures.object) {
-  //    result = op(std::move(result), fu.get());
-  //  }
-  //});
-  target.work([g_results=make_moc(std::move(g_results)), &result, op, w=id] () {
-    for(auto i=0u; i<w; i++) {
-      result = op(std::move(result), g_results.object[i]);
-    }
-  });
-
-  return std::make_pair(source, target); 
-}
-
-// ----------------------------------------------------------------------------
-
-/** 
-@class Subflow
-
-@brief building methods of a subflow graph in dynamic tasking
-
-By default, a subflow automatically joins its parent node. You may explicitly
-join or detach a subflow by calling Subflow::join or Subflow::detach.
-
-*/ 
-class Subflow : public FlowBuilder {
-
-  friend class Executor;
-
-  public:
-    
-    /**
-    @brief enables the subflow to join its parent task
-
-    Performs an immediate action to join the subflow. Once the subflow is joined,
-    it is considered finished and you may not apply any other actions to it.
-    */
-    void join();
-
-    /**
-    @brief enables the subflow to detach from its parent task
-
-    A joined subflow cannot be detached. The subflow will be detached upon leaving
-    its execution context.
-    */
-    void detach();
-    
-    /**
-    @brief queries if the subflow will be detached from its parent task
-    */
-    bool detached() const;
-
-    /**
-    @brief queries if the subflow is joinable
-
-    When a subflow is joined, it becomes not joinable.
-    */
-    bool joinable() const;
-
-  private:
-    
-    Subflow(Executor&, Node*, Graph&);
-
-    Executor& _executor;
-    Node* _parent;
-
-    bool _joined {false};
-    bool _detach {false};
-};
-
-// Constructor
-inline Subflow::Subflow(Executor& executor, Node* parent, Graph& graph) :
-  FlowBuilder {graph},
-  _executor   {executor},
-  _parent     {parent} {
-}
-
-// Procedure: detach
-inline void Subflow::detach() {
-  if(_joined) {
-    TF_THROW("subflow already joined");
-  }
-  _detach = true;
-}
-
-// Function: detached
-inline bool Subflow::detached() const {
-  return _detach;
-}
-
-// Function: joined
-inline bool Subflow::joinable() const {
-  return !_joined;
-}
-
-
-// ----------------------------------------------------------------------------
-// Legacy code
-// ----------------------------------------------------------------------------
-
-using SubflowBuilder = Subflow;
-
-}  // end of namespace tf. ---------------------------------------------------
-
-
diff --git a/bundled/taskflow-2.5.0/include/taskflow/core/graph.hpp b/bundled/taskflow-2.5.0/include/taskflow/core/graph.hpp
deleted file mode 100644 (file)
index af258ec..0000000
+++ /dev/null
@@ -1,528 +0,0 @@
-#pragma once
-
-#include "error.hpp"
-#include "../declarations.hpp"
-#include "../utility/object_pool.hpp"
-#include "../utility/traits.hpp"
-#include "../utility/passive_vector.hpp"
-#include "../utility/singleton.hpp"
-#include "../utility/uuid.hpp"
-#include "../utility/os.hpp"
-#include "../nstd/variant.hpp"
-
-#if defined(__CUDA__) || defined(__CUDACC__)
-#define TF_ENABLE_CUDA
-#include "../cuda/cuda_flow.hpp"
-#endif
-
-namespace tf {
-
-// ----------------------------------------------------------------------------
-// domain
-// ----------------------------------------------------------------------------
-
-enum Domain : int {
-  HOST = 0,
-#ifdef TF_ENABLE_CUDA
-  CUDA,
-#endif
-  NUM_DOMAINS
-};
-
-
-// ----------------------------------------------------------------------------
-// Class: Graph
-// ----------------------------------------------------------------------------
-class Graph {
-
-  friend class Node;
-  friend class Taskflow;
-  friend class Executor;
-
-  public:
-
-    Graph() = default;
-    Graph(const Graph&) = delete;
-    Graph(Graph&&);
-
-    ~Graph();
-
-    Graph& operator = (const Graph&) = delete;
-    Graph& operator = (Graph&&);
-    
-    void clear();
-
-    bool empty() const;
-
-    size_t size() const;
-    
-    template <typename ...Args>
-    Node* emplace_back(Args&& ...); 
-
-    Node* emplace_back();
-
-  private:
-
-    static ObjectPool<Node>& _node_pool();
-    
-    std::vector<Node*> _nodes;
-};
-
-// ----------------------------------------------------------------------------
-
-// Class: Node
-class Node {
-
-  friend class Task;
-  friend class TaskView;
-  friend class Topology;
-  friend class Taskflow;
-  friend class Executor;
-  friend class FlowBuilder;
-  friend class Subflow;
-
-  TF_ENABLE_POOLABLE_ON_THIS;
-
-  // state bit flag
-  constexpr static int BRANCH  = 0x1;
-  
-  // static work handle
-  struct StaticWork {
-
-    template <typename C> 
-    StaticWork(C&&);
-
-    std::function<void()> work;
-  };
-
-  // dynamic work handle
-  struct DynamicWork {
-
-    template <typename C> 
-    DynamicWork(C&&);
-
-    std::function<void(Subflow&)> work;
-    Graph subgraph;
-  };
-  
-  // condition work handle
-  struct ConditionWork {
-
-    template <typename C> 
-    ConditionWork(C&&);
-
-    std::function<int()> work;
-  };
-
-  // module work handle
-  struct ModuleWork {
-
-    template <typename T>
-    ModuleWork(T&&);
-
-    Taskflow* module {nullptr};
-  };
-  
-  // cudaFlow work handle
-#ifdef TF_ENABLE_CUDA
-  struct cudaFlowWork {
-    
-    template <typename C> 
-    cudaFlowWork(C&& c) : work {std::forward<C>(c)} {}
-
-    std::function<void(cudaFlow&)> work;
-
-    cudaGraph graph;
-  };
-#endif
-    
-  using handle_t = nstd::variant<
-    nstd::monostate,  // placeholder
-#ifdef TF_ENABLE_CUDA
-    cudaFlowWork,     // cudaFlow
-#endif
-    StaticWork,       // static tasking
-    DynamicWork,      // dynamic tasking
-    ConditionWork,    // conditional tasking
-    ModuleWork        // composable tasking
-  >;
-  
-  public:
-  
-  // variant index
-  constexpr static auto PLACEHOLDER_WORK = get_index_v<nstd::monostate, handle_t>;
-  constexpr static auto STATIC_WORK      = get_index_v<StaticWork, handle_t>;
-  constexpr static auto DYNAMIC_WORK     = get_index_v<DynamicWork, handle_t>;
-  constexpr static auto CONDITION_WORK   = get_index_v<ConditionWork, handle_t>; 
-  constexpr static auto MODULE_WORK      = get_index_v<ModuleWork, handle_t>; 
-
-#ifdef TF_ENABLE_CUDA
-  constexpr static auto CUDAFLOW_WORK  = get_index_v<cudaFlowWork, handle_t>; 
-#endif
-
-    template <typename ...Args>
-    Node(Args&&... args);
-
-    ~Node();
-
-    size_t num_successors() const;
-    size_t num_dependents() const;
-    size_t num_strong_dependents() const;
-    size_t num_weak_dependents() const;
-    
-    const std::string& name() const;
-
-    Domain domain() const;
-
-  private:
-
-    std::string _name;
-
-    handle_t _handle;
-
-    PassiveVector<Node*> _successors;
-    PassiveVector<Node*> _dependents;
-
-    Topology* _topology {nullptr};
-    
-    Node* _parent {nullptr};
-
-    int _state {0};
-
-    std::atomic<size_t> _join_counter {0};
-    
-    void _precede(Node*);
-    void _set_state(int);
-    void _unset_state(int);
-    void _clear_state();
-    void _set_up_join_counter();
-
-    bool _has_state(int) const;
-
-};
-
-// ----------------------------------------------------------------------------
-// Definition for Node::StaticWork
-// ----------------------------------------------------------------------------
-    
-// Constructor
-template <typename C> 
-Node::StaticWork::StaticWork(C&& c) : work {std::forward<C>(c)} {
-}
-
-// ----------------------------------------------------------------------------
-// Definition for Node::DynamicWork
-// ----------------------------------------------------------------------------
-    
-// Constructor
-template <typename C> 
-Node::DynamicWork::DynamicWork(C&& c) : work {std::forward<C>(c)} {
-}
-
-// ----------------------------------------------------------------------------
-// Definition for Node::ConditionWork
-// ----------------------------------------------------------------------------
-    
-// Constructor
-template <typename C> 
-Node::ConditionWork::ConditionWork(C&& c) : work {std::forward<C>(c)} {
-}
-
-// ----------------------------------------------------------------------------
-// Definition for Node::ModuleWork
-// ----------------------------------------------------------------------------
-    
-// Constructor
-template <typename T>
-Node::ModuleWork::ModuleWork(T&& tf) : module {tf} {
-}
-
-// ----------------------------------------------------------------------------
-// Definition for Node
-// ----------------------------------------------------------------------------
-
-// Constructor
-template <typename ...Args>
-Node::Node(Args&&... args): _handle{std::forward<Args>(args)...} {
-} 
-
-// Destructor
-inline Node::~Node() {
-  // this is to avoid stack overflow
-
-  if(_handle.index() == DYNAMIC_WORK) {
-
-    auto& subgraph = nstd::get<DynamicWork>(_handle).subgraph;
-
-    std::vector<Node*> nodes;
-
-    std::move(
-     subgraph._nodes.begin(), subgraph._nodes.end(), std::back_inserter(nodes)
-    );
-    subgraph._nodes.clear();
-
-    size_t i = 0;
-
-    while(i < nodes.size()) {
-
-      if(nodes[i]->_handle.index() == DYNAMIC_WORK) {
-
-        auto& sbg = nstd::get<DynamicWork>(nodes[i]->_handle).subgraph;
-        std::move(
-          sbg._nodes.begin(), sbg._nodes.end(), std::back_inserter(nodes)
-        );
-        sbg._nodes.clear();
-      }
-
-      ++i;
-    }
-      
-    auto& np = Graph::_node_pool();
-    for(i=0; i<nodes.size(); ++i) {
-      //nodes[i]->~Node();
-      //np.deallocate(nodes[i]);
-      np.recycle(nodes[i]);
-    }
-  }
-}
-
-// Procedure: _precede
-inline void Node::_precede(Node* v) {
-  _successors.push_back(v);
-  v->_dependents.push_back(this);
-}
-
-// Function: num_successors
-inline size_t Node::num_successors() const {
-  return _successors.size();
-}
-
-// Function: dependents
-inline size_t Node::num_dependents() const {
-  return _dependents.size();
-}
-
-// Function: num_weak_dependents
-inline size_t Node::num_weak_dependents() const {
-  return std::count_if(
-    _dependents.begin(), 
-    _dependents.end(), 
-    [](Node* node){ return node->_handle.index() == Node::CONDITION_WORK; } 
-  );
-}
-
-// Function: num_strong_dependents
-inline size_t Node::num_strong_dependents() const {
-  return std::count_if(
-    _dependents.begin(), 
-    _dependents.end(), 
-    [](Node* node){ return node->_handle.index() != Node::CONDITION_WORK; } 
-  );
-}
-
-// Function: name
-inline const std::string& Node::name() const {
-  return _name;
-}
-
-// Function: domain
-inline Domain Node::domain() const {
-
-  Domain domain;
-
-  switch(_handle.index()) {
-
-    case STATIC_WORK:
-    case DYNAMIC_WORK:
-    case CONDITION_WORK:
-    case MODULE_WORK:
-      domain = Domain::HOST;
-    break;
-
-#ifdef TF_ENABLE_CUDA
-    case CUDAFLOW_WORK:
-      domain = Domain::CUDA;
-    break;
-#endif
-
-    default:
-      domain = Domain::HOST;
-    break;
-  }
-
-  return domain;
-}
-
-//
-//// Function: dump
-//inline std::string Node::dump() const {
-//  std::ostringstream os;  
-//  dump(os);
-//  return os.str();
-//}
-//
-//// Function: dump
-//inline void Node::dump(std::ostream& os) const {
-//
-//  os << 'p' << this << "[label=\"";
-//  if(_name.empty()) os << 'p' << this;
-//  else os << _name;
-//  os << "\" ";
-//
-//  // condition node is colored green
-//  if(_handle.index() == CONDITION_WORK) {
-//    os << " shape=diamond color=black fillcolor=aquamarine style=filled";
-//  }
-//
-//  os << "];\n";
-//  
-//  for(size_t s=0; s<_successors.size(); ++s) {
-//    if(_handle.index() == CONDITION_WORK) {
-//      // case edge is dashed
-//      os << 'p' << this << " -> p" << _successors[s] 
-//         << " [style=dashed label=\"" << s << "\"];\n";
-//    }
-//    else {
-//      os << 'p' << this << " -> p" << _successors[s] << ";\n";
-//    }
-//  }
-//  
-//  // subflow join node
-//  if(_parent && _successors.size() == 0) {
-//    os << 'p' << this << " -> p" << _parent << ";\n";
-//  }
-//  
-//  if(_subgraph && !_subgraph->empty()) {
-//
-//    os << "subgraph cluster_p" << this << " {\nlabel=\"Subflow: ";
-//    if(_name.empty()) os << 'p' << this;
-//    else os << _name;
-//
-//    os << "\";\n" << "color=blue\n";
-//
-//    for(const auto& n : _subgraph->nodes()) {
-//      n->dump(os);
-//    }
-//    os << "}\n";
-//  }
-//}
-    
-// Procedure: _set_state
-inline void Node::_set_state(int flag) { 
-  _state |= flag; 
-}
-
-// Procedure: _unset_state
-inline void Node::_unset_state(int flag) { 
-  _state &= ~flag; 
-}
-
-// Procedure: _clear_state
-inline void Node::_clear_state() { 
-  _state = 0; 
-}
-
-// Procedure: _set_up_join_counter
-inline void Node::_set_up_join_counter() {
-
-  int c = 0;
-
-  for(auto p : _dependents) {
-    if(p->_handle.index() == Node::CONDITION_WORK) {
-      _set_state(Node::BRANCH);
-    }
-    else {
-      c++;
-    }
-  }
-
-  _join_counter.store(c, std::memory_order_relaxed);
-}
-
-// Function: _has_state
-inline bool Node::_has_state(int flag) const {
-  return _state & flag;
-}
-
-// ----------------------------------------------------------------------------
-// Graph definition
-// ----------------------------------------------------------------------------
-    
-// Function: _node_pool
-inline ObjectPool<Node>& Graph::_node_pool() {
-  static ObjectPool<Node> pool;
-  return pool;
-}
-
-// Destructor
-inline Graph::~Graph() {
-  auto& np = _node_pool();
-  for(auto node : _nodes) {
-    //node->~Node();
-    //np.deallocate(node);
-    np.recycle(node);
-  }
-}
-
-// Move constructor
-inline Graph::Graph(Graph&& other) : 
-  _nodes {std::move(other._nodes)} {
-}
-
-// Move assignment
-inline Graph& Graph::operator = (Graph&& other) {
-  _nodes = std::move(other._nodes);
-  return *this;
-}
-
-// Procedure: clear
-inline void Graph::clear() {
-  auto& np = _node_pool();
-  for(auto node : _nodes) {
-    //node->~Node();
-    //np.deallocate(node);
-    np.recycle(node);
-  }
-  _nodes.clear();
-}
-
-// Function: size
-// query the size
-inline size_t Graph::size() const {
-  return _nodes.size();
-}
-
-// Function: empty
-// query the emptiness
-inline bool Graph::empty() const {
-  return _nodes.empty();
-}
-    
-// Function: emplace_back
-// create a node from a give argument; constructor is called if necessary
-template <typename ...ArgsT>
-Node* Graph::emplace_back(ArgsT&&... args) {
-  //auto node = _node_pool().allocate();
-  //new (node) Node(std::forward<ArgsT>(args)...);
-  //_nodes.push_back(node);
-  _nodes.push_back(_node_pool().animate(std::forward<ArgsT>(args)...));
-  return _nodes.back();
-}
-
-// Function: emplace_back
-// create a node from a give argument; constructor is called if necessary
-inline Node* Graph::emplace_back() {
-  //auto node = _node_pool().allocate();
-  //new (node) Node();
-  //_nodes.push_back(node);
-  _nodes.push_back(_node_pool().animate());
-  return _nodes.back();
-}
-
-
-}  // end of namespace tf. ---------------------------------------------------
-
-
-
-
-
diff --git a/bundled/taskflow-2.5.0/include/taskflow/core/notifier.hpp b/bundled/taskflow-2.5.0/include/taskflow/core/notifier.hpp
deleted file mode 100644 (file)
index b3bdb9f..0000000
+++ /dev/null
@@ -1,274 +0,0 @@
-// 2019/02/09 - created by Tsung-Wei Huang
-//  - modified the event count from Eigen
-
-#pragma once
-
-#include <iostream>
-#include <vector>
-#include <cstdlib>
-#include <cstdio>
-#include <atomic>
-#include <memory>
-#include <deque>
-#include <mutex>
-#include <condition_variable>
-#include <thread>
-#include <algorithm>
-#include <numeric>
-#include <cassert>
-
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2016 Dmitry Vyukov <dvyukov@google.com>
-//
-// 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/.
-
-namespace tf {
-
-// Notifier allows to wait for arbitrary predicates in non-blocking
-// algorithms. Think of condition variable, but wait predicate does not need to
-// be protected by a mutex. Usage:
-// Waiting thread does:
-//
-//   if (predicate)
-//     return act();
-//   Notifier::Waiter& w = waiters[my_index];
-//   ec.prepare_wait(&w);
-//   if (predicate) {
-//     ec.cancel_wait(&w);
-//     return act();
-//   }
-//   ec.commit_wait(&w);
-//
-// Notifying thread does:
-//
-//   predicate = true;
-//   ec.notify(true);
-//
-// notify is cheap if there are no waiting threads. prepare_wait/commit_wait are not
-// cheap, but they are executed only if the preceeding predicate check has
-// failed.
-//
-// Algorihtm outline:
-// There are two main variables: predicate (managed by user) and _state.
-// Operation closely resembles Dekker mutual algorithm:
-// https://en.wikipedia.org/wiki/Dekker%27s_algorithm
-// Waiting thread sets _state then checks predicate, Notifying thread sets
-// predicate then checks _state. Due to seq_cst fences in between these
-// operations it is guaranteed than either waiter will see predicate change
-// and won't block, or notifying thread will see _state change and will unblock
-// the waiter, or both. But it can't happen that both threads don't see each
-// other changes, which would lead to deadlock.
-class Notifier {
-
-  friend class Executor;
-
-  public:
-  
-  struct Waiter {
-    std::atomic<Waiter*> next;
-    std::mutex mu;
-    std::condition_variable cv;
-    uint64_t epoch;
-    unsigned state;
-    enum {
-      kNotSignaled,
-      kWaiting,
-      kSignaled,
-    };
-  };
-
-  explicit Notifier(size_t N) : _waiters{N} {
-    assert(_waiters.size() < (1 << kWaiterBits) - 1);
-    // Initialize epoch to something close to overflow to test overflow.
-    _state = kStackMask | (kEpochMask - kEpochInc * _waiters.size() * 2);
-  }
-
-  ~Notifier() {
-    // Ensure there are no waiters.
-    assert((_state.load() & (kStackMask | kWaiterMask)) == kStackMask);
-  }
-
-  // prepare_wait prepares for waiting.
-  // After calling this function the thread must re-check the wait predicate
-  // and call either cancel_wait or commit_wait passing the same Waiter object.
-  void prepare_wait(Waiter* w) {
-    w->epoch = _state.fetch_add(kWaiterInc, std::memory_order_relaxed);
-    std::atomic_thread_fence(std::memory_order_seq_cst);
-  }
-
-  // commit_wait commits waiting.
-  void commit_wait(Waiter* w) {
-    w->state = Waiter::kNotSignaled;
-    // Modification epoch of this waiter.
-    uint64_t epoch =
-        (w->epoch & kEpochMask) +
-        (((w->epoch & kWaiterMask) >> kWaiterShift) << kEpochShift);
-    uint64_t state = _state.load(std::memory_order_seq_cst);
-    for (;;) {
-      if (int64_t((state & kEpochMask) - epoch) < 0) {
-        // The preceeding waiter has not decided on its fate. Wait until it
-        // calls either cancel_wait or commit_wait, or is notified.
-        std::this_thread::yield();
-        state = _state.load(std::memory_order_seq_cst);
-        continue;
-      }
-      // We've already been notified.
-      if (int64_t((state & kEpochMask) - epoch) > 0) return;
-      // Remove this thread from prewait counter and add it to the waiter list.
-      assert((state & kWaiterMask) != 0);
-      uint64_t newstate = state - kWaiterInc + kEpochInc;
-      newstate = (newstate & ~kStackMask) | (w - &_waiters[0]);
-      if ((state & kStackMask) == kStackMask)
-        w->next.store(nullptr, std::memory_order_relaxed);
-      else
-        w->next.store(&_waiters[state & kStackMask], std::memory_order_relaxed);
-      if (_state.compare_exchange_weak(state, newstate,
-                                       std::memory_order_release))
-        break;
-    }
-    _park(w);
-  }
-
-  // cancel_wait cancels effects of the previous prepare_wait call.
-  void cancel_wait(Waiter* w) {
-    uint64_t epoch =
-        (w->epoch & kEpochMask) +
-        (((w->epoch & kWaiterMask) >> kWaiterShift) << kEpochShift);
-    uint64_t state = _state.load(std::memory_order_relaxed);
-    for (;;) {
-      if (int64_t((state & kEpochMask) - epoch) < 0) {
-        // The preceeding waiter has not decided on its fate. Wait until it
-        // calls either cancel_wait or commit_wait, or is notified.
-        std::this_thread::yield();
-        state = _state.load(std::memory_order_relaxed);
-        continue;
-      }
-      // We've already been notified.
-      if (int64_t((state & kEpochMask) - epoch) > 0) return;
-      // Remove this thread from prewait counter.
-      assert((state & kWaiterMask) != 0);
-      if (_state.compare_exchange_weak(state, state - kWaiterInc + kEpochInc,
-                                       std::memory_order_relaxed))
-        return;
-    }
-  }
-
-  // notify wakes one or all waiting threads.
-  // Must be called after changing the associated wait predicate.
-  void notify(bool all) {
-    std::atomic_thread_fence(std::memory_order_seq_cst);
-    uint64_t state = _state.load(std::memory_order_acquire);
-    for (;;) {
-      // Easy case: no waiters.
-      if ((state & kStackMask) == kStackMask && (state & kWaiterMask) == 0)
-        return;
-      uint64_t waiters = (state & kWaiterMask) >> kWaiterShift;
-      uint64_t newstate;
-      if (all) {
-        // Reset prewait counter and empty wait list.
-        newstate = (state & kEpochMask) + (kEpochInc * waiters) + kStackMask;
-      } else if (waiters) {
-        // There is a thread in pre-wait state, unblock it.
-        newstate = state + kEpochInc - kWaiterInc;
-      } else {
-        // Pop a waiter from list and unpark it.
-        Waiter* w = &_waiters[state & kStackMask];
-        Waiter* wnext = w->next.load(std::memory_order_relaxed);
-        uint64_t next = kStackMask;
-        if (wnext != nullptr) next = wnext - &_waiters[0];
-        // Note: we don't add kEpochInc here. ABA problem on the lock-free stack
-        // can't happen because a waiter is re-pushed onto the stack only after
-        // it was in the pre-wait state which inevitably leads to epoch
-        // increment.
-        newstate = (state & kEpochMask) + next;
-      }
-      if (_state.compare_exchange_weak(state, newstate,
-                                       std::memory_order_acquire)) {
-        if (!all && waiters) return;  // unblocked pre-wait thread
-        if ((state & kStackMask) == kStackMask) return;
-        Waiter* w = &_waiters[state & kStackMask];
-        if (!all) w->next.store(nullptr, std::memory_order_relaxed);
-        _unpark(w);
-        return;
-      }
-    }
-  }
-  
-  // notify n workers
-  void notify_n(size_t n) {
-    if(n >= _waiters.size()) {
-      notify(true);
-    }
-    else {
-      for(size_t k=0; k<n; ++k) {
-        notify(false);
-      }
-    }
-  }
-
-  size_t size() const {
-    return _waiters.size();
-  }
-
- private:
-
-  // State_ layout:
-  // - low kStackBits is a stack of waiters committed wait.
-  // - next kWaiterBits is count of waiters in prewait state.
-  // - next kEpochBits is modification counter.
-  static const uint64_t kStackBits = 16;
-  static const uint64_t kStackMask = (1ull << kStackBits) - 1;
-  static const uint64_t kWaiterBits = 16;
-  static const uint64_t kWaiterShift = 16;
-  static const uint64_t kWaiterMask = ((1ull << kWaiterBits) - 1)
-                                      << kWaiterShift;
-  static const uint64_t kWaiterInc = 1ull << kWaiterBits;
-  static const uint64_t kEpochBits = 32;
-  static const uint64_t kEpochShift = 32;
-  static const uint64_t kEpochMask = ((1ull << kEpochBits) - 1) << kEpochShift;
-  static const uint64_t kEpochInc = 1ull << kEpochShift;
-  std::atomic<uint64_t> _state;
-  std::vector<Waiter> _waiters;
-
-  void _park(Waiter* w) {
-    std::unique_lock<std::mutex> lock(w->mu);
-    while (w->state != Waiter::kSignaled) {
-      w->state = Waiter::kWaiting;
-      w->cv.wait(lock);
-    }
-  }
-
-  void _unpark(Waiter* waiters) {
-    Waiter* next = nullptr;
-    for (Waiter* w = waiters; w; w = next) {
-      next = w->next.load(std::memory_order_relaxed);
-      unsigned state;
-      {
-        std::unique_lock<std::mutex> lock(w->mu);
-        state = w->state;
-        w->state = Waiter::kSignaled;
-      }
-      // Avoid notifying if it wasn't waiting.
-      if (state == Waiter::kWaiting) w->cv.notify_one();
-    }
-  }
-
-  Notifier(const Notifier&) = delete;
-  Notifier& operator=(const Notifier&) = delete;
-
-  Notifier(Notifier&& rhs) : 
-    _state   {rhs._state.load()},
-    _waiters {std::move(rhs._waiters)} {
-  }
-
-  
-};
-
-
-
-}  // namespace tf ------------------------------------------------------------
-
diff --git a/bundled/taskflow-2.5.0/include/taskflow/core/observer.hpp b/bundled/taskflow-2.5.0/include/taskflow/core/observer.hpp
deleted file mode 100644 (file)
index be73a0f..0000000
+++ /dev/null
@@ -1,521 +0,0 @@
-// 2020/04/30 - midified by Tsung-Wei Huang
-//  - adding TaskflowBoard support
-//
-// 2019/07/31 - modified by Tsung-Wei Huang
-//  - fixed the missing comma in outputing JSON  
-//
-// 2019/06/13 - modified by Tsung-Wei Huang
-//  - added TaskView interface
-//
-// 2019/04/17 - created by Tsung-Wei Huang
-
-#pragma once
-
-#include "task.hpp"
-
-namespace tf {
-
-/**
-@class: ObserverInterface
-
-@brief The interface class for creating an executor observer.
-
-The tf::ExecutorObserver class let users define methods to monitor the behaviors
-of an executor. 
-This is particularly useful when you want to inspect the performance of an executor.
-*/
-class ObserverInterface {
-
-  friend class Executor;
-  
-  public:
-
-  /**
-  @brief virtual destructor
-  */
-  virtual ~ObserverInterface() = default;
-  
-  /**
-  @brief constructor-like method to call when the executor observer is fully created
-  @param num_workers the number of the worker threads in the executor
-  */
-  virtual void set_up(size_t num_workers) = 0;
-  
-  /**
-  @brief method to call before a worker thread executes a closure 
-  @param worker_id the id of this worker thread 
-  @param task_view a constant wrapper object to the task 
-  */
-  virtual void on_entry(size_t worker_id, TaskView task_view) = 0;
-  
-  /**
-  @brief method to call after a worker thread executed a closure
-  @param worker_id the id of this worker thread 
-  @param task_view a constant wrapper object to the task
-  */
-  virtual void on_exit(size_t worker_id, TaskView task_view) = 0;
-};
-
-// ----------------------------------------------------------------------------
-// ChromeTracingObserver definition
-// ----------------------------------------------------------------------------
-
-/**
-@class: ChromeTracingObserver
-
-@brief observer designed based on chrome tracing format
-
-*/
-class ChromeTracingObserver : public ObserverInterface {
-
-  friend class Executor;
-  
-  // data structure to record each task execution
-  struct Segment {
-
-    std::string name;
-
-    std::chrono::time_point<std::chrono::steady_clock> beg;
-    std::chrono::time_point<std::chrono::steady_clock> end;
-
-    Segment(
-      const std::string& n,
-      std::chrono::time_point<std::chrono::steady_clock> b
-    );
-
-    Segment(
-      const std::string& n,
-      std::chrono::time_point<std::chrono::steady_clock> b,
-      std::chrono::time_point<std::chrono::steady_clock> e
-    );
-  };
-  
-  // data structure to store the entire execution timeline
-  struct Timeline {
-    std::chrono::time_point<std::chrono::steady_clock> origin;
-    std::vector<std::vector<Segment>> segments;
-    std::vector<std::stack<std::chrono::time_point<std::chrono::steady_clock>>> stacks;
-  };  
-
-  public:
-
-    /**
-    @brief dump the timelines in JSON format to an ostream
-    @param ostream the target std::ostream to dump
-    */
-    inline void dump(std::ostream& ostream) const;
-
-    /**
-    @brief dump the timelines in JSON to a std::string
-    @return a JSON string 
-    */
-    inline std::string dump() const;
-
-    /**
-    @brief clear the timeline data
-    */
-    inline void clear();
-
-    /**
-    @brief get the number of total tasks in the observer
-    @return number of total tasks
-    */
-    inline size_t num_tasks() const;
-
-  private:
-    
-    inline void set_up(size_t num_workers) override final;
-    inline void on_entry(size_t worker_id, TaskView task_view) override final;
-    inline void on_exit(size_t worker_id, TaskView task_view) override final;
-
-    Timeline _timeline;
-};  
-    
-// constructor
-inline ChromeTracingObserver::Segment::Segment(
-  const std::string& n,
-  std::chrono::time_point<std::chrono::steady_clock> b
-) :
-  name {n}, beg {b} {
-} 
-
-// constructor
-inline ChromeTracingObserver::Segment::Segment(
-  const std::string& n,
-  std::chrono::time_point<std::chrono::steady_clock> b,
-  std::chrono::time_point<std::chrono::steady_clock> e
-) :
-  name {n}, beg {b}, end {e} {
-}
-
-// Procedure: set_up
-inline void ChromeTracingObserver::set_up(size_t num_workers) {
-  _timeline.segments.resize(num_workers);
-  _timeline.stacks.resize(num_workers);
-
-  for(size_t w=0; w<num_workers; ++w) {
-    _timeline.segments[w].reserve(32);
-  }
-  
-  _timeline.origin = std::chrono::steady_clock::now();
-}
-
-// Procedure: on_entry
-inline void ChromeTracingObserver::on_entry(size_t w, TaskView) {
-  _timeline.stacks[w].push(std::chrono::steady_clock::now());
-}
-
-// Procedure: on_exit
-inline void ChromeTracingObserver::on_exit(size_t w, TaskView tv) {
-  assert(!_timeline.stacks[w].empty());
-
-  auto beg = _timeline.stacks[w].top();
-  _timeline.stacks[w].pop();
-
-  _timeline.segments[w].emplace_back(
-    tv.name(), beg, std::chrono::steady_clock::now()
-  );
-}
-
-// Function: clear
-inline void ChromeTracingObserver::clear() {
-  for(size_t w=0; w<_timeline.segments.size(); ++w) {
-    _timeline.segments[w].clear();
-    while(!_timeline.stacks[w].empty()) {
-      _timeline.stacks[w].pop();
-    }
-  }
-}
-
-// Procedure: dump
-inline void ChromeTracingObserver::dump(std::ostream& os) const {
-
-  size_t first;
-
-  for(first = 0; first<_timeline.segments.size(); ++first) {
-    if(_timeline.segments[first].size() > 0) { 
-      break; 
-    }
-  }
-
-  os << '[';
-
-  for(size_t w=first; w<_timeline.segments.size(); w++) {
-
-    if(w != first && _timeline.segments[w].size() > 0) {
-      os << ',';
-    }
-
-    for(size_t i=0; i<_timeline.segments[w].size(); i++) {
-
-      os << '{'
-         << "\"cat\":\"ChromeTracingObserver\",";
-
-      // name field
-      os << "\"name\":\"";
-      if(_timeline.segments[w][i].name.empty()) {
-        os << w << '_' << i;
-      }
-      else {
-        os << _timeline.segments[w][i].name;
-      }
-      os << "\",";
-      
-      // segment field
-      os << "\"ph\":\"X\","
-         << "\"pid\":1,"
-         << "\"tid\":" << w << ','
-         << "\"ts\":" << std::chrono::duration_cast<std::chrono::microseconds>(
-                           _timeline.segments[w][i].beg - _timeline.origin
-                         ).count() << ','
-         << "\"dur\":" << std::chrono::duration_cast<std::chrono::microseconds>(
-                           _timeline.segments[w][i].end - _timeline.segments[w][i].beg
-                         ).count();
-
-      if(i != _timeline.segments[w].size() - 1) {
-        os << "},";
-      }
-      else {
-        os << '}';
-      }
-    }
-  }
-  os << "]\n";
-}
-
-// Function: dump
-inline std::string ChromeTracingObserver::dump() const {
-  std::ostringstream oss;
-  dump(oss);
-  return oss.str();
-}
-
-// Function: num_tasks
-inline size_t ChromeTracingObserver::num_tasks() const {
-  return std::accumulate(
-    _timeline.segments.begin(), _timeline.segments.end(), size_t{0}, 
-    [](size_t sum, const auto& exe){ 
-      return sum + exe.size(); 
-    }
-  );
-}
-
-// ----------------------------------------------------------------------------
-// TFProfObserver definition
-// ----------------------------------------------------------------------------
-
-/**
-@class: TFProfObserver
-
-@brief observer designed based on taskflow board format
-
-*/
-class TFProfObserver : public ObserverInterface {
-
-  friend class Executor;
-  
-  // data structure to record each task execution
-  struct Segment {
-
-    std::string name;
-    TaskType type;
-
-    std::chrono::time_point<std::chrono::steady_clock> beg;
-    std::chrono::time_point<std::chrono::steady_clock> end;
-
-    Segment(
-      const std::string& n,
-      TaskType t,
-      std::chrono::time_point<std::chrono::steady_clock> b
-    );
-
-    Segment(
-      const std::string& n,
-      TaskType t,
-      std::chrono::time_point<std::chrono::steady_clock> b,
-      std::chrono::time_point<std::chrono::steady_clock> e
-    );
-  };
-  
-  // data structure to store the entire execution timeline
-  struct Timeline {
-    std::chrono::time_point<std::chrono::steady_clock> origin;
-    std::vector<std::vector<Segment>> segments;
-    std::vector<std::stack<std::chrono::time_point<std::chrono::steady_clock>>> stacks;
-  };  
-
-  public:
-    
-    /**
-    @brief dump the timelines in JSON format to an ostream
-    @param ostream the target std::ostream to dump
-    */
-    inline void dump(std::ostream& ostream) const;
-
-    /**
-    @brief dump the timelines in JSON to a std::string
-    @return a JSON string 
-    */
-    inline std::string dump() const;
-
-    /**
-    @brief clear the timeline data
-    */
-    inline void clear();
-
-    /**
-    @brief get the number of total tasks in the observer
-    @return number of total tasks
-    */
-    inline size_t num_tasks() const;
-
-  private:
-    
-    inline void set_up(size_t num_workers) override final;
-    inline void on_entry(size_t worker_id, TaskView task_view) override final;
-    inline void on_exit(size_t worker_id, TaskView task_view) override final;
-
-    Timeline _timeline;
-
-    UUID _uuid;
-};  
-
-// constructor
-inline TFProfObserver::Segment::Segment(
-  const std::string& n,
-  TaskType t,
-  std::chrono::time_point<std::chrono::steady_clock> b
-) :
-  name {n}, type {t}, beg {b} {
-} 
-
-// constructor
-inline TFProfObserver::Segment::Segment(
-  const std::string& n,
-  TaskType t,
-  std::chrono::time_point<std::chrono::steady_clock> b,
-  std::chrono::time_point<std::chrono::steady_clock> e
-) :
-  name {n}, type {t}, beg {b}, end {e} {
-}
-
-// Procedure: set_up
-inline void TFProfObserver::set_up(size_t num_workers) {
-
-  _timeline.segments.resize(num_workers);
-  _timeline.stacks.resize(num_workers);
-
-  for(size_t w=0; w<num_workers; ++w) {
-    _timeline.segments[w].reserve(32);
-  }
-  
-  _timeline.origin = std::chrono::steady_clock::now();
-}
-
-// Procedure: on_entry
-inline void TFProfObserver::on_entry(size_t w, TaskView) {
-  _timeline.stacks[w].push(std::chrono::steady_clock::now());
-}
-
-// Procedure: on_exit
-inline void TFProfObserver::on_exit(size_t w, TaskView tv) {
-  assert(!_timeline.stacks[w].empty());
-
-  auto beg = _timeline.stacks[w].top();
-  _timeline.stacks[w].pop();
-
-  _timeline.segments[w].emplace_back(
-    tv.name(), tv.type(), beg, std::chrono::steady_clock::now()
-  );
-}
-
-// Function: clear
-inline void TFProfObserver::clear() {
-  for(size_t w=0; w<_timeline.segments.size(); ++w) {
-    _timeline.segments[w].clear();
-    while(!_timeline.stacks[w].empty()) {
-      _timeline.stacks[w].pop();
-    }
-  }
-}
-
-// Procedure: dump
-inline void TFProfObserver::dump(std::ostream& os) const {
-
-  size_t first;
-
-  for(first = 0; first<_timeline.segments.size(); ++first) {
-    if(_timeline.segments[first].size() > 0) { 
-      break; 
-    }
-  }
-  
-  // not timeline data to dump
-  if(first == _timeline.segments.size()) {
-    os << "{}\n";
-    return;
-  }
-
-  os << "{\"executor\":\"" << _uuid << "\",\"data\":[";
-
-  for(size_t w=first; w<_timeline.segments.size(); w++) {
-
-    if(_timeline.segments[w].empty()) {
-      continue;
-    }
-
-    if(w != first) {
-      os << ',';
-    }
-
-    os << "{\"worker\":\"worker " << w << "\",\"data\":[";
-    for(size_t i=0; i<_timeline.segments[w].size(); ++i) {
-
-      const auto& s = _timeline.segments[w][i];
-
-      if(i) os << ',';
-      
-      // span 
-      os << "{\"span\":[" 
-         << std::chrono::duration_cast<std::chrono::microseconds>(
-              s.beg - _timeline.origin
-            ).count() << ","
-         << std::chrono::duration_cast<std::chrono::microseconds>(
-              s.end - _timeline.origin
-            ).count() << "],";
-      
-      // name
-      os << "\"name\":\""; 
-      if(s.name.empty()) {
-        os << w << '_' << i;
-      }
-      else {
-        os << s.name;
-      }
-      os << "\",";
-  
-      // category "type": "Condition Task",
-      os << "\"type\":\"" << task_type_to_string(s.type) << "\"";
-
-      os << "}";
-    }
-    os << "]}";
-  }
-
-  os << "]}\n";
-}
-
-// Function: dump
-inline std::string TFProfObserver::dump() const {
-  std::ostringstream oss;
-  dump(oss);
-  return oss.str();
-}
-
-// Function: num_tasks
-inline size_t TFProfObserver::num_tasks() const {
-  return std::accumulate(
-    _timeline.segments.begin(), _timeline.segments.end(), size_t{0}, 
-    [](size_t sum, const auto& exe){ 
-      return sum + exe.size(); 
-    }
-  );
-}
-
-// ----------------------------------------------------------------------------
-// Identifier for Each Built-in Observer
-// ----------------------------------------------------------------------------
-
-/** @enum ObserverType
-
-built-in observer types
-
-*/
-enum ObserverType {
-  TFPROF = 1,
-  CHROME = 2
-};
-
-/**
-@brief convert an observer type to a human-readable string
-*/
-inline const char* observer_type_to_string(ObserverType type) {
-  const char* val;
-  switch(type) {
-    case TFPROF: val = "TFProf";    break;
-    case CHROME: val = "Chrome";    break;
-    default:     val = "undefined"; break;
-  }
-  return val;
-}
-
-// ----------------------------------------------------------------------------
-// Legacy Alias
-// ----------------------------------------------------------------------------
-using ExecutorObserverInterface = ObserverInterface;
-using ExecutorObserver          = ChromeTracingObserver;
-
-
-}  // end of namespace tf -----------------------------------------------------
-
-
diff --git a/bundled/taskflow-2.5.0/include/taskflow/core/task.hpp b/bundled/taskflow-2.5.0/include/taskflow/core/task.hpp
deleted file mode 100644 (file)
index 589050b..0000000
+++ /dev/null
@@ -1,750 +0,0 @@
-#pragma once
-
-#include "graph.hpp"
-
-namespace tf {
-
-// ----------------------------------------------------------------------------
-// Task Types
-// ----------------------------------------------------------------------------
-
-/**
-@enum TaskType
-
-@brief enumeration of all task types
-*/
-enum TaskType {
-  PLACEHOLDER_TASK = Node::PLACEHOLDER_WORK,
-#ifdef TF_ENABLE_CUDA
-  CUDAFLOW_TASK    = Node::CUDAFLOW_WORK,
-#endif
-  STATIC_TASK      = Node::STATIC_WORK,
-  DYNAMIC_TASK     = Node::DYNAMIC_WORK,
-  CONDITION_TASK   = Node::CONDITION_WORK,
-  MODULE_TASK      = Node::MODULE_WORK,
-  NUM_TASK_TYPES
-};
-
-/**
-@brief convert a task type to a human-readable string
-*/
-inline const char* task_type_to_string(TaskType type) {
-
-  const char* val;
-
-  switch(type) {
-    case PLACEHOLDER_TASK: val = "placeholder"; break;
-#ifdef TF_ENABLE_CUDA
-    case CUDAFLOW_TASK:    val = "cudaflow";    break;
-#endif
-    case STATIC_TASK:      val = "static";      break;
-    case DYNAMIC_TASK:     val = "subflow";     break;
-    case CONDITION_TASK:   val = "condition";   break;
-    case MODULE_TASK:      val = "module";      break;
-    default:               val = "undefined";   break;
-  }
-
-  return val;
-}
-
-// ----------------------------------------------------------------------------
-// Task Traits
-// ----------------------------------------------------------------------------
-
-/**
-@struct is_static_task
-
-@brief determines if a callable is a static task
-
-A static task is a callable object constructible from std::function<void()>.
-*/
-template <typename C>
-constexpr bool is_static_task_v = is_invocable_r_v<void, C> &&
-                                 !is_invocable_r_v<int, C>;
-
-/**
-@struct is_dynamic_task
-
-@brief determines if a callable is a dynamic task
-
-A dynamic task is a callable object constructible from std::function<void(Subflow&)>.
-*/
-template <typename C>
-constexpr bool is_dynamic_task_v = is_invocable_r_v<void, C, Subflow&>;
-
-/**
-@struct is_condition_task
-
-@brief determines if a callable is a condition task
-
-A condition task is a callable object constructible from std::function<int()>.
-*/
-template <typename C>
-constexpr bool is_condition_task_v = is_invocable_r_v<int, C>;
-
-#ifdef TF_ENABLE_CUDA
-/**
-@struct is_cudaflow_task
-
-@brief determines if a callable is a cudaflow task
-
-A cudaFlow task is a callable object constructible from std::function<void(cudaFlow&)>.
-*/
-template <typename C>
-constexpr bool is_cudaflow_task_v = is_invocable_r_v<void, C, cudaFlow&>;
-#endif
-
-
-
-// ----------------------------------------------------------------------------
-// Task
-// ----------------------------------------------------------------------------
-
-/**
-@class Task
-
-@brief handle to a node in a task dependency graph
-
-A Task is handle object of a node in a dependency graph. 
-It provides a set of methods for users to access and modify the attributes of 
-the associated graph node.
-
-*/
-class Task {
-
-  friend class FlowBuilder;
-  friend class Taskflow;
-  friend class TaskView;
-  
-  public:
-
-    /**
-    @brief constructs an empty task
-    */
-    Task() = default;
-
-    /**
-    @brief constructs the task with the copy of the other task
-    */
-    Task(const Task& other);
-    
-    /**
-    @brief replaces the contents with a copy of the other task
-    */
-    Task& operator = (const Task&);
-    
-    /**
-    @brief replaces the contents with a null pointer
-    */
-    Task& operator = (std::nullptr_t);
-
-    /**
-    @brief compares if two tasks are associated with the same graph node
-    */
-    bool operator == (const Task& rhs) const;
-
-    /**
-    @brief compares if two tasks are not associated with the same graph node
-    */
-    bool operator != (const Task& rhs) const;
-    
-    /**
-    @brief queries the name of the task
-    */
-    const std::string& name() const;
-    
-    /**
-    @brief queries the number of successors of the task
-    */
-    size_t num_successors() const;
-
-    /**
-    @brief queries the number of predecessors of the task
-    */
-    size_t num_dependents() const;
-    
-    /**
-    @brief queries the number of strong dependents of the task
-    */
-    size_t num_strong_dependents() const;
-
-    /**
-    @brief queries the number of weak dependents of the task
-    */
-    size_t num_weak_dependents() const;
-    
-    /**
-    @brief assigns a name to the task
-
-    @param name a @std_string acceptable string
-
-    @return @c *this
-    */
-    Task& name(const std::string& name);
-
-    /**
-    @brief assigns a static task
-
-    @tparam C callable object type
-
-    @param callable a callable object constructible from std::function<void()>
-
-    @return @c *this
-    */
-    template <typename C>
-    std::enable_if_t<is_static_task_v<C>, Task>& work(C&& callable);
-    
-    /**
-    @brief assigns a dynamic task
-
-    @tparam C callable object type
-
-    @param callable a callable object constructible from std::function<void(Subflow&)>
-
-    @return @c *this
-    */
-    template <typename C>
-    std::enable_if_t<is_dynamic_task_v<C>, Task>& work(C&& callable);
-    
-    /**
-    @brief assigns a condition task
-
-    @tparam C callable object type
-
-    @param callable a callable object constructible from std::function<int()>
-
-    @return @c *this
-    */
-    template <typename C>
-    std::enable_if_t<is_condition_task_v<C>, Task>& work(C&& callable);
-
-#ifdef TF_ENABLE_CUDA    
-    /**
-    @brief assigns a cudaFlow task
-
-    @tparam C callable object type
-
-    @param callable a callable object constructible from std::function<void(cudaFlow&)>
-
-    @return @c *this
-    */
-    template <typename C>
-    std::enable_if_t<is_cudaflow_task_v<C>, Task>& work(C&& callable);
-#endif
-
-    /**
-    @brief creates a module task from a taskflow
-
-    @param taskflow a taskflow object for the module
-
-    @return @c *this
-    */
-    Task& composed_of(Taskflow& taskflow);
-    
-    /**
-    @brief adds precedence links from this to other tasks
-
-    @tparam Ts... parameter pack
-
-    @param tasks one or multiple tasks
-
-    @return @c *this
-    */
-    template <typename... Ts>
-    Task& precede(Ts&&... tasks);
-    
-    /**
-    @brief adds precedence links from other tasks to this
-
-    @tparam Ts parameter pack 
-
-    @param tasks one or multiple tasks
-
-    @return @c *this
-    */
-    template <typename... Ts>
-    Task& succeed(Ts&&... tasks);
-    
-    /**
-    @brief resets the task handle to null
-    */
-    void reset();
-
-    /**
-    @brief resets the associated work to a placeholder
-    */
-    void reset_work();
-
-    /**
-    @brief queries if the task handle points to a task node
-    */
-    bool empty() const;
-
-    /**
-    @brief queries if the task has a work assigned
-    */
-    bool has_work() const;
-    
-    /**
-    @brief applies an visitor callable to each successor of the task
-    */
-    template <typename V>
-    void for_each_successor(V&& visitor) const;
-    
-    /**
-    @brief applies an visitor callable to each dependents of the task
-    */
-    template <typename V>
-    void for_each_dependent(V&& visitor) const;
-
-    /**
-    @brief obtains a hash value of the underlying node
-    */
-    size_t hash_value() const;
-    
-    /**
-    @brief returns the task type
-    */
-    TaskType type() const;
-
-  private:
-    
-    Task(Node*);
-
-    Node* _node {nullptr};
-
-    template <typename T>
-    void _precede(T&&);
-    
-    template <typename T, typename... Rest>
-    void _precede(T&&, Rest&&...);
-    
-    template <typename T>
-    void _succeed(T&&);
-    
-    template <typename T, typename... Rest>
-    void _succeed(T&&, Rest&&...);
-};
-
-// Constructor
-inline Task::Task(Node* node) : _node {node} {
-}
-
-// Constructor
-inline Task::Task(const Task& rhs) : _node {rhs._node} {
-}
-
-// Function: precede
-template <typename... Ts>
-Task& Task::precede(Ts&&... tasks) {
-  //(_node->_precede(tgts._node), ...);
-  _precede(std::forward<Ts>(tasks)...);
-  return *this;
-}
-
-/// @private
-// Procedure: _precede
-template <typename T>
-void Task::_precede(T&& other) {
-  _node->_precede(other._node);
-}
-
-/// @private
-// Procedure: _precede
-template <typename T, typename... Ts>
-void Task::_precede(T&& task, Ts&&... others) {
-  _precede(std::forward<T>(task));
-  _precede(std::forward<Ts>(others)...);
-}
-
-// Function: succeed
-template <typename... Ts>
-Task& Task::succeed(Ts&&... tasks) {
-  //(tasks._node->_precede(_node), ...);
-  _succeed(std::forward<Ts>(tasks)...);
-  return *this;
-}
-
-/// @private
-// Procedure: succeed
-template <typename T>
-void Task::_succeed(T&& other) {
-  other._node->_precede(_node);
-}
-
-/// @private
-// Procedure: _succeed
-template <typename T, typename... Ts>
-void Task::_succeed(T&& task, Ts&&... others) {
-  _succeed(std::forward<T>(task));
-  _succeed(std::forward<Ts>(others)...);
-}
-
-// Function: composed_of
-inline Task& Task::composed_of(Taskflow& tf) {
-  _node->_handle.emplace<Node::ModuleWork>(&tf);
-  return *this;
-}
-
-// Operator =
-inline Task& Task::operator = (const Task& rhs) {
-  _node = rhs._node;
-  return *this;
-}
-
-// Operator =
-inline Task& Task::operator = (std::nullptr_t ptr) {
-  _node = ptr;
-  return *this;
-}
-
-// Operator ==
-inline bool Task::operator == (const Task& rhs) const {
-  return _node == rhs._node;
-}
-
-// Operator !=
-inline bool Task::operator != (const Task& rhs) const {
-  return _node != rhs._node;
-}
-
-// Function: name
-inline Task& Task::name(const std::string& name) {
-  _node->_name = name;
-  return *this;
-}
-
-// Procedure: reset
-inline void Task::reset() {
-  _node = nullptr;
-}
-
-// Procedure: reset_work
-inline void Task::reset_work() {
-  _node->_handle = nstd::monostate{};
-}
-
-// Function: name
-inline const std::string& Task::name() const {
-  return _node->_name;
-}
-
-// Function: num_dependents
-inline size_t Task::num_dependents() const {
-  return _node->num_dependents();
-}
-
-// Function: num_strong_dependents
-inline size_t Task::num_strong_dependents() const {
-  return _node->num_strong_dependents();
-}
-
-// Function: num_weak_dependents
-inline size_t Task::num_weak_dependents() const {
-  return _node->num_weak_dependents();
-}
-
-// Function: num_successors
-inline size_t Task::num_successors() const {
-  return _node->num_successors();
-}
-
-// Function: empty
-inline bool Task::empty() const {
-  return _node == nullptr;
-}
-
-// Function: has_work
-inline bool Task::has_work() const {
-  return _node ? _node->_handle.index() != 0 : false;
-}
-
-// Function: task_type
-inline TaskType Task::type() const {
-  return static_cast<TaskType>(_node->_handle.index());
-}
-
-// Function: for_each_successor
-template <typename V>
-void Task::for_each_successor(V&& visitor) const {
-  for(size_t i=0; i<_node->_successors.size(); ++i) {
-    visitor(Task(_node->_successors[i]));
-  }
-}
-
-// Function: for_each_dependent
-template <typename V>
-void Task::for_each_dependent(V&& visitor) const {
-  for(size_t i=0; i<_node->_dependents.size(); ++i) {
-    visitor(Task(_node->_dependents[i]));
-  }
-}
-
-// Function: hash_value
-inline size_t Task::hash_value() const {
-  return std::hash<Node*>{}(_node);
-}
-
-// Function: work
-// assign a static work
-template <typename C>
-std::enable_if_t<is_static_task_v<C>, Task>& Task::work(C&& c) {
-  _node->_handle.emplace<Node::StaticWork>(std::forward<C>(c));
-  return *this;
-}
-
-// Function: work
-// assigns a dynamic work
-template <typename C>
-std::enable_if_t<is_dynamic_task_v<C>, Task>& Task::work(C&& c) {
-  _node->_handle.emplace<Node::DynamicWork>(std::forward<C>(c));
-  return *this;
-}
-
-// Function: work
-// assigns a condition work
-template <typename C>
-std::enable_if_t<is_condition_task_v<C>, Task>& Task::work(C&& c) {
-  _node->_handle.emplace<Node::ConditionWork>(std::forward<C>(c));
-  return *this;
-}
-
-#ifdef TF_ENABLE_CUDA
-// Function: work
-// assigns a cudaFlow work
-template <typename C>
-std::enable_if_t<is_cudaflow_task_v<C>, Task>& Task::work(C&& c) {
-  _node->_handle.emplace<Node::cudaFlowWork>(std::forward<C>(c));
-  return *this;
-}
-#endif
-
-// ----------------------------------------------------------------------------
-
-/**
-@class TaskView
-
-@brief class to access task information from the observer interface
-*/
-class TaskView {
-  
-  friend class Executor;
-
-  public:
-
-    /**
-    @brief constructs an empty task view
-    */
-    TaskView() = default;
-
-    /**
-    @brief constructs a task view from a task
-    */
-    TaskView(const Task& task);
-    
-    /**
-    @brief constructs the task with the copy of the other task
-    */
-    TaskView(const TaskView& other);
-    
-    /**
-    @brief replaces the contents with a copy of the other task
-    */
-    TaskView& operator = (const TaskView& other);
-    
-    /**
-    @brief replaces the contents with another task
-    */
-    TaskView& operator = (const Task& other);
-    
-    /**
-    @brief replaces the contents with a null pointer
-    */
-    TaskView& operator = (std::nullptr_t);
-
-    /**
-    @brief compares if two taskviews are associated with the same task
-    */
-    bool operator == (const TaskView&) const;
-    
-    /**
-    @brief compares if two taskviews are associated with different tasks
-    */
-    bool operator != (const TaskView&) const;
-    
-    /**
-    @brief queries the name of the task
-    */
-    const std::string& name() const;
-    
-    /**
-    @brief queries the number of successors of the task
-    */
-    size_t num_successors() const;
-
-    /**
-    @brief queries the number of predecessors of the task
-    */
-    size_t num_dependents() const;
-    
-    /**
-    @brief queries the number of strong dependents of the task
-    */
-    size_t num_strong_dependents() const;
-
-    /**
-    @brief queries the number of weak dependents of the task
-    */
-    size_t num_weak_dependents() const;
-
-    /**
-    @brief resets to an empty view
-    */
-    void reset();
-
-    /**
-    @brief queries if the task view is empty
-    */
-    bool empty() const;
-    
-    /**
-    @brief applies an visitor callable to each successor of the task
-    */
-    template <typename V>
-    void for_each_successor(V&& visitor) const;
-    
-    /**
-    @brief applies an visitor callable to each dependents of the task
-    */
-    template <typename V>
-    void for_each_dependent(V&& visitor) const;
-
-    /**
-    @brief queries the task type
-    */
-    TaskType type() const;
-    
-  private:
-    
-    TaskView(Node*);
-
-    Node* _node {nullptr};
-};
-
-// Constructor
-inline TaskView::TaskView(Node* node) : _node {node} {
-}
-
-// Constructor
-inline TaskView::TaskView(const TaskView& rhs) : _node {rhs._node} {
-}
-
-// Constructor
-inline TaskView::TaskView(const Task& task) : _node {task._node} {
-}
-
-// Operator =
-inline TaskView& TaskView::operator = (const TaskView& rhs) {
-  _node = rhs._node;
-  return *this;
-}
-
-// Operator =
-inline TaskView& TaskView::operator = (const Task& rhs) {
-  _node = rhs._node;
-  return *this;
-}
-
-// Operator =
-inline TaskView& TaskView::operator = (std::nullptr_t ptr) {
-  _node = ptr;
-  return *this;
-}
-
-// Function: name
-inline const std::string& TaskView::name() const {
-  return _node->_name;
-}
-
-// Function: num_dependents
-inline size_t TaskView::num_dependents() const {
-  return _node->num_dependents();
-}
-
-// Function: num_strong_dependents
-inline size_t TaskView::num_strong_dependents() const {
-  return _node->num_strong_dependents();
-}
-
-// Function: num_weak_dependents
-inline size_t TaskView::num_weak_dependents() const {
-  return _node->num_weak_dependents();
-}
-
-// Function: num_successors
-inline size_t TaskView::num_successors() const {
-  return _node->num_successors();
-}
-
-// Function: reset
-inline void TaskView::reset() {
-  _node = nullptr;
-}
-
-// Function: empty
-inline bool TaskView::empty() const {
-  return _node == nullptr;
-}
-
-// Function: type
-inline TaskType TaskView::type() const {
-  return static_cast<TaskType>(_node->_handle.index());
-}
-
-// Operator ==
-inline bool TaskView::operator == (const TaskView& rhs) const {
-  return _node == rhs._node;
-}
-
-// Operator !=
-inline bool TaskView::operator != (const TaskView& rhs) const {
-  return _node != rhs._node;
-}
-
-// Function: for_each_successor
-template <typename V>
-void TaskView::for_each_successor(V&& visitor) const {
-  for(size_t i=0; i<_node->_successors.size(); ++i) {
-    visitor(TaskView(_node->_successors[i]));
-  }
-}
-
-// Function: for_each_dependent
-template <typename V>
-void TaskView::for_each_dependent(V&& visitor) const {
-  for(size_t i=0; i<_node->_dependents.size(); ++i) {
-    visitor(TaskView(_node->_dependents[i]));
-  }
-}
-
-}  // end of namespace tf. ---------------------------------------------------
-
-namespace std {
-
-/**
-@class hash<tf::Task>
-
-@brief hash specialization for std::hash<tf::Task>
-
-*/
-template <>
-struct hash<tf::Task> {
-  auto operator() (const tf::Task& task) const noexcept {
-    return task.hash_value();
-  }
-};
-
-}  // end of namespace std ----------------------------------------------------
-
-
-
diff --git a/bundled/taskflow-2.5.0/include/taskflow/core/taskflow.hpp b/bundled/taskflow-2.5.0/include/taskflow/core/taskflow.hpp
deleted file mode 100644 (file)
index f6123ef..0000000
+++ /dev/null
@@ -1,353 +0,0 @@
-#pragma once
-
-#include <stack>
-
-#include "flow_builder.hpp"
-#include "topology.hpp"
-
-namespace tf {
-
-// ----------------------------------------------------------------------------
-
-/**
-@class Taskflow 
-
-@brief main entry to create a task dependency graph
-
-*/
-class Taskflow : public FlowBuilder {
-
-  friend class Topology;
-  friend class Executor;
-  friend class FlowBuilder;
-
-  struct Dumper {
-    std::stack<const Taskflow*> stack;
-    std::unordered_set<const Taskflow*> visited;
-  };
-
-  public:
-
-    /**
-    @brief constructs a taskflow with a given name
-    */
-    Taskflow(const std::string& name);
-
-    /**
-    @brief constructs a taskflow
-    */
-    Taskflow();
-
-    /**
-    @brief destroy the taskflow (virtual call)
-    */
-    virtual ~Taskflow();
-    
-    /**
-    @brief dumps the taskflow to a std::ostream in DOT format
-
-    @param ostream a std::ostream target
-    */
-    void dump(std::ostream& ostream) const;
-    
-    /**
-    @brief dumps the taskflow in DOT format to a std::string
-    */
-    std::string dump() const;
-    
-    /**
-    @brief queries the number of tasks in the taskflow
-    */
-    size_t num_tasks() const;
-    
-    /**
-    @brief queries the emptiness of the taskflow
-    */
-    bool empty() const;
-
-    /**
-    @brief sets the name of the taskflow
-    
-    @return @c *this
-    */
-    void name(const std::string&); 
-
-    /**
-    @brief queries the name of the taskflow
-    */
-    const std::string& name() const ;
-    
-    /**
-    @brief clears the associated task dependency graph
-    */
-    void clear();
-
-    /**
-    @brief applies an visitor callable to each task in the taskflow
-    */
-    template <typename V>
-    void for_each_task(V&& visitor) const;
-
-  private:
-    std::string _name;
-   
-    Graph _graph;
-
-    std::mutex _mtx;
-
-    std::list<Topology> _topologies;
-
-    void _dump(std::ostream&, const Taskflow*) const;
-    void _dump(std::ostream&, const Node*, Dumper&) const;
-    void _dump(std::ostream&, const Graph&, Dumper&) const;
-};
-
-// Constructor
-inline Taskflow::Taskflow(const std::string& name) : 
-  FlowBuilder {_graph},
-  _name       {name} {
-}
-
-// Constructor
-inline Taskflow::Taskflow() : FlowBuilder{_graph} {
-}
-
-// Destructor
-inline Taskflow::~Taskflow() {
-  assert(_topologies.empty());
-}
-
-// Procedure:
-inline void Taskflow::clear() {
-  _graph.clear();
-}
-
-// Function: num_noces
-inline size_t Taskflow::num_tasks() const {
-  return _graph.size();
-}
-
-// Function: empty
-inline bool Taskflow::empty() const {
-  return _graph.empty();
-}
-
-// Function: name
-inline void Taskflow::name(const std::string &name) {
-  _name = name;
-}
-
-// Function: name
-inline const std::string& Taskflow::name() const {
-  return _name;
-}
-
-// Function: for_each_task
-template <typename V>
-void Taskflow::for_each_task(V&& visitor) const {
-  for(size_t i=0; i<_graph._nodes.size(); ++i) {
-    visitor(Task(_graph._nodes[i]));
-  }
-}
-
-// Procedure: dump
-inline std::string Taskflow::dump() const {
-  std::ostringstream oss;
-  dump(oss);
-  return oss.str();
-}
-
-// Function: dump
-inline void Taskflow::dump(std::ostream& os) const {
-  os << "digraph Taskflow {\n";
-  _dump(os, this);
-  os << "}\n";
-}
-
-// Procedure: _dump
-inline void Taskflow::_dump(std::ostream& os, const Taskflow* top) const {
-  
-  Dumper dumper;
-  
-  dumper.stack.push(top);
-  dumper.visited.insert(top);
-
-  while(!dumper.stack.empty()) {
-    
-    auto f = dumper.stack.top();
-    dumper.stack.pop();
-    
-    os << "subgraph cluster_p" << f << " {\nlabel=\"Taskflow: ";
-    if(f->_name.empty()) os << 'p' << f;
-    else os << f->_name;
-    os << "\";\n";
-    _dump(os, f->_graph, dumper);
-    os << "}\n";
-  }
-}
-
-// Procedure: _dump
-inline void Taskflow::_dump(
-  std::ostream& os, const Node* node, Dumper& dumper
-) const {
-
-  os << 'p' << node << "[label=\"";
-  if(node->_name.empty()) os << 'p' << node;
-  else os << node->_name;
-  os << "\" ";
-
-  // shape for node
-  switch(node->_handle.index()) {
-
-    case Node::CONDITION_WORK:
-      os << "shape=diamond color=black fillcolor=aquamarine style=filled";
-    break;
-
-#ifdef TF_ENABLE_CUDA
-    case Node::CUDAFLOW_WORK:
-      os << "shape=folder fillcolor=cyan style=filled";
-    break;
-#endif
-
-    default:
-    break;
-  }
-
-  os << "];\n";
-  
-  for(size_t s=0; s<node->_successors.size(); ++s) {
-    if(node->_handle.index() == Node::CONDITION_WORK) {
-      // case edge is dashed
-      os << 'p' << node << " -> p" << node->_successors[s] 
-         << " [style=dashed label=\"" << s << "\"];\n";
-    }
-    else {
-      os << 'p' << node << " -> p" << node->_successors[s] << ";\n";
-    }
-  }
-  
-  // subflow join node
-  if(node->_parent && node->_successors.size() == 0) {
-    os << 'p' << node << " -> p" << node->_parent << ";\n";
-  }
-
-  switch(node->_handle.index()) {
-
-    case Node::DYNAMIC_WORK: {
-      auto& sbg = nstd::get<Node::DynamicWork>(node->_handle).subgraph;
-      if(!sbg.empty()) {
-        os << "subgraph cluster_p" << node << " {\nlabel=\"Subflow: ";
-        if(node->_name.empty()) os << 'p' << node;
-        else os << node->_name;
-
-        os << "\";\n" << "color=blue\n";
-        _dump(os, sbg, dumper);
-        os << "}\n";
-      }
-    }
-    break;
-
-#ifdef TF_ENABLE_CUDA
-    case Node::CUDAFLOW_WORK: {
-      auto& cfg = nstd::get<Node::cudaFlowWork>(node->_handle).graph;
-      if(!cfg.empty()) {
-        os << "subgraph cluster_p" << node << " {\nlabel=\"cudaFlow: ";
-        if(node->_name.empty()) os << 'p' << node;
-        else os << node->_name;
-
-        os << "\";\n" << "color=\"purple\"\n";
-
-        for(const auto& v : cfg._nodes) {
-
-          os << 'p' << v.get() << "[label=\"";
-          if(v->_name.empty()) {
-            os << 'p' << v.get() << "\"";
-          }
-          else {
-            os << v->_name << "\"";
-          }
-          
-          switch(v->_handle.index()) {
-            case cudaNode::NOOP:
-            break;
-
-            case cudaNode::COPY:
-              //os << " shape=\"cds\"";
-            break;
-
-            case cudaNode::KERNEL:
-              os << " style=\"filled\""
-                 << " color=\"white\" fillcolor=\"black\""
-                 << " fontcolor=\"white\""
-                 << " shape=\"box3d\"";
-            break;
-
-            default:
-            break;
-          }
-  
-          os << "];\n";
-          for(const auto s : v->_successors) {
-            os << 'p' << v.get() << " -> " << 'p' << s << ";\n";
-          }
-          
-          if(v->_successors.size() == 0) {
-            os << 'p' << v.get() << " -> p" << node << ";\n";
-          }
-
-        }
-        os << "}\n";
-      }
-    }
-    break;
-#endif
-
-    default:
-    break;
-  }
-}
-
-// Procedure: _dump
-inline void Taskflow::_dump(
-  std::ostream& os, const Graph& graph, Dumper& dumper
-) const {
-    
-  for(const auto& n : graph._nodes) {
-
-    // regular task
-    if(n->_handle.index() != Node::MODULE_WORK) {
-      _dump(os, n, dumper);
-    }
-    // module task
-    else {
-
-      auto module = nstd::get<Node::ModuleWork>(n->_handle).module;
-
-      os << 'p' << n << "[shape=box3d, color=blue, label=\"";
-      if(n->_name.empty()) os << n;
-      else os << n->_name;
-      os << " [Taskflow: ";
-      if(module->_name.empty()) os << 'p' << module;
-      else os << module->_name;
-      os << "]\"];\n";
-
-      if(dumper.visited.find(module) == dumper.visited.end()) {
-        dumper.visited.insert(module);
-        dumper.stack.push(module);
-      }
-
-      for(const auto s : n->_successors) {
-        os << 'p' << n << "->" << 'p' << s << ";\n";
-      }
-    }
-  }
-}
-
-// ----------------------------------------------------------------------------
-// Backward compatibility
-// ----------------------------------------------------------------------------
-using Framework = Taskflow;
-
-}  // end of namespace tf. ---------------------------------------------------
-
diff --git a/bundled/taskflow-2.5.0/include/taskflow/core/topology.hpp b/bundled/taskflow-2.5.0/include/taskflow/core/topology.hpp
deleted file mode 100644 (file)
index 97780d9..0000000
+++ /dev/null
@@ -1,93 +0,0 @@
-#pragma once
-
-//#include "taskflow.hpp"
-
-namespace tf {
-
-// ----------------------------------------------------------------------------
-  
-// class: Topology
-class Topology {
-  
-  friend class Taskflow;
-  friend class Executor;
-  
-  public:
-
-    template <typename P, typename C>
-    Topology(Taskflow&, P&&, C&&);
-    
-  private:
-
-    Taskflow& _taskflow;
-
-    std::promise<void> _promise;
-
-    PassiveVector<Node*> _sources;
-    
-    std::function<bool()> _pred;
-    std::function<void()> _call;
-
-    std::atomic<size_t> _join_counter {0};
-};
-
-// Constructor
-template <typename P, typename C>
-inline Topology::Topology(Taskflow& tf, P&& p, C&& c): 
-  _taskflow(tf),
-  _pred {std::forward<P>(p)},
-  _call {std::forward<C>(c)} {
-}
-
-// Procedure: _bind
-// Re-builds the source links and the sink number for this topology.
-//inline void Topology::_bind(Graph& g) {
-//  
-//  _sources.clear();
-//
-//  //PassiveVector<Node*> condition_nodes;
-//  
-//  // scan each node in the graph and build up the links
-//  for(auto& node : g.nodes()) {
-//
-//    node->_topology = this;
-//    node->_clear_state();
-//    node->_set_up_join_counter();
-//
-//    if(node->num_dependents() == 0) {
-//      _sources.push_back(node.get());
-//    }
-//
-//    //int join_counter = 0;
-//    //for(auto p : node->_dependents) {
-//    //  if(p->_work.index() == Node::CONDITION_WORK) {
-//    //    node->_set_state(Node::BRANCH);
-//    //  }
-//    //  else {
-//    //    join_counter++;
-//    //  }
-//    //}
-//
-//    //node->_join_counter.store(join_counter, std::memory_order_relaxed);
-//    
-//    //// TODO: Merge with the loop below?
-//    //if(node->_work.index() == Node::CONDITION_WORK) {
-//    //  condition_nodes.push_back(node.get());
-//    //}
-//
-//    //// Reset each node's num_dependents
-//    //node->_join_counter.store(node->_dependents.size(), std::memory_order_relaxed);
-//  }
-//
-//  // We need to deduct the condition predecessors in impure case nodes
-//  //for(auto& n: condition_nodes) {
-//  //  for(auto& s: n->_successors) {
-//  //    s->_join_counter.fetch_sub(1, std::memory_order_relaxed);
-//  //    s->set_branch();
-//  //  }
-//  //}
-//}
-
-
-
-}  // end of namespace tf. ----------------------------------------------------
diff --git a/bundled/taskflow-2.5.0/include/taskflow/core/tsq.hpp b/bundled/taskflow-2.5.0/include/taskflow/core/tsq.hpp
deleted file mode 100644 (file)
index 23ea34d..0000000
+++ /dev/null
@@ -1,250 +0,0 @@
-// 2020/02/24 - created by twhuang
-//  - specialized work stealing queue for pointer
-
-#pragma once
-
-#include <atomic>
-#include <vector>
-#include <cassert>
-#include <cstdint>
-#include <cstddef>
-#include <cstdlib>
-
-namespace tf {
-
-/**
-@class: TaskQueue
-
-@tparam T data type (must be a pointer)
-
-@brief Lock-free unbounded single-producer multiple-consumer queue.
-
-This class implements the work stealing queue described in the paper, 
-"Correct and Efficient Work-Stealing for Weak Memory Models,"
-available at https://www.di.ens.fr/~zappa/readings/ppopp13.pdf.
-
-Only the queue owner can perform pop and push operations,
-while others can steal data from the queue.
-*/
-template <typename T>
-class TaskQueue {
-
-  static_assert(std::is_pointer<T>::value, "T must be a pointer type");
-
-  struct Array {
-
-    int64_t C;
-    int64_t M;
-    std::atomic<T>* S;
-
-    explicit Array(int64_t c) : 
-      C {c},
-      M {c-1},
-      S {new std::atomic<T>[static_cast<size_t>(C)]} {
-    }
-
-    ~Array() {
-      delete [] S;
-    }
-
-    int64_t capacity() const noexcept {
-      return C;
-    }
-    
-    template <typename O>
-    void push(int64_t i, O&& o) noexcept {
-      S[i & M].store(std::forward<O>(o), std::memory_order_relaxed);
-    }
-
-    T pop(int64_t i) noexcept {
-      return S[i & M].load(std::memory_order_relaxed);
-    }
-
-    Array* resize(int64_t b, int64_t t) {
-      Array* ptr = new Array {2*C};
-      for(int64_t i=t; i!=b; ++i) {
-        ptr->push(i, pop(i));
-      }
-      return ptr;
-    }
-
-  };
-
-  std::atomic<int64_t> _top;
-  std::atomic<int64_t> _bottom;
-  std::atomic<Array*> _array;
-  std::vector<Array*> _garbage;
-
-  public:
-    
-    /**
-    @brief constructs the queue with a given capacity
-
-    @param capacity the capacity of the queue (must be power of 2)
-    */
-    explicit TaskQueue(int64_t capacity = 1024);
-
-    /**
-    @brief destructs the queue
-    */
-    ~TaskQueue();
-    
-    /**
-    @brief queries if the queue is empty at the time of this call
-    */
-    bool empty() const noexcept;
-    
-    /**
-    @brief queries the number of items at the time of this call
-    */
-    size_t size() const noexcept;
-
-    /**
-    @brief queries the capacity of the queue
-    */
-    int64_t capacity() const noexcept;
-    
-    /**
-    @brief inserts an item to the queue
-
-    Only the owner thread can insert an item to the queue. 
-    The operation can trigger the queue to resize its capacity 
-    if more space is required.
-
-    @tparam O data type 
-
-    @param item the item to perfect-forward to the queue
-    */
-    void push(T item);
-    
-    /**
-    @brief pops out an item from the queue
-
-    Only the owner thread can pop out an item from the queue. 
-    The return can be a nullptr if this operation failed (empty queue).
-    */
-    T pop();
-    
-    /**
-    @brief steals an item from the queue
-
-    Any threads can try to steal an item from the queue.
-    The return can be a nullptr if this operation failed (not necessary empty).
-    */
-    T steal();
-};
-
-// Constructor
-template <typename T>
-TaskQueue<T>::TaskQueue(int64_t c) {
-  assert(c && (!(c & (c-1))));
-  _top.store(0, std::memory_order_relaxed);
-  _bottom.store(0, std::memory_order_relaxed);
-  _array.store(new Array{c}, std::memory_order_relaxed);
-  _garbage.reserve(32);
-}
-
-// Destructor
-template <typename T>
-TaskQueue<T>::~TaskQueue() {
-  for(auto a : _garbage) {
-    delete a;
-  }
-  delete _array.load();
-}
-  
-// Function: empty
-template <typename T>
-bool TaskQueue<T>::empty() const noexcept {
-  int64_t b = _bottom.load(std::memory_order_relaxed);
-  int64_t t = _top.load(std::memory_order_relaxed);
-  return b <= t;
-}
-
-// Function: size
-template <typename T>
-size_t TaskQueue<T>::size() const noexcept {
-  int64_t b = _bottom.load(std::memory_order_relaxed);
-  int64_t t = _top.load(std::memory_order_relaxed);
-  return static_cast<size_t>(b >= t ? b - t : 0);
-}
-
-// Function: push
-template <typename T>
-void TaskQueue<T>::push(T o) {
-  int64_t b = _bottom.load(std::memory_order_relaxed);
-  int64_t t = _top.load(std::memory_order_acquire);
-  Array* a = _array.load(std::memory_order_relaxed);
-
-  // queue is full
-  if(a->capacity() - 1 < (b - t)) {
-    Array* tmp = a->resize(b, t);
-    _garbage.push_back(a);
-    std::swap(a, tmp);
-    _array.store(a, std::memory_order_relaxed);
-  }
-
-  a->push(b, o);
-  std::atomic_thread_fence(std::memory_order_release);
-  _bottom.store(b + 1, std::memory_order_relaxed);
-}
-
-// Function: pop
-template <typename T>
-T TaskQueue<T>::pop() {
-  int64_t b = _bottom.load(std::memory_order_relaxed) - 1;
-  Array* a = _array.load(std::memory_order_relaxed);
-  _bottom.store(b, std::memory_order_relaxed);
-  std::atomic_thread_fence(std::memory_order_seq_cst);
-  int64_t t = _top.load(std::memory_order_relaxed);
-
-  T item {nullptr};
-
-  if(t <= b) {
-    item = a->pop(b);
-    if(t == b) {
-      // the last item just got stolen
-      if(!_top.compare_exchange_strong(t, t+1, 
-                                       std::memory_order_seq_cst, 
-                                       std::memory_order_relaxed)) {
-        item = nullptr;
-      }
-      _bottom.store(b + 1, std::memory_order_relaxed);
-    }
-  }
-  else {
-    _bottom.store(b + 1, std::memory_order_relaxed);
-  }
-
-  return item;
-}
-
-// Function: steal
-template <typename T>
-T TaskQueue<T>::steal() {
-  int64_t t = _top.load(std::memory_order_acquire);
-  std::atomic_thread_fence(std::memory_order_seq_cst);
-  int64_t b = _bottom.load(std::memory_order_acquire);
-  
-  T item {nullptr};
-
-  if(t < b) {
-    Array* a = _array.load(std::memory_order_consume);
-    item = a->pop(t);
-    if(!_top.compare_exchange_strong(t, t+1,
-                                     std::memory_order_seq_cst,
-                                     std::memory_order_relaxed)) {
-      return nullptr;
-    }
-  }
-
-  return item;
-}
-
-// Function: capacity
-template <typename T>
-int64_t TaskQueue<T>::capacity() const noexcept {
-  return _array.load(std::memory_order_relaxed)->capacity();
-}
-
-}  // end of namespace tf -----------------------------------------------------
diff --git a/bundled/taskflow-2.5.0/include/taskflow/cuda/cuda_device.hpp b/bundled/taskflow-2.5.0/include/taskflow/cuda/cuda_device.hpp
deleted file mode 100644 (file)
index 7b9371a..0000000
+++ /dev/null
@@ -1,136 +0,0 @@
-#pragma once
-
-#include "cuda_error.hpp"
-
-namespace tf { 
-
-/**
-@brief queries the number of available devices
-*/
-inline size_t cuda_num_devices() {
-       int N = 0;
-  TF_CHECK_CUDA(cudaGetDeviceCount(&N), "failed to get device count");
-       return static_cast<size_t>(N);
-}
-
-/**
-@brief gets the current device associated with the caller thread
-*/
-inline int cuda_get_device() {
-  int id;
-  TF_CHECK_CUDA(cudaGetDevice(&id), "failed to get current device id");
-       return id;
-}
-
-/**
-@brief switches to a given device context
-*/
-inline void cuda_set_device(int id) {
-  TF_CHECK_CUDA(cudaSetDevice(id), "failed to switch to device ", id);
-}
-    
-/**    
-@brief obtains the device property 
-*/
-inline void cuda_get_device_property(int i, cudaDeviceProp& p) {
-  TF_CHECK_CUDA(
-    cudaGetDeviceProperties(&p, i), "failed to get property of device ", i
-  );
-}
-
-/**    
-@brief obtains the device property 
-*/
-inline cudaDeviceProp cuda_get_device_property(int i) {
-  cudaDeviceProp p;
-  TF_CHECK_CUDA(
-    cudaGetDeviceProperties(&p, i), "failed to get property of device ", i
-  );
-  return p;
-}
-
-/**
-@brief cuda_dump_device_property
-*/
-inline void cuda_dump_device_property(std::ostream& os, const cudaDeviceProp& p) {
-
-  os << "Major revision number:         " << p.major << '\n'
-     << "Minor revision number:         " << p.minor << '\n'
-     << "Name:                          " << p.name  << '\n'
-     << "Total global memory:           " << p.totalGlobalMem << '\n'
-     << "Total shared memory per block: " << p.sharedMemPerBlock << '\n'
-     << "Total registers per block:     " << p.regsPerBlock << '\n'
-     << "Warp size:                     " << p.warpSize << '\n'
-     << "Maximum memory pitch:          " << p.memPitch << '\n'
-     << "Maximum threads per block:     " << p.maxThreadsPerBlock << '\n';
-
-  os << "Maximum dimension of block:    ";
-  for (int i = 0; i < 3; ++i) {
-    if(i) os << 'x';
-    os << p.maxThreadsDim[i];
-  }
-  os << '\n';
-
-  os << "Maximum dimenstion of grid:    ";
-  for (int i = 0; i < 3; ++i) {
-    if(i) os << 'x';
-    os << p.maxGridSize[i];;
-  }
-  os << '\n';
-
-  os << "Clock rate:                    " << p.clockRate << '\n'
-     << "Total constant memory:         " << p.totalConstMem << '\n'
-     << "Texture alignment:             " << p.textureAlignment << '\n'
-     << "Concurrent copy and execution: " << p.deviceOverlap << '\n'
-     << "Number of multiprocessors:     " << p.multiProcessorCount << '\n'
-     << "Kernel execution timeout:      " << p.kernelExecTimeoutEnabled << '\n'
-     << "GPU sharing Host Memory:       " << p.integrated << '\n'
-     << "Host page-locked mem mapping:  " << p.canMapHostMemory << '\n'
-     << "Alignment for Surfaces:        " << p.surfaceAlignment << '\n'
-     << "Device has ECC support:        " << p.ECCEnabled << '\n'
-     << "Unified Addressing (UVA):      " << p.unifiedAddressing << '\n';
-}
-
-// ----------------------------------------------------------------------------
-// Class definitions
-// ----------------------------------------------------------------------------
-
-/** @class cudaScopedDevice
-
-@brief RAII-style device context switch
-
-*/
-class cudaScopedDevice {
-
-  public:
-    
-    cudaScopedDevice(int);
-    ~cudaScopedDevice();
-
-  private:
-
-    int _p;
-};
-
-// Constructor
-inline cudaScopedDevice::cudaScopedDevice(int dev) { 
-  TF_CHECK_CUDA(cudaGetDevice(&_p), "failed to get current device scope");
-  if(_p == dev) {
-    _p = -1;
-  }
-  else {
-    TF_CHECK_CUDA(cudaSetDevice(dev), "failed to scope on device ", dev);
-  }
-}
-
-// Destructor
-inline cudaScopedDevice::~cudaScopedDevice() { 
-  if(_p != -1) {
-    cudaSetDevice(_p);
-    //TF_CHECK_CUDA(cudaSetDevice(_p), "failed to scope back to device ", _p);
-  }
-}
-
-}  // end of namespace cuda ---------------------------------------------------
-
-
diff --git a/bundled/taskflow-2.5.0/include/taskflow/cuda/cuda_error.hpp b/bundled/taskflow-2.5.0/include/taskflow/cuda/cuda_error.hpp
deleted file mode 100644 (file)
index a2b6795..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-#pragma once
-
-#include <cuda.h>
-#include <iostream>
-#include <sstream>
-#include <exception>
-
-#include "../utility/stringify.hpp"
-
-#define TF_CUDA_REMOVE_FIRST_HELPER(N, ...) __VA_ARGS__
-#define TF_CUDA_REMOVE_FIRST(...) TF_CUDA_REMOVE_FIRST_HELPER(__VA_ARGS__)
-#define TF_CUDA_GET_FIRST_HELPER(N, ...) N
-#define TF_CUDA_GET_FIRST(...) TF_CUDA_GET_FIRST_HELPER(__VA_ARGS__)
-
-#define TF_CHECK_CUDA(...)                                       \
-if(TF_CUDA_GET_FIRST(__VA_ARGS__) != cudaSuccess) {              \
-  std::ostringstream oss;                                        \
-  auto ev = TF_CUDA_GET_FIRST(__VA_ARGS__);                      \
-  auto unknown_str  = "unknown error";                           \
-  auto unknown_name = "cudaErrorUnknown";                        \
-  auto error_str  = ::cudaGetErrorString(ev);                    \
-  auto error_name = ::cudaGetErrorName(ev);                      \
-  oss << "[" << __FILE__ << ":" << __LINE__ << "] "              \
-      << (error_str  ? error_str  : unknown_str)                 \
-      << " ("                                                    \
-      << (error_name ? error_name : unknown_name)                \
-      << ") - ";                                                 \
-  tf::ostreamize(oss, TF_CUDA_REMOVE_FIRST(__VA_ARGS__));  \
-  throw std::runtime_error(oss.str());                           \
-}
-
diff --git a/bundled/taskflow-2.5.0/include/taskflow/cuda/cuda_flow.hpp b/bundled/taskflow-2.5.0/include/taskflow/cuda/cuda_flow.hpp
deleted file mode 100644 (file)
index efe770a..0000000
+++ /dev/null
@@ -1,503 +0,0 @@
-#pragma once
-
-#include "cuda_task.hpp"
-
-namespace tf {
-
-/**
-@class cudaFlow
-
-@brief methods for building a CUDA task dependency graph.
-
-A cudaFlow is a high-level interface to manipulate GPU tasks using 
-the task dependency graph model.
-The class provides a set of methods for creating and launch different tasks
-on one or multiple CUDA devices,
-for instance, kernel tasks, data transfer tasks, and memory operation tasks.
-*/
-class cudaFlow {
-
-  friend class Executor;
-
-  public:
-    
-    /**
-    @brief constructs a cudaFlow builder object
-
-    @tparam P predicate type
-
-    @param graph a cudaGraph to manipulate
-    @param p predicate which return @c true if the launching should be contined
-    */
-    template <typename P>
-    cudaFlow(cudaGraph& graph, P&& p);
-
-    /**
-    @brief queries the emptiness of the graph
-    */
-    bool empty() const;
-    
-    /**
-    @brief creates a no-operation task
-
-    An empty node performs no operation during execution, 
-    but can be used for transitive ordering. 
-    For example, a phased execution graph with 2 groups of n nodes 
-    with a barrier between them can be represented using an empty node 
-    and 2*n dependency edges, 
-    rather than no empty node and n^2 dependency edges.
-    */
-    cudaTask noop();
-    
-    // CUDA seems pretty restrictive about calling host in a cudaGraph.
-    // We disable this function and wait for future stability.
-    //
-    //@brief creates a host execution task
-    //
-    //@tparam C callable type
-    //
-    //@param c a callable object constructible from std::function<void()>.
-
-    //A host can only execute CPU-specific functions and cannot do any CUDA calls 
-    //(e.g., cudaMalloc).
-    //
-    //template <typename C>
-    //cudaTask host(C&& c);
-    
-    /**
-    @brief creates a kernel task
-    
-    @tparam F kernel function type
-    @tparam ArgsT kernel function parameters type
-
-    @param g configured grid
-    @param b configured block
-    @param s configured shared memory
-    @param f kernel function
-    @param args arguments to forward to the kernel function by copy
-
-    @return cudaTask handle
-    */
-    template <typename F, typename... ArgsT>
-    cudaTask kernel(dim3 g, dim3 b, size_t s, F&& f, ArgsT&&... args);
-    
-    /**
-    @brief creates a kernel task on a device
-    
-    @tparam F kernel function type
-    @tparam ArgsT kernel function parameters type
-    
-    @param d device identifier to luanch the kernel
-    @param g configured grid
-    @param b configured block
-    @param s configured shared memory
-    @param f kernel function
-    @param args arguments to forward to the kernel function by copy
-
-    @return cudaTask handle
-    */
-    template <typename F, typename... ArgsT>
-    cudaTask kernel_on(int d, dim3 g, dim3 b, size_t s, F&& f, ArgsT&&... args);
-
-    /**
-    @brief creates a memset task
-
-    @param dst pointer to the destination device memory area
-    @param v value to set for each byte of specified memory
-    @param count size in bytes to set
-
-    A memset task fills the first @c count bytes of device memory area 
-    pointed by @c dst with the byte value @c v.
-    */
-    cudaTask memset(void* dst, int v, size_t count);
-    
-    /**
-    @brief creates a memcpy task
-    
-    @param tgt pointer to the target memory block
-    @param src pointer to the source memory block
-    @param bytes bytes to copy
-
-    @return cudaTask handle
-
-    A memcpy task transfers @c bytes of data from a course location
-    to a target location. Direction can be arbitrary among CPUs and GPUs.
-    */ 
-    cudaTask memcpy(void* tgt, const void* src, size_t bytes);
-
-    /**
-    @brief creates a zero task that zeroes a typed memory block
-
-    @tparam T element type (size of @c T must be either 1, 2, or 4)
-    @param dst pointer to the destination device memory area
-    @param count number of elements
-
-    A zero task zeroes the first @c count elements of type @c T 
-    in a device memory area pointed by @c dst.
-    */
-    template <typename T>
-    std::enable_if_t<
-      is_pod_v<T> && (sizeof(T)==1 || sizeof(T)==2 || sizeof(T)==4), 
-      cudaTask
-    > 
-    zero(T* dst, size_t count);
-
-    /**
-    @brief creates a fill task that fills a typed memory block with a value
-
-    @tparam T element type (size of @c T must be either 1, 2, or 4)
-    @param dst pointer to the destination device memory area
-    @param value value to fill for each element of type @c T
-    @param count number of elements
-
-    A fill task fills the first @c count elements of type @c T with @c value
-    in a device memory area pointed by @c dst.
-    The value to fill is interpreted in type @c T rather than byte.
-    */
-    template <typename T>
-    std::enable_if_t<
-      is_pod_v<T> && (sizeof(T)==1 || sizeof(T)==2 || sizeof(T)==4), 
-      cudaTask
-    >
-    fill(T* dst, T value, size_t count);
-    
-    /**
-    @brief creates a copy task
-    
-    @tparam T element type (non-void)
-
-    @param tgt pointer to the target memory block
-    @param src pointer to the source memory block
-    @param num number of elements to copy
-
-    @return cudaTask handle
-
-    A copy task transfers <tt>num*sizeof(T)</tt> bytes of data from a source location
-    to a target location. Direction can be arbitrary among CPUs and GPUs.
-    */
-    template <
-      typename T, 
-      std::enable_if_t<!std::is_same<T, void>::value, void>* = nullptr
-    >
-    cudaTask copy(T* tgt, const T* src, size_t num);
-
-    /**
-    @brief assigns a device to launch the cudaFlow
-
-    @param device target device identifier
-    */
-    void device(int device);
-
-    /**
-    @brief queries the device associated with the cudaFlow
-    */
-    int device() const;
-
-    /**
-    @brief assigns a stream to launch the cudaFlow
-
-    @param stream target stream identifier
-    */
-    void stream(cudaStream_t stream);
-
-    /**
-    @brief assigns a predicate to loop the cudaFlow until the predicate is satisfied
-
-    @tparam P predicate type
-    @param p predicate which return @c true if the launching should be contined
-
-    The execution of cudaFlow is equivalent to: <tt>while(!predicate()) { run cudaflow; }</tt>
-    */
-    template <typename P>
-    void predicate(P&& p);
-    
-    /**
-    @brief repeats the execution of the cudaFlow by @c n times
-    */
-    void repeat(size_t n);
-
-  private:
-
-    cudaGraph& _graph;
-    
-    int _device {0};
-
-    nstd::optional<cudaStream_t> _stream;
-
-    std::function<bool()> _predicate;
-};
-
-// Constructor
-template <typename P>
-cudaFlow::cudaFlow(cudaGraph& g, P&& p) : 
-  _graph {g},
-  _predicate {std::forward<P>(p)} {
-}
-
-// Procedure: predicate
-template <typename P>
-void cudaFlow::predicate(P&& pred) {
-  _predicate = std::forward<P>(pred);
-}
-
-// Procedure: repeat
-inline void cudaFlow::repeat(size_t n) {
-  _predicate = [n] () mutable { return n-- == 0; };
-}
-
-// Function: empty
-inline bool cudaFlow::empty() const {
-  return _graph._nodes.empty();
-}
-
-// Procedure: device
-inline void cudaFlow::device(int d) {
-  _device = d;
-}
-
-// Function: device
-inline int cudaFlow::device() const {
-  return _device;
-}
-
-// Procedure: stream
-inline void cudaFlow::stream(cudaStream_t s) {
-  _stream = s;
-}
-
-// Function: noop
-inline cudaTask cudaFlow::noop() {
-  auto node = _graph.emplace_back(nstd::in_place_type_t<cudaNode::Noop>{}, 
-    [](cudaGraph_t& graph, cudaGraphNode_t& node){
-      TF_CHECK_CUDA(
-        ::cudaGraphAddEmptyNode(&node, graph, nullptr, 0),
-        "failed to create a no-operation (empty) node"
-      );
-    }
-  );
-  return cudaTask(node);
-}
-
-//// Function: host
-//template <typename C>
-//cudaTask cudaFlow::host(C&& c) {
-//  auto node = _graph.emplace_back(nstd::in_place_type_t<cudaNode::Host>{}, 
-//    [c=std::forward<C>(c)](cudaGraph_t& graph, cudaGraphNode_t& node) mutable {
-//      cudaHostNodeParams p;
-//      p.fn = [] (void* data) { (*static_cast<C*>(data))(); };
-//      p.userData = &c;
-//      TF_CHECK_CUDA(
-//        ::cudaGraphAddHostNode(&node, graph, nullptr, 0, &p),
-//        "failed to create a host node"
-//      );
-//    }
-//  );
-//  return cudaTask(node);
-//}
-
-// Function: kernel
-template <typename F, typename... ArgsT>
-cudaTask cudaFlow::kernel(
-  dim3 g, dim3 b, size_t s, F&& f, ArgsT&&... args
-) {
-  
-  using traits = function_traits<F>;
-
-  static_assert(traits::arity == sizeof...(ArgsT), "arity mismatches");
-  
-  auto node = _graph.emplace_back(nstd::in_place_type_t<cudaNode::Kernel>{}, 
-    [g, b, s, f=(void*)f, args...] (cudaGraph_t& graph, cudaGraphNode_t& node) {
-
-      cudaKernelNodeParams p;
-      void* arguments[sizeof...(ArgsT)] = { (void*)(&args)... };
-      p.func = f;
-      p.gridDim = g;
-      p.blockDim = b;
-      p.sharedMemBytes = s;
-      p.kernelParams = arguments;
-      p.extra = nullptr;
-
-      TF_CHECK_CUDA(
-        ::cudaGraphAddKernelNode(&node, graph, nullptr, 0, &p),
-        "failed to create a cudaGraph node in kernel task"
-      );
-    }
-  );
-  
-  return cudaTask(node);
-}
-
-// Function: kernel
-template <typename F, typename... ArgsT>
-cudaTask cudaFlow::kernel_on(
-  int d, dim3 g, dim3 b, size_t s, F&& f, ArgsT&&... args
-) {
-  
-  using traits = function_traits<F>;
-
-  static_assert(traits::arity == sizeof...(ArgsT), "arity mismatches");
-  
-  auto node = _graph.emplace_back(nstd::in_place_type_t<cudaNode::Kernel>{}, 
-    [d, g, b, s, f=(void*)f, args...] (cudaGraph_t& graph, cudaGraphNode_t& node) {
-
-      cudaKernelNodeParams p;
-      void* arguments[sizeof...(ArgsT)] = { (void*)(&args)... };
-      p.func = f;
-      p.gridDim = g;
-      p.blockDim = b;
-      p.sharedMemBytes = s;
-      p.kernelParams = arguments;
-      p.extra = nullptr;
-
-      cudaScopedDevice ctx(d);
-      TF_CHECK_CUDA(
-        ::cudaGraphAddKernelNode(&node, graph, nullptr, 0, &p),
-        "failed to create a cudaGraph node in kernel_on task"
-      );
-    }
-  );
-  
-  return cudaTask(node);
-}
-
-// Function: zero
-template <typename T>
-std::enable_if_t<
-  is_pod_v<T> && (sizeof(T)==1 || sizeof(T)==2 || sizeof(T)==4), 
-  cudaTask
-> 
-cudaFlow::zero(T* dst, size_t count) {
-  auto node = _graph.emplace_back(nstd::in_place_type_t<cudaNode::Memset>{},
-    [dst, count] (cudaGraph_t& graph, cudaGraphNode_t& node) {
-      cudaMemsetParams p;
-      p.dst = dst;
-      p.value = 0;
-      p.pitch = 0;
-      p.elementSize = sizeof(T);  // either 1, 2, or 4
-      p.width = count;
-      p.height = 1;
-      TF_CHECK_CUDA(
-        cudaGraphAddMemsetNode(&node, graph, nullptr, 0, &p),
-        "failed to create a cudaGraph node in zero task"
-      );
-    }
-  );
-  return cudaTask(node);
-}
-    
-// Function: fill
-template <typename T>
-std::enable_if_t<
-  is_pod_v<T> && (sizeof(T)==1 || sizeof(T)==2 || sizeof(T)==4), 
-  cudaTask
->
-cudaFlow::fill(T* dst, T value, size_t count) {
-  auto node = _graph.emplace_back(nstd::in_place_type_t<cudaNode::Memset>{},
-    [dst, value, count] (cudaGraph_t& graph, cudaGraphNode_t& node) {
-      cudaMemsetParams p;
-      p.dst = dst;
-
-      // perform bit-wise copy
-      p.value = 0;  // crucial
-      static_assert(sizeof(T) <= sizeof(p.value), "internal error");
-      std::memcpy(&p.value, &value, sizeof(T));
-
-      p.pitch = 0;
-      p.elementSize = sizeof(T);  // either 1, 2, or 4
-      p.width = count;
-      p.height = 1;
-      TF_CHECK_CUDA(
-        cudaGraphAddMemsetNode(&node, graph, nullptr, 0, &p),
-        "failed to create a cudaGraph node in fill task"
-      );
-    }
-  );
-  return cudaTask(node);
-}
-
-// Function: copy
-template <
-  typename T,
-  std::enable_if_t<!std::is_same<T, void>::value, void>*
->
-cudaTask cudaFlow::copy(T* tgt, const T* src, size_t num) {
-
-  using U = std::decay_t<T>;
-
-  auto node = _graph.emplace_back(nstd::in_place_type_t<cudaNode::Copy>{}, 
-    [tgt, src, num] (cudaGraph_t& graph, cudaGraphNode_t& node) {
-
-      cudaMemcpy3DParms p;
-      p.srcArray = nullptr;
-      p.srcPos = ::make_cudaPos(0, 0, 0);
-      p.srcPtr = ::make_cudaPitchedPtr(const_cast<T*>(src), num*sizeof(U), num, 1);
-      p.dstArray = nullptr;
-      p.dstPos = ::make_cudaPos(0, 0, 0);
-      p.dstPtr = ::make_cudaPitchedPtr(tgt, num*sizeof(U), num, 1);
-      p.extent = ::make_cudaExtent(num*sizeof(U), 1, 1);
-      p.kind = cudaMemcpyDefault;
-
-      TF_CHECK_CUDA(
-        cudaGraphAddMemcpyNode(&node, graph, nullptr, 0, &p),
-        "failed to create a cudaGraph node in copy task"
-      );
-    }
-  );
-
-  return cudaTask(node);
-}
-
-// Function: memset
-inline cudaTask cudaFlow::memset(void* dst, int ch, size_t count) {
-
-  auto node = _graph.emplace_back(nstd::in_place_type_t<cudaNode::Memset>{},
-    [dst, ch, count] (cudaGraph_t& graph, cudaGraphNode_t& node) {
-      cudaMemsetParams p;
-      p.dst = dst;
-      p.value = ch;
-      p.pitch = 0;
-      //p.elementSize = (count & 1) == 0 ? ((count & 3) == 0 ? 4 : 2) : 1;
-      //p.width = (count & 1) == 0 ? ((count & 3) == 0 ? count >> 2 : count >> 1) : count;
-      p.elementSize = 1;  // either 1, 2, or 4
-      p.width = count;
-      p.height = 1;
-      TF_CHECK_CUDA(
-        cudaGraphAddMemsetNode(&node, graph, nullptr, 0, &p),
-        "failed to create a cudaGraph node in memset task"
-      );
-    }
-  );
-  
-  return cudaTask(node);
-}
-
-// Function: memcpy
-inline cudaTask cudaFlow::memcpy(void* tgt, const void* src, size_t bytes) {
-  auto node = _graph.emplace_back(nstd::in_place_type_t<cudaNode::Copy>{},
-    [tgt, src, bytes] (cudaGraph_t& graph, cudaGraphNode_t& node) {
-      // Parameters in cudaPitchedPtr
-      // d   - Pointer to allocated memory
-      // p   - Pitch of allocated memory in bytes
-      // xsz - Logical width of allocation in elements
-      // ysz - Logical height of allocation in elements
-      cudaMemcpy3DParms p;
-      p.srcArray = nullptr;
-      p.srcPos = ::make_cudaPos(0, 0, 0);
-      p.srcPtr = ::make_cudaPitchedPtr(const_cast<void*>(src), bytes, bytes, 1);
-      p.dstArray = nullptr;
-      p.dstPos = ::make_cudaPos(0, 0, 0);
-      p.dstPtr = ::make_cudaPitchedPtr(tgt, bytes, bytes, 1);
-      p.extent = ::make_cudaExtent(bytes, 1, 1);
-      p.kind = cudaMemcpyDefault;
-      TF_CHECK_CUDA(
-        cudaGraphAddMemcpyNode(&node, graph, nullptr, 0, &p),
-        "failed to create a cudaGraph node in memcpy task"
-      );
-    }
-  );
-  return cudaTask(node);
-}
-
-}  // end of namespace tf -----------------------------------------------------
-
-
diff --git a/bundled/taskflow-2.5.0/include/taskflow/cuda/cuda_graph.hpp b/bundled/taskflow-2.5.0/include/taskflow/cuda/cuda_graph.hpp
deleted file mode 100644 (file)
index cb42617..0000000
+++ /dev/null
@@ -1,310 +0,0 @@
-#pragma once
-
-#include "cuda_device.hpp"
-
-#include "../utility/object_pool.hpp"
-#include "../utility/traits.hpp"
-#include "../utility/passive_vector.hpp"
-#include "../nstd/variant.hpp"
-#include "../nstd/optional.hpp"
-
-namespace tf {
-
-// ----------------------------------------------------------------------------
-// cudaNode class
-// ----------------------------------------------------------------------------
-
-// class: cudaNode
-class cudaNode {
-  
-  friend class cudaFlow;
-  friend class cudaGraph;
-  friend class cudaTask;
-
-  friend class Taskflow;
-  friend class Executor;
-
-  
-  // Noop handle
-  struct Noop {
-
-    template <typename C>
-    Noop(C&&);
-
-    std::function<void(cudaGraph_t&, cudaGraphNode_t&)> work;
-  };
-
-  //// Host handle
-  //struct Host {
-
-  //  template <typename C>
-  //  Host(C&&);
-  //  
-  //  std::function<void(cudaGraph_t&, cudaGraphNode_t&)> work;
-  //};
-
-  // Memset handle
-  struct Memset {
-    
-    template <typename C>
-    Memset(C&&);
-
-    std::function<void(cudaGraph_t&, cudaGraphNode_t&)> work;
-  };
-
-  // Copy handle
-  struct Copy {
-    
-    template <typename C>
-    Copy(C&&);
-
-    std::function<void(cudaGraph_t&, cudaGraphNode_t&)> work;
-  };
-  
-  // Kernel handle
-  struct Kernel {
-    
-    template <typename C>
-    Kernel(C&&);
-
-    std::function<void(cudaGraph_t&, cudaGraphNode_t&)> work;
-  };
-
-  using handle_t = nstd::variant<
-    nstd::monostate, 
-    Noop, 
-    //Host, 
-    Memset, 
-    Copy, 
-    Kernel
-  >;
-  
-  // variant index
-  constexpr static auto NOOP   = get_index_v<Noop, handle_t>;
-  //constexpr static auto HOST   = get_index_v<Host, handle_t>;
-  constexpr static auto MEMSET = get_index_v<Memset, handle_t>;
-  constexpr static auto COPY   = get_index_v<Copy, handle_t>; 
-  constexpr static auto KERNEL = get_index_v<Kernel, handle_t>;
-
-  public:
-    
-    template <typename... ArgsT>
-    cudaNode(ArgsT&&...);
-
-  private:
-
-    std::string _name;
-    
-    handle_t _handle;
-
-    cudaGraphNode_t _native_handle {nullptr};
-
-    PassiveVector<cudaNode*> _successors;
-
-    void _precede(cudaNode*);
-};
-
-// ----------------------------------------------------------------------------
-// cudaGraph class
-// ----------------------------------------------------------------------------
-
-// class: cudaGraph
-class cudaGraph {
-
-  friend class cudaFlow;
-  friend class cudaNode;
-  friend class cudaTask;
-  
-  friend class Taskflow;
-  friend class Executor;
-
-  public:
-
-    ~cudaGraph();
-
-    template <typename... ArgsT>
-    cudaNode* emplace_back(ArgsT&&...);
-
-    cudaGraph_t native_handle();
-
-    void clear();
-
-    bool empty() const;
-
-  private:
-    
-    cudaGraph_t _native_handle {nullptr};
-
-    std::vector<std::unique_ptr<cudaNode>> _nodes;
-
-    void _make_native_graph();
-};
-
-// ----------------------------------------------------------------------------
-// cudaNode definitions
-// ----------------------------------------------------------------------------
-
-//// Host handle constructor
-//template <typename C>
-//cudaNode::Host::Host(C&& c) : work {std::forward<C>(c)} {
-//}
-
-// Noop handle constructor
-template <typename C>
-cudaNode::Noop::Noop(C&& c) : work {std::forward<C>(c)} {
-}
-
-// Memset handle constructor
-template <typename C>
-cudaNode::Memset::Memset(C&& c) : work {std::forward<C>(c)} {
-}
-
-// Copy handle constructor
-template <typename C>
-cudaNode::Copy::Copy(C&& c) : work {std::forward<C>(c)} {
-}
-
-// Kernel handle constructor
-template <typename C>
-cudaNode::Kernel::Kernel(C&& c) : work {std::forward<C>(c)} {
-}
-
-// Constructor
-template <typename... ArgsT>
-cudaNode::cudaNode(ArgsT&&... args) : _handle {std::forward<ArgsT>(args)...} {
-}
-
-// Procedure: _precede
-inline void cudaNode::_precede(cudaNode* v) {
-  _successors.push_back(v);
-}
-
-// ----------------------------------------------------------------------------
-// cudaGraph definitions
-// ----------------------------------------------------------------------------
-
-// Destructor
-inline cudaGraph::~cudaGraph() {
-  if(_native_handle) {
-    cudaGraphDestroy(_native_handle);
-  }
-}
-
-// Function: empty
-inline bool cudaGraph::empty() const {
-  return _nodes.empty();
-}
-
-// Procedure: clear
-inline void cudaGraph::clear() {
-
-  _nodes.clear();
-
-  if(_native_handle) {
-    TF_CHECK_CUDA(
-      cudaGraphDestroy(_native_handle), "failed to destroy a cudaGraph on clear"
-    );
-    _native_handle = nullptr;
-  }
-}
-    
-// Function: emplace_back
-template <typename... ArgsT>
-cudaNode* cudaGraph::emplace_back(ArgsT&&... args) {
-  auto node = std::make_unique<cudaNode>(std::forward<ArgsT>(args)...);
-  _nodes.emplace_back(std::move(node));
-  return _nodes.back().get();
-}
-
-// Function: native_handle
-inline cudaGraph_t cudaGraph::native_handle() {
-  return _native_handle;
-}
-
-// Procedure: _make_native_graph
-inline void cudaGraph::_make_native_graph() {
-
-  //// TODO: must be nullptr
-  //if(_native_handle) {
-  //  TF_CHECK_CUDA(
-  //    cudaGraphDestroy(_native_handle), "failed to destroy the previous cudaGraph"
-  //  );
-  //  _native_handle = nullptr;
-  //}
-  //
-  //cudaScopedDevice ctx {d};
-  assert(_native_handle == nullptr);
-
-  TF_CHECK_CUDA(
-    cudaGraphCreate(&_native_handle, 0), "failed to create a cudaGraph"
-  );
-
-  // create nodes
-  for(auto& node : _nodes) {
-    switch(node->_handle.index()) {
-      case cudaNode::NOOP:
-        nstd::get<cudaNode::Noop>(node->_handle).work(
-          _native_handle, node->_native_handle
-        );
-      break;
-      
-      //case cudaNode::HOST:
-      //  nstd::get<cudaNode::Host>(node->_handle).work(
-      //    _native_handle, node->_native_handle
-      //  );
-      //break;
-
-      case cudaNode::MEMSET:
-        nstd::get<cudaNode::Memset>(node->_handle).work(
-          _native_handle, node->_native_handle
-        );
-      break;
-
-      case cudaNode::COPY:
-        nstd::get<cudaNode::Copy>(node->_handle).work(
-          _native_handle, node->_native_handle
-        );
-      break;
-
-      case cudaNode::KERNEL:
-        nstd::get<cudaNode::Kernel>(node->_handle).work(
-          _native_handle, node->_native_handle
-        );
-      break;
-    }
-  }
-
-  // create edges
-  for(auto& node : _nodes) {
-    for(auto succ : node->_successors){
-      TF_CHECK_CUDA(
-        ::cudaGraphAddDependencies(
-          _native_handle, &(node->_native_handle), &(succ->_native_handle), 1
-        ),
-        "failed to add a preceding link"
-      );
-    }
-  }
-
-}
-
-
-//inline void cudaGraph::run() {
-//  cudaGraphExec_t graphExec;
-//  TF_CHECK_CUDA(
-//    cudaGraphInstantiate(&graphExec, _handle, nullptr, nullptr, 0),
-//    "failed to create an executable cudaGraph"
-//  );
-//  TF_CHECK_CUDA(cudaGraphLaunch(graphExec, 0), "failed to launch cudaGraph")
-//  TF_CHECK_CUDA(cudaStreamSynchronize(0), "failed to sync cudaStream");
-//  TF_CHECK_CUDA(
-//    cudaGraphExecDestroy(graphExec), "failed to destroy an executable cudaGraph"
-//  );
-//}
-
-
-
-
-
-}  // end of namespace tf -----------------------------------------------------
-
diff --git a/bundled/taskflow-2.5.0/include/taskflow/cuda/cuda_task.hpp b/bundled/taskflow-2.5.0/include/taskflow/cuda/cuda_task.hpp
deleted file mode 100644 (file)
index 670765f..0000000
+++ /dev/null
@@ -1,173 +0,0 @@
-#pragma once
-
-#include "cuda_graph.hpp"
-
-namespace tf {
-
-/**
-@class cudaTask
-
-@brief handle to a node in a cudaGraph
-*/
-class cudaTask {
-
-  friend class cudaFlow;
-
-  public:
-    
-    /**
-    @brief constructs an empty cudaTask
-    */
-    cudaTask() = default;
-
-    /**
-    @brief copy-constructs a cudaTask
-    */
-    cudaTask(const cudaTask&) = default;
-
-    /**
-    @brief copy-assigns a cudaTask
-    */
-    cudaTask& operator = (const cudaTask&) = default;
-
-    /**
-    @brief adds precedence links from this to other tasks
-
-    @tparam Ts... parameter pack
-
-    @param tasks one or multiple tasks
-
-    @return @c *this
-    */
-    template <typename... Ts>
-    cudaTask& precede(Ts&&... tasks);
-    
-    /**
-    @brief adds precedence links from other tasks to this
-
-    @tparam Ts... parameter pack
-
-    @param tasks one or multiple tasks
-
-    @return @c *this
-    */
-    template <typename... Ts>
-    cudaTask& succeed(Ts&&... tasks);
-    
-    /**
-    @brief assigns a name to the task
-
-    @param name a @std_string acceptable string
-
-    @return @c *this
-    */
-    cudaTask& name(const std::string& name);
-    
-    /**
-    @brief queries the name of the task
-    */
-    const std::string& name() const;
-
-    /**
-    @brief queries the number of successors
-    */
-    size_t num_successors() const;
-
-    /**
-    @brief queries if the task is associated with a cudaNode
-    */
-    bool empty() const;
-
-  private:
-    
-    cudaTask(cudaNode*);
-
-    cudaNode* _node {nullptr};
-    
-    /// @private
-    template <typename T>
-    void _precede(T&&);
-
-    /// @private
-    template <typename T, typename... Ts>
-    void _precede(T&&, Ts&&...);
-    
-    /// @private
-    template <typename T>
-    void _succeed(T&&);
-
-    // @private
-    template <typename T, typename... Ts>
-    void _succeed(T&&, Ts&&...);
-};
-
-// Constructor
-inline cudaTask::cudaTask(cudaNode* node) : _node {node} {
-}
-
-// Function: precede
-template <typename... Ts>
-cudaTask& cudaTask::precede(Ts&&... tasks) {
-  _precede(std::forward<Ts>(tasks)...);
-  return *this;
-}
-
-/// @private
-// Procedure: precede
-template <typename T>
-void cudaTask::_precede(T&& other) {
-  _node->_precede(other._node);
-}
-
-/// @private
-// Procedure: _precede
-template <typename T, typename... Ts>
-void cudaTask::_precede(T&& task, Ts&&... others) {
-  _precede(std::forward<T>(task));
-  _precede(std::forward<Ts>(others)...);
-}
-
-// Function: succeed
-template <typename... Ts>
-cudaTask& cudaTask::succeed(Ts&&... tasks) {
-  _succeed(std::forward<Ts>(tasks)...);
-  return *this;
-}
-
-/// @private
-// Procedure: _succeed
-template <typename T>
-void cudaTask::_succeed(T&& other) {
-  other._node->_precede(_node);
-}
-
-/// @private
-// Procedure: _succeed
-template <typename T, typename... Ts>
-void cudaTask::_succeed(T&& task, Ts&&... others) {
-  _succeed(std::forward<T>(task));
-  _succeed(std::forward<Ts>(others)...);
-}
-
-// Function: empty
-inline bool cudaTask::empty() const {
-  return _node == nullptr;
-}
-
-// Function: name
-inline cudaTask& cudaTask::name(const std::string& name) {
-  _node->_name = name;
-  return *this;
-}
-
-// Function: name
-inline const std::string& cudaTask::name() const {
-  return _node->_name;
-}
-
-// Function: num_successors
-inline size_t cudaTask::num_successors() const {
-  return _node->_successors.size();
-}
-
-}  // end of namespace tf -----------------------------------------------------
diff --git a/bundled/taskflow-2.5.0/include/taskflow/declarations.hpp b/bundled/taskflow-2.5.0/include/taskflow/declarations.hpp
deleted file mode 100644 (file)
index 3047b2f..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-#pragma once
-
-namespace tf {
-
-// ----------------------------------------------------------------------------
-// forward declarations
-// ----------------------------------------------------------------------------
-
-// taskflow
-class Node;
-class Graph;
-class FlowBuilder;
-class Subflow;
-class Task;
-class TaskView;
-class Taskflow;
-class Topology;
-class Executor;
-class WorkerView;
-class ObserverInterface;
-class ChromeTracingObserver;
-class TFProfObserver;
-
-// cudaflow
-class cudaNode;
-class cudaGraph;
-class cudaTask;
-class cudaFlow;
-
-
-
-}  // end of namespace tf -----------------------------------------------------
-
-
-
-
diff --git a/bundled/taskflow-2.5.0/include/taskflow/nstd/any.hpp b/bundled/taskflow-2.5.0/include/taskflow/nstd/any.hpp
deleted file mode 100644 (file)
index a27000f..0000000
+++ /dev/null
@@ -1,703 +0,0 @@
-//
-// Copyright (c) 2016-2018 Martin Moene
-//
-// https://github.com/martinmoene/any-lite
-//
-// Distributed under the Boost Software License, Version 1.0.
-// (See accompanying file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
-
-#pragma once
-
-#ifndef NSTD_ANY_LITE_HPP
-#define NSTD_ANY_LITE_HPP
-
-#define any_lite_MAJOR  0
-#define any_lite_MINOR  2
-#define any_lite_PATCH  0
-
-#define any_lite_VERSION  any_STRINGIFY(any_lite_MAJOR) "." any_STRINGIFY(any_lite_MINOR) "." any_STRINGIFY(any_lite_PATCH)
-
-#define any_STRINGIFY(  x )  any_STRINGIFY_( x )
-#define any_STRINGIFY_( x )  #x
-
-// any-lite configuration:
-
-#define any_ANY_DEFAULT  0
-#define any_ANY_NSTD   1
-#define any_ANY_STD      2
-
-#if !defined( any_CONFIG_SELECT_ANY )
-# define any_CONFIG_SELECT_ANY  ( any_HAVE_STD_ANY ? any_ANY_STD : any_ANY_NSTD )
-#endif
-
-// Control presence of exception handling (try and auto discover):
-
-#ifndef any_CONFIG_NO_EXCEPTIONS
-# if defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)
-#  define any_CONFIG_NO_EXCEPTIONS  0
-# else
-#  define any_CONFIG_NO_EXCEPTIONS  1
-# endif
-#endif
-
-// C++ language version detection (C++20 is speculative):
-// Note: VC14.0/1900 (VS2015) lacks too much from C++14.
-
-#ifndef   any_CPLUSPLUS
-# if defined(_MSVC_LANG ) && !defined(__clang__)
-#  define any_CPLUSPLUS  (_MSC_VER == 1900 ? 201103L : _MSVC_LANG )
-# else
-#  define any_CPLUSPLUS  __cplusplus
-# endif
-#endif
-
-#define any_CPP98_OR_GREATER  ( any_CPLUSPLUS >= 199711L )
-#define any_CPP11_OR_GREATER  ( any_CPLUSPLUS >= 201103L )
-#define any_CPP14_OR_GREATER  ( any_CPLUSPLUS >= 201402L )
-#define any_CPP17_OR_GREATER  ( any_CPLUSPLUS >= 201703L )
-#define any_CPP20_OR_GREATER  ( any_CPLUSPLUS >= 202000L )
-
-// Use C++17 std::any if available and requested:
-
-#if any_CPP17_OR_GREATER && defined(__has_include )
-# if __has_include( <any> )
-#  define any_HAVE_STD_ANY  1
-# else
-#  define any_HAVE_STD_ANY  0
-# endif
-#else
-# define  any_HAVE_STD_ANY  0
-#endif
-
-#define  any_USES_STD_ANY  ( (any_CONFIG_SELECT_ANY == any_ANY_STD) || ((any_CONFIG_SELECT_ANY == any_ANY_DEFAULT) && any_HAVE_STD_ANY) )
-
-//
-// in_place: code duplicated in any-lite, expected-lite, optional-lite, value-ptr-lite, variant-lite:
-//
-
-#ifndef nstd_lite_HAVE_IN_PLACE_TYPES
-#define nstd_lite_HAVE_IN_PLACE_TYPES  1
-
-// C++17 std::in_place in <utility>:
-
-#if any_CPP17_OR_GREATER
-
-#include <utility>
-
-namespace nstd {
-
-using std::in_place;
-using std::in_place_type;
-using std::in_place_index;
-using std::in_place_t;
-using std::in_place_type_t;
-using std::in_place_index_t;
-
-#define nstd_lite_in_place_t(      T)  std::in_place_t
-#define nstd_lite_in_place_type_t( T)  std::in_place_type_t<T>
-#define nstd_lite_in_place_index_t(K)  std::in_place_index_t<K>
-
-#define nstd_lite_in_place(      T)    std::in_place_t{}
-#define nstd_lite_in_place_type( T)    std::in_place_type_t<T>{}
-#define nstd_lite_in_place_index(K)    std::in_place_index_t<K>{}
-
-} // namespace nstd
-
-#else // any_CPP17_OR_GREATER
-
-#include <cstddef>
-
-namespace nstd {
-namespace detail {
-
-template< class T >
-struct in_place_type_tag {};
-
-template< std::size_t K >
-struct in_place_index_tag {};
-
-} // namespace detail
-
-struct in_place_t {};
-
-template< class T >
-inline in_place_t in_place( detail::in_place_type_tag<T> = detail::in_place_type_tag<T>() )
-{
-    return in_place_t();
-}
-
-template< std::size_t K >
-inline in_place_t in_place( detail::in_place_index_tag<K> = detail::in_place_index_tag<K>() )
-{
-    return in_place_t();
-}
-
-template< class T >
-inline in_place_t in_place_type( detail::in_place_type_tag<T> = detail::in_place_type_tag<T>() )
-{
-    return in_place_t();
-}
-
-template< std::size_t K >
-inline in_place_t in_place_index( detail::in_place_index_tag<K> = detail::in_place_index_tag<K>() )
-{
-    return in_place_t();
-}
-
-// mimic templated typedef:
-
-#define nstd_lite_in_place_t(      T)  nstd::in_place_t(&)( nstd::detail::in_place_type_tag<T>  )
-#define nstd_lite_in_place_type_t( T)  nstd::in_place_t(&)( nstd::detail::in_place_type_tag<T>  )
-#define nstd_lite_in_place_index_t(K)  nstd::in_place_t(&)( nstd::detail::in_place_index_tag<K> )
-
-#define nstd_lite_in_place(      T)    nstd::in_place_type<T>
-#define nstd_lite_in_place_type( T)    nstd::in_place_type<T>
-#define nstd_lite_in_place_index(K)    nstd::in_place_index<K>
-
-} // namespace nstd
-
-#endif // any_CPP17_OR_GREATER
-#endif // nstd_lite_HAVE_IN_PLACE_TYPES
-
-//
-// Using std::any:
-//
-
-#if any_USES_STD_ANY
-
-#include <any>
-#include <utility>
-
-namespace nstd {
-
-    using std::any;
-    using std::any_cast;
-    using std::make_any;
-    using std::swap;
-    using std::bad_any_cast;
-}
-
-#else // any_USES_STD_ANY
-
-#include <utility>
-
-// Compiler versions:
-//
-// MSVC++  6.0  _MSC_VER == 1200  any_COMPILER_MSVC_VERSION ==  60  (Visual Studio 6.0)
-// MSVC++  7.0  _MSC_VER == 1300  any_COMPILER_MSVC_VERSION ==  70  (Visual Studio .NET 2002)
-// MSVC++  7.1  _MSC_VER == 1310  any_COMPILER_MSVC_VERSION ==  71  (Visual Studio .NET 2003)
-// MSVC++  8.0  _MSC_VER == 1400  any_COMPILER_MSVC_VERSION ==  80  (Visual Studio 2005)
-// MSVC++  9.0  _MSC_VER == 1500  any_COMPILER_MSVC_VERSION ==  90  (Visual Studio 2008)
-// MSVC++ 10.0  _MSC_VER == 1600  any_COMPILER_MSVC_VERSION == 100  (Visual Studio 2010)
-// MSVC++ 11.0  _MSC_VER == 1700  any_COMPILER_MSVC_VERSION == 110  (Visual Studio 2012)
-// MSVC++ 12.0  _MSC_VER == 1800  any_COMPILER_MSVC_VERSION == 120  (Visual Studio 2013)
-// MSVC++ 14.0  _MSC_VER == 1900  any_COMPILER_MSVC_VERSION == 140  (Visual Studio 2015)
-// MSVC++ 14.1  _MSC_VER >= 1910  any_COMPILER_MSVC_VERSION == 141  (Visual Studio 2017)
-// MSVC++ 14.2  _MSC_VER >= 1920  any_COMPILER_MSVC_VERSION == 142  (Visual Studio 2019)
-
-#if defined(_MSC_VER ) && !defined(__clang__)
-# define any_COMPILER_MSVC_VER      (_MSC_VER )
-# define any_COMPILER_MSVC_VERSION  (_MSC_VER / 10 - 10 * ( 5 + (_MSC_VER < 1900 ) ) )
-#else
-# define any_COMPILER_MSVC_VER      0
-# define any_COMPILER_MSVC_VERSION  0
-#endif
-
-#define any_COMPILER_VERSION( major, minor, patch )  ( 10 * ( 10 * (major) + (minor) ) + (patch) )
-
-#if defined(__clang__)
-# define any_COMPILER_CLANG_VERSION  any_COMPILER_VERSION(__clang_major__, __clang_minor__, __clang_patchlevel__)
-#else
-# define any_COMPILER_CLANG_VERSION  0
-#endif
-
-#if defined(__GNUC__) && !defined(__clang__)
-# define any_COMPILER_GNUC_VERSION  any_COMPILER_VERSION(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
-#else
-# define any_COMPILER_GNUC_VERSION  0
-#endif
-
-// half-open range [lo..hi):
-//#define any_BETWEEN( v, lo, hi ) ( (lo) <= (v) && (v) < (hi) )
-
-// Presence of language and library features:
-
-#define any_HAVE( feature )  ( any_HAVE_##feature )
-
-#ifdef _HAS_CPP0X
-# define any_HAS_CPP0X  _HAS_CPP0X
-#else
-# define any_HAS_CPP0X  0
-#endif
-
-#define any_CPP11_90   (any_CPP11_OR_GREATER || any_COMPILER_MSVC_VER >= 1500)
-#define any_CPP11_100  (any_CPP11_OR_GREATER || any_COMPILER_MSVC_VER >= 1600)
-#define any_CPP11_120  (any_CPP11_OR_GREATER || any_COMPILER_MSVC_VER >= 1800)
-#define any_CPP11_140  (any_CPP11_OR_GREATER || any_COMPILER_MSVC_VER >= 1900)
-
-#define any_CPP14_000  (any_CPP14_OR_GREATER)
-#define any_CPP17_000  (any_CPP17_OR_GREATER)
-
-// Presence of C++11 language features:
-
-#define any_HAVE_CONSTEXPR_11           any_CPP11_140
-#define any_HAVE_DEFAULT_FUNCTION_TEMPLATE_ARG \
-                                        any_CPP11_120
-#define any_HAVE_INITIALIZER_LIST       any_CPP11_120
-#define any_HAVE_NOEXCEPT               any_CPP11_140
-#define any_HAVE_NULLPTR                any_CPP11_100
-#define any_HAVE_TYPE_TRAITS            any_CPP11_90
-#define any_HAVE_STATIC_ASSERT          any_CPP11_100
-#define any_HAVE_ADD_CONST              any_CPP11_90
-#define any_HAVE_REMOVE_REFERENCE       any_CPP11_90
-
-#define any_HAVE_TR1_ADD_CONST          (!! any_COMPILER_GNUC_VERSION )
-#define any_HAVE_TR1_REMOVE_REFERENCE   (!! any_COMPILER_GNUC_VERSION )
-#define any_HAVE_TR1_TYPE_TRAITS        (!! any_COMPILER_GNUC_VERSION )
-
-// Presence of C++14 language features:
-
-#define any_HAVE_CONSTEXPR_14           any_CPP14_000
-
-// Presence of C++17 language features:
-
-#define any_HAVE_NODISCARD              any_CPP17_000
-
-// Presence of C++ language features:
-
-#if any_HAVE_CONSTEXPR_11
-# define any_constexpr constexpr
-#else
-# define any_constexpr /*constexpr*/
-#endif
-
-#if any_HAVE_CONSTEXPR_14
-# define any_constexpr14 constexpr
-#else
-# define any_constexpr14 /*constexpr*/
-#endif
-
-#if any_HAVE_NOEXCEPT
-# define any_noexcept noexcept
-#else
-# define any_noexcept /*noexcept*/
-#endif
-
-#if any_HAVE_NULLPTR
-# define any_nullptr nullptr
-#else
-# define any_nullptr NULL
-#endif
-
-#if any_HAVE_NODISCARD
-# define any_nodiscard [[nodiscard]]
-#else
-# define any_nodiscard /*[[nodiscard]]*/
-#endif
-
-// additional includes:
-
-#if any_CONFIG_NO_EXCEPTIONS
-# include <cassert>
-#else
-# include <typeinfo>
-#endif
-
-#if ! any_HAVE_NULLPTR
-# include <cstddef>
-#endif
-
-#if any_HAVE_INITIALIZER_LIST
-# include <initializer_list>
-#endif
-
-#if any_HAVE_TYPE_TRAITS
-# include <type_traits>
-#elif any_HAVE_TR1_TYPE_TRAITS
-# include <tr1/type_traits>
-#endif
-
-// Method enabling
-
-#if any_CPP11_OR_GREATER
-
-#define any_REQUIRES_0(...) \
-    template< bool B = (__VA_ARGS__), typename std::enable_if<B, int>::type = 0 >
-
-#define any_REQUIRES_T(...) \
-    , typename = typename std::enable_if< (__VA_ARGS__), nstd::any_lite::detail::enabler >::type
-
-#define any_REQUIRES_R(R, ...) \
-    typename std::enable_if<__VA_ARGS__, R>::type
-
-#define any_REQUIRES_A(...) \
-    , typename std::enable_if<__VA_ARGS__, void*>::type = nullptr
-
-#endif
-
-//
-// any:
-//
-
-namespace nstd {  namespace any_lite {
-
-// C++11 emulation:
-
-namespace std11 {
-
-#if any_HAVE_ADD_CONST
-
-using std::add_const;
-
-#elif any_HAVE_TR1_ADD_CONST
-
-using std::tr1::add_const;
-
-#else
-
-template< class T > struct add_const { typedef const T type; };
-
-#endif // any_HAVE_ADD_CONST
-
-#if any_HAVE_REMOVE_REFERENCE
-
-using std::remove_reference;
-
-#elif any_HAVE_TR1_REMOVE_REFERENCE
-
-using std::tr1::remove_reference;
-
-#else
-
-template< class T > struct remove_reference     { typedef T type; };
-template< class T > struct remove_reference<T&> { typedef T type; };
-
-#endif // any_HAVE_REMOVE_REFERENCE
-
-} // namespace std11
-
-namespace detail {
-
-// for any_REQUIRES_T
-
-/*enum*/ class enabler{};
-
-} // namespace detail
-
-#if ! any_CONFIG_NO_EXCEPTIONS
-
-class bad_any_cast : public std::bad_cast
-{
-public:
-#if any_CPP11_OR_GREATER
-    virtual const char* what() const any_noexcept
-#else
-    virtual const char* what() const throw()
-#endif
-   {
-      return "any-lite: bad any_cast";
-   }
-};
-
-#endif // any_CONFIG_NO_EXCEPTIONS
-
-class any
-{
-public:
-    any_constexpr any() any_noexcept
-    : content( any_nullptr )
-    {}
-
-    any( any const & other )
-    : content( other.content ? other.content->clone() : any_nullptr )
-    {}
-
-#if any_CPP11_OR_GREATER
-
-    any( any && other ) any_noexcept
-    : content( std::move( other.content ) )
-    {
-        other.content = any_nullptr;
-    }
-
-    template<
-        class ValueType, class T = typename std::decay<ValueType>::type
-        any_REQUIRES_T( ! std::is_same<T, any>::value )
-    >
-    any( ValueType && value ) any_noexcept
-    : content( new holder<T>( std::forward<ValueType>( value ) ) )
-    {}
-
-    template<
-        class T, class... Args
-        any_REQUIRES_T( std::is_constructible<T, Args&&...>::value )
-    >
-    explicit any( nstd_lite_in_place_type_t(T), Args&&... args )
-    : content( new holder<T>( T( std::forward<Args>(args)... ) ) )
-    {}
-
-    template<
-        class T, class U, class... Args
-        any_REQUIRES_T( std::is_constructible<T, std::initializer_list<U>&, Args&&...>::value )
-    >
-    explicit any( nstd_lite_in_place_type_t(T), std::initializer_list<U> il, Args&&... args )
-    : content( new holder<T>( T( il, std::forward<Args>(args)... ) ) )
-    {}
-
-#else
-
-    template< class ValueType >
-    any( ValueType const & value )
-    : content( new holder<ValueType>( value ) )
-    {}
-
-#endif // any_CPP11_OR_GREATER
-
-    ~any()
-    {
-        reset();
-    }
-
-    any & operator=( any const & other )
-    {
-        any( other ).swap( *this );
-        return *this;
-    }
-
-#if any_CPP11_OR_GREATER
-
-    any & operator=( any && other ) any_noexcept
-    {
-        any( std::move( other ) ).swap( *this );
-        return *this;
-    }
-
-    template<
-        class ValueType, class T = typename std::decay<ValueType>::type
-        any_REQUIRES_T( ! std::is_same<T, any>::value )
-    >
-    any & operator=( ValueType && value )
-    {
-        any( std::move( value ) ).swap( *this );
-        return *this;
-    }
-
-    template< class T, class... Args >
-    void emplace( Args && ... args )
-    {
-        any( T( std::forward<Args>(args)... ) ).swap( *this );
-    }
-
-    template<
-        class T, class U, class... Args
-        any_REQUIRES_T( std::is_constructible<T, std::initializer_list<U>&, Args&&...>::value )
-    >
-    void emplace( std::initializer_list<U> il, Args&&... args )
-    {
-        any( T( il, std::forward<Args>(args)... ) ).swap( *this );
-    }
-
-#else
-
-    template< class ValueType >
-    any & operator=( ValueType const & value )
-    {
-        any( value ).swap( *this );
-        return *this;
-    }
-
-#endif // any_CPP11_OR_GREATER
-
-    void reset() any_noexcept
-    {
-        delete content; content = any_nullptr;
-    }
-
-    void swap( any & other ) any_noexcept
-    {
-        std::swap( content, other.content );
-    }
-
-    bool has_value() const any_noexcept
-    {
-        return content != any_nullptr;
-    }
-
-    const std::type_info & type() const any_noexcept
-    {
-        return has_value() ? content->type() : typeid( void );
-    }
-
-    //
-    // non-standard:
-    //
-
-    template< class ValueType >
-    const ValueType * to_ptr() const
-    {
-        return &( static_cast<holder<ValueType> *>( content )->held );
-    }
-
-    template< class ValueType >
-    ValueType * to_ptr()
-    {
-        return &( static_cast<holder<ValueType> *>( content )->held );
-    }
-
-private:
-    class placeholder
-    {
-    public:
-        virtual ~placeholder()
-        {
-        }
-
-        virtual std::type_info const & type() const = 0;
-
-        virtual placeholder * clone() const = 0;
-    };
-
-    template< typename ValueType >
-    class holder : public placeholder
-    {
-    public:
-        holder( ValueType const & value )
-        : held( value )
-        {}
-
-#if any_CPP11_OR_GREATER
-        holder( ValueType && value )
-        : held( std::move( value ) )
-        {}
-#endif
-
-        virtual std::type_info const & type() const
-        {
-            return typeid( ValueType );
-        }
-
-        virtual placeholder * clone() const
-        {
-            return new holder( held );
-        }
-
-        ValueType held;
-    };
-
-    placeholder * content;
-};
-
-inline void swap( any & x, any & y ) any_noexcept
-{
-    x.swap( y );
-}
-
-#if any_CPP11_OR_GREATER
-
-template< class T, class ...Args >
-inline any make_any( Args&& ...args )
-{
-    return any( nstd_lite_in_place_type(T), std::forward<Args>(args)...);
-}
-
-template< class T, class U, class ...Args >
-inline any make_any( std::initializer_list<U> il, Args&& ...args )
-{
-    return any( nstd_lite_in_place_type(T), il, std::forward<Args>(args)...);
-}
-
-#endif // any_CPP11_OR_GREATER
-
-template<
-    class ValueType
-#if any_HAVE_DEFAULT_FUNCTION_TEMPLATE_ARG
-//  any_REQUIRES_T(...) Allow for VC120 (VS2013):
-    , typename = typename std::enable_if< (std::is_reference<ValueType>::value || std::is_copy_constructible<ValueType>::value), nstd::any_lite::detail::enabler >::type
-#endif
->
-any_nodiscard inline ValueType any_cast( any const & operand )
-{
-   const ValueType * result = any_cast< typename std11::add_const< typename std11::remove_reference<ValueType>::type >::type >( &operand );
-
-#if any_CONFIG_NO_EXCEPTIONS
-   assert( result );
-#else
-   if ( ! result )
-   {
-       throw bad_any_cast();
-   }
-#endif
-
-   return *result;
-}
-
-template<
-    class ValueType
-#if any_HAVE_DEFAULT_FUNCTION_TEMPLATE_ARG
-//  any_REQUIRES_T(...) Allow for VC120 (VS2013):
-    , typename = typename std::enable_if< (std::is_reference<ValueType>::value || std::is_copy_constructible<ValueType>::value), nstd::any_lite::detail::enabler >::type
-#endif
->
-any_nodiscard inline ValueType any_cast( any & operand )
-{
-   const ValueType * result = any_cast< typename std11::remove_reference<ValueType>::type >( &operand );
-
-#if any_CONFIG_NO_EXCEPTIONS
-   assert( result );
-#else
-   if ( ! result )
-   {
-       throw bad_any_cast();
-   }
-#endif
-
-   return *result;
-}
-
-#if any_CPP11_OR_GREATER
-
-template<
-    class ValueType
-#if any_HAVE_DEFAULT_FUNCTION_TEMPLATE_ARG
-    any_REQUIRES_T( std::is_reference<ValueType>::value || std::is_copy_constructible<ValueType>::value )
-#endif
->
-any_nodiscard inline ValueType any_cast( any && operand )
-{
-   const ValueType * result = any_cast< typename std11::remove_reference<ValueType>::type >( &operand );
-
-#if any_CONFIG_NO_EXCEPTIONS
-   assert( result );
-#else
-   if ( ! result )
-   {
-       throw bad_any_cast();
-   }
-#endif
-
-   return *result;
-}
-
-#endif // any_CPP11_OR_GREATER
-
-template< class ValueType >
-any_nodiscard inline ValueType const * any_cast( any const * operand ) any_noexcept
-{
-    return operand != any_nullptr && operand->type() == typeid(ValueType) ? operand->to_ptr<ValueType>() : any_nullptr;
-}
-
-template<class ValueType >
-any_nodiscard inline ValueType * any_cast( any * operand ) any_noexcept
-{
-    return operand != any_nullptr && operand->type() == typeid(ValueType) ? operand->to_ptr<ValueType>() : any_nullptr;
-}
-
-} // namespace any_lite
-
-using namespace any_lite;
-
-} // namespace nstd
-
-#endif // any_USES_STD_ANY
-
-#endif // NSTD_ANY_LITE_HPP
diff --git a/bundled/taskflow-2.5.0/include/taskflow/nstd/optional.hpp b/bundled/taskflow-2.5.0/include/taskflow/nstd/optional.hpp
deleted file mode 100644 (file)
index 578ea03..0000000
+++ /dev/null
@@ -1,1718 +0,0 @@
-//
-// Copyright (c) 2014-2018 Martin Moene
-//
-// https://github.com/martinmoene/optional-lite
-//
-// Distributed under the Boost Software License, Version 1.0.
-// (See accompanying file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
-
-#pragma once
-
-#define optional_lite_MAJOR  3
-#define optional_lite_MINOR  2
-#define optional_lite_PATCH  0
-
-#define optional_lite_VERSION  optional_STRINGIFY(optional_lite_MAJOR) "." optional_STRINGIFY(optional_lite_MINOR) "." optional_STRINGIFY(optional_lite_PATCH)
-
-#define optional_STRINGIFY(  x )  optional_STRINGIFY_( x )
-#define optional_STRINGIFY_( x )  #x
-
-// optional-lite configuration:
-
-#define optional_OPTIONAL_DEFAULT  0
-#define optional_OPTIONAL_NONSTD   1
-#define optional_OPTIONAL_STD      2
-
-#if !defined( optional_CONFIG_SELECT_OPTIONAL )
-# define optional_CONFIG_SELECT_OPTIONAL  ( optional_HAVE_STD_OPTIONAL ? optional_OPTIONAL_STD : optional_OPTIONAL_NONSTD )
-#endif
-
-// Control presence of exception handling (try and auto discover):
-
-#ifndef optional_CONFIG_NO_EXCEPTIONS
-# if defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)
-#  define optional_CONFIG_NO_EXCEPTIONS  0
-# else
-#  define optional_CONFIG_NO_EXCEPTIONS  1
-# endif
-#endif
-
-// C++ language version detection (C++20 is speculative):
-// Note: VC14.0/1900 (VS2015) lacks too much from C++14.
-
-#ifndef   optional_CPLUSPLUS
-# if defined(_MSVC_LANG ) && !defined(__clang__)
-#  define optional_CPLUSPLUS  (_MSC_VER == 1900 ? 201103L : _MSVC_LANG )
-# else
-#  define optional_CPLUSPLUS  __cplusplus
-# endif
-#endif
-
-#define optional_CPP98_OR_GREATER  ( optional_CPLUSPLUS >= 199711L )
-#define optional_CPP11_OR_GREATER  ( optional_CPLUSPLUS >= 201103L )
-#define optional_CPP11_OR_GREATER_ ( optional_CPLUSPLUS >= 201103L )
-#define optional_CPP14_OR_GREATER  ( optional_CPLUSPLUS >= 201402L )
-#define optional_CPP17_OR_GREATER  ( optional_CPLUSPLUS >= 201703L )
-#define optional_CPP20_OR_GREATER  ( optional_CPLUSPLUS >= 202000L )
-
-// C++ language version (represent 98 as 3):
-
-#define optional_CPLUSPLUS_V  ( optional_CPLUSPLUS / 100 - (optional_CPLUSPLUS > 200000 ? 2000 : 1994) )
-
-// Use C++17 std::optional if available and requested:
-
-#if optional_CPP17_OR_GREATER && defined(__has_include )
-# if __has_include( <optional> )
-#  define optional_HAVE_STD_OPTIONAL  1
-# else
-#  define optional_HAVE_STD_OPTIONAL  0
-# endif
-#else
-# define  optional_HAVE_STD_OPTIONAL  0
-#endif
-
-#define optional_USES_STD_OPTIONAL  ( (optional_CONFIG_SELECT_OPTIONAL == optional_OPTIONAL_STD) || ((optional_CONFIG_SELECT_OPTIONAL == optional_OPTIONAL_DEFAULT) && optional_HAVE_STD_OPTIONAL) )
-
-//
-// in_place: code duplicated in any-lite, expected-lite, optional-lite, value-ptr-lite, variant-lite:
-//
-
-#ifndef nonstd_lite_HAVE_IN_PLACE_TYPES
-#define nonstd_lite_HAVE_IN_PLACE_TYPES  1
-
-// C++17 std::in_place in <utility>:
-
-#if optional_CPP17_OR_GREATER
-
-#include <utility>
-
-namespace nonstd {
-
-using std::in_place;
-using std::in_place_type;
-using std::in_place_index;
-using std::in_place_t;
-using std::in_place_type_t;
-using std::in_place_index_t;
-
-#define nonstd_lite_in_place_t(      T)  std::in_place_t
-#define nonstd_lite_in_place_type_t( T)  std::in_place_type_t<T>
-#define nonstd_lite_in_place_index_t(K)  std::in_place_index_t<K>
-
-#define nonstd_lite_in_place(      T)    std::in_place_t{}
-#define nonstd_lite_in_place_type( T)    std::in_place_type_t<T>{}
-#define nonstd_lite_in_place_index(K)    std::in_place_index_t<K>{}
-
-} // namespace nonstd
-
-#else // optional_CPP17_OR_GREATER
-
-#include <cstddef>
-
-namespace nonstd {
-namespace detail {
-
-template< class T >
-struct in_place_type_tag {};
-
-template< std::size_t K >
-struct in_place_index_tag {};
-
-} // namespace detail
-
-struct in_place_t {};
-
-template< class T >
-inline in_place_t in_place( detail::in_place_type_tag<T> /*unused*/ = detail::in_place_type_tag<T>() )
-{
-    return in_place_t();
-}
-
-template< std::size_t K >
-inline in_place_t in_place( detail::in_place_index_tag<K> /*unused*/ = detail::in_place_index_tag<K>() )
-{
-    return in_place_t();
-}
-
-template< class T >
-inline in_place_t in_place_type( detail::in_place_type_tag<T> /*unused*/ = detail::in_place_type_tag<T>() )
-{
-    return in_place_t();
-}
-
-template< std::size_t K >
-inline in_place_t in_place_index( detail::in_place_index_tag<K> /*unused*/ = detail::in_place_index_tag<K>() )
-{
-    return in_place_t();
-}
-
-// mimic templated typedef:
-
-#define nonstd_lite_in_place_t(      T)  nonstd::in_place_t(&)( nonstd::detail::in_place_type_tag<T>  )
-#define nonstd_lite_in_place_type_t( T)  nonstd::in_place_t(&)( nonstd::detail::in_place_type_tag<T>  )
-#define nonstd_lite_in_place_index_t(K)  nonstd::in_place_t(&)( nonstd::detail::in_place_index_tag<K> )
-
-#define nonstd_lite_in_place(      T)    nonstd::in_place_type<T>
-#define nonstd_lite_in_place_type( T)    nonstd::in_place_type<T>
-#define nonstd_lite_in_place_index(K)    nonstd::in_place_index<K>
-
-} // namespace nonstd
-
-#endif // optional_CPP17_OR_GREATER
-#endif // nonstd_lite_HAVE_IN_PLACE_TYPES
-
-//
-// Using std::optional:
-//
-
-#if optional_USES_STD_OPTIONAL
-
-#include <optional>
-
-namespace nonstd {
-
-    using std::optional;
-    using std::bad_optional_access;
-    using std::hash;
-
-    using std::nullopt;
-    using std::nullopt_t;
-
-    using std::operator==;
-    using std::operator!=;
-    using std::operator<;
-    using std::operator<=;
-    using std::operator>;
-    using std::operator>=;
-    using std::make_optional;
-    using std::swap;
-}
-
-#else // optional_USES_STD_OPTIONAL
-
-#include <cassert>
-#include <utility>
-
-// optional-lite alignment configuration:
-
-#ifndef  optional_CONFIG_MAX_ALIGN_HACK
-# define optional_CONFIG_MAX_ALIGN_HACK  0
-#endif
-
-#ifndef  optional_CONFIG_ALIGN_AS
-// no default, used in #if defined()
-#endif
-
-#ifndef  optional_CONFIG_ALIGN_AS_FALLBACK
-# define optional_CONFIG_ALIGN_AS_FALLBACK  double
-#endif
-
-// Compiler warning suppression:
-
-#if defined(__clang__)
-# pragma clang diagnostic push
-# pragma clang diagnostic ignored "-Wundef"
-#elif defined(__GNUC__)
-# pragma GCC   diagnostic push
-# pragma GCC   diagnostic ignored "-Wundef"
-#elif defined(_MSC_VER )
-# pragma warning( push )
-#endif
-
-// half-open range [lo..hi):
-#define optional_BETWEEN( v, lo, hi ) ( (lo) <= (v) && (v) < (hi) )
-
-// Compiler versions:
-//
-// MSVC++  6.0  _MSC_VER == 1200  optional_COMPILER_MSVC_VERSION ==  60  (Visual Studio 6.0)
-// MSVC++  7.0  _MSC_VER == 1300  optional_COMPILER_MSVC_VERSION ==  70  (Visual Studio .NET 2002)
-// MSVC++  7.1  _MSC_VER == 1310  optional_COMPILER_MSVC_VERSION ==  71  (Visual Studio .NET 2003)
-// MSVC++  8.0  _MSC_VER == 1400  optional_COMPILER_MSVC_VERSION ==  80  (Visual Studio 2005)
-// MSVC++  9.0  _MSC_VER == 1500  optional_COMPILER_MSVC_VERSION ==  90  (Visual Studio 2008)
-// MSVC++ 10.0  _MSC_VER == 1600  optional_COMPILER_MSVC_VERSION == 100  (Visual Studio 2010)
-// MSVC++ 11.0  _MSC_VER == 1700  optional_COMPILER_MSVC_VERSION == 110  (Visual Studio 2012)
-// MSVC++ 12.0  _MSC_VER == 1800  optional_COMPILER_MSVC_VERSION == 120  (Visual Studio 2013)
-// MSVC++ 14.0  _MSC_VER == 1900  optional_COMPILER_MSVC_VERSION == 140  (Visual Studio 2015)
-// MSVC++ 14.1  _MSC_VER >= 1910  optional_COMPILER_MSVC_VERSION == 141  (Visual Studio 2017)
-// MSVC++ 14.2  _MSC_VER >= 1920  optional_COMPILER_MSVC_VERSION == 142  (Visual Studio 2019)
-
-#if defined(_MSC_VER ) && !defined(__clang__)
-# define optional_COMPILER_MSVC_VER      (_MSC_VER )
-# define optional_COMPILER_MSVC_VERSION  (_MSC_VER / 10 - 10 * ( 5 + (_MSC_VER < 1900 ) ) )
-#else
-# define optional_COMPILER_MSVC_VER      0
-# define optional_COMPILER_MSVC_VERSION  0
-#endif
-
-#define optional_COMPILER_VERSION( major, minor, patch )  ( 10 * (10 * (major) + (minor) ) + (patch) )
-
-#if defined(__GNUC__) && !defined(__clang__)
-# define optional_COMPILER_GNUC_VERSION   optional_COMPILER_VERSION(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
-#else
-# define optional_COMPILER_GNUC_VERSION   0
-#endif
-
-#if defined(__clang__)
-# define optional_COMPILER_CLANG_VERSION  optional_COMPILER_VERSION(__clang_major__, __clang_minor__, __clang_patchlevel__)
-#else
-# define optional_COMPILER_CLANG_VERSION  0
-#endif
-
-#if optional_BETWEEN(optional_COMPILER_MSVC_VERSION, 70, 140 )
-# pragma warning( disable: 4345 )   // initialization behavior changed
-#endif
-
-#if optional_BETWEEN(optional_COMPILER_MSVC_VERSION, 70, 150 )
-# pragma warning( disable: 4814 )   // in C++14 'constexpr' will not imply 'const'
-#endif
-
-// Presence of language and library features:
-
-#define optional_HAVE(FEATURE) ( optional_HAVE_##FEATURE )
-
-#ifdef _HAS_CPP0X
-# define optional_HAS_CPP0X  _HAS_CPP0X
-#else
-# define optional_HAS_CPP0X  0
-#endif
-
-// Unless defined otherwise below, consider VC14 as C++11 for optional-lite:
-
-#if optional_COMPILER_MSVC_VER >= 1900
-# undef  optional_CPP11_OR_GREATER
-# define optional_CPP11_OR_GREATER  1
-#endif
-
-#define optional_CPP11_90   (optional_CPP11_OR_GREATER_ || optional_COMPILER_MSVC_VER >= 1500)
-#define optional_CPP11_100  (optional_CPP11_OR_GREATER_ || optional_COMPILER_MSVC_VER >= 1600)
-#define optional_CPP11_110  (optional_CPP11_OR_GREATER_ || optional_COMPILER_MSVC_VER >= 1700)
-#define optional_CPP11_120  (optional_CPP11_OR_GREATER_ || optional_COMPILER_MSVC_VER >= 1800)
-#define optional_CPP11_140  (optional_CPP11_OR_GREATER_ || optional_COMPILER_MSVC_VER >= 1900)
-#define optional_CPP11_141  (optional_CPP11_OR_GREATER_ || optional_COMPILER_MSVC_VER >= 1910)
-
-#define optional_CPP11_140_490  ((optional_CPP11_OR_GREATER_ && optional_COMPILER_GNUC_VERSION >= 490) || (optional_COMPILER_MSVC_VER >= 1910))
-
-#define optional_CPP14_000  (optional_CPP14_OR_GREATER)
-#define optional_CPP17_000  (optional_CPP17_OR_GREATER)
-
-// Presence of C++11 language features:
-
-#define optional_HAVE_CONSTEXPR_11      optional_CPP11_140
-#define optional_HAVE_IS_DEFAULT        optional_CPP11_140
-#define optional_HAVE_NOEXCEPT          optional_CPP11_140
-#define optional_HAVE_NULLPTR           optional_CPP11_100
-#define optional_HAVE_REF_QUALIFIER     optional_CPP11_140_490
-#define optional_HAVE_INITIALIZER_LIST  optional_CPP11_140
-
-// Presence of C++14 language features:
-
-#define optional_HAVE_CONSTEXPR_14      optional_CPP14_000
-
-// Presence of C++17 language features:
-
-#define optional_HAVE_NODISCARD         optional_CPP17_000
-
-// Presence of C++ library features:
-
-#define optional_HAVE_CONDITIONAL       optional_CPP11_120
-#define optional_HAVE_REMOVE_CV         optional_CPP11_120
-#define optional_HAVE_TYPE_TRAITS       optional_CPP11_90
-
-#define optional_HAVE_TR1_TYPE_TRAITS   (!! optional_COMPILER_GNUC_VERSION )
-#define optional_HAVE_TR1_ADD_POINTER   (!! optional_COMPILER_GNUC_VERSION )
-
-// C++ feature usage:
-
-#if optional_HAVE( CONSTEXPR_11 )
-# define optional_constexpr  constexpr
-#else
-# define optional_constexpr  /*constexpr*/
-#endif
-
-#if optional_HAVE( IS_DEFAULT )
-# define optional_is_default  = default;
-#else
-# define optional_is_default  {}
-#endif
-
-#if optional_HAVE( CONSTEXPR_14 )
-# define optional_constexpr14  constexpr
-#else
-# define optional_constexpr14  /*constexpr*/
-#endif
-
-#if optional_HAVE( NODISCARD )
-# define optional_nodiscard  [[nodiscard]]
-#else
-# define optional_nodiscard  /*[[nodiscard]]*/
-#endif
-
-#if optional_HAVE( NOEXCEPT )
-# define optional_noexcept  noexcept
-#else
-# define optional_noexcept  /*noexcept*/
-#endif
-
-#if optional_HAVE( NULLPTR )
-# define optional_nullptr  nullptr
-#else
-# define optional_nullptr  NULL
-#endif
-
-#if optional_HAVE( REF_QUALIFIER )
-// NOLINTNEXTLINE( bugprone-macro-parentheses )
-# define optional_ref_qual  &
-# define optional_refref_qual  &&
-#else
-# define optional_ref_qual  /*&*/
-# define optional_refref_qual  /*&&*/
-#endif
-
-// additional includes:
-
-#if optional_CONFIG_NO_EXCEPTIONS
-// already included: <cassert>
-#else
-# include <stdexcept>
-#endif
-
-#if optional_CPP11_OR_GREATER
-# include <functional>
-#endif
-
-#if optional_HAVE( INITIALIZER_LIST )
-# include <initializer_list>
-#endif
-
-#if optional_HAVE( TYPE_TRAITS )
-# include <type_traits>
-#elif optional_HAVE( TR1_TYPE_TRAITS )
-# include <tr1/type_traits>
-#endif
-
-// Method enabling
-
-#if optional_CPP11_OR_GREATER
-
-#define optional_REQUIRES_0(...) \
-    template< bool B = (__VA_ARGS__), typename std::enable_if<B, int>::type = 0 >
-
-#define optional_REQUIRES_T(...) \
-    , typename std::enable_if< (__VA_ARGS__), int >::type = 0
-
-#define optional_REQUIRES_R(R, ...) \
-    typename std::enable_if< (__VA_ARGS__), R>::type
-
-#define optional_REQUIRES_A(...) \
-    , typename std::enable_if< (__VA_ARGS__), void*>::type = nullptr
-
-#endif
-
-//
-// optional:
-//
-
-namespace nonstd { namespace optional_lite {
-
-namespace std11 {
-
-#if optional_CPP11_OR_GREATER
-    using std::move;
-#else
-    template< typename T > T & move( T & t ) { return t; }
-#endif
-
-#if optional_HAVE( CONDITIONAL )
-    using std::conditional;
-#else
-    template< bool B, typename T, typename F > struct conditional              { typedef T type; };
-    template<         typename T, typename F > struct conditional<false, T, F> { typedef F type; };
-#endif // optional_HAVE_CONDITIONAL
-
-// gcc < 5:
-#if optional_CPP11_OR_GREATER
-#if optional_BETWEEN( optional_COMPILER_GNUC_VERSION, 1, 500 )
-    template< typename T > struct is_trivially_copy_constructible : std::true_type{};
-    template< typename T > struct is_trivially_move_constructible : std::true_type{};
-#else
-    using std::is_trivially_copy_constructible;
-    using std::is_trivially_move_constructible;
-#endif
-#endif
-} // namespace std11
-
-#if optional_CPP11_OR_GREATER
-
-/// type traits C++17:
-
-namespace std17 {
-
-#if optional_CPP17_OR_GREATER
-
-using std::is_swappable;
-using std::is_nothrow_swappable;
-
-#elif optional_CPP11_OR_GREATER
-
-namespace detail {
-
-using std::swap;
-
-struct is_swappable
-{
-    template< typename T, typename = decltype( swap( std::declval<T&>(), std::declval<T&>() ) ) >
-    static std::true_type test( int /*unused*/ );
-
-    template< typename >
-    static std::false_type test(...);
-};
-
-struct is_nothrow_swappable
-{
-    // wrap noexcept(expr) in separate function as work-around for VC140 (VS2015):
-
-    template< typename T >
-    static constexpr bool satisfies()
-    {
-        return noexcept( swap( std::declval<T&>(), std::declval<T&>() ) );
-    }
-
-    template< typename T >
-    static auto test( int /*unused*/ ) -> std::integral_constant<bool, satisfies<T>()>{}
-
-    template< typename >
-    static auto test(...) -> std::false_type;
-};
-
-} // namespace detail
-
-// is [nothow] swappable:
-
-template< typename T >
-struct is_swappable : decltype( detail::is_swappable::test<T>(0) ){};
-
-template< typename T >
-struct is_nothrow_swappable : decltype( detail::is_nothrow_swappable::test<T>(0) ){};
-
-#endif // optional_CPP17_OR_GREATER
-
-} // namespace std17
-
-/// type traits C++20:
-
-namespace std20 {
-
-template< typename T >
-struct remove_cvref
-{
-    typedef typename std::remove_cv< typename std::remove_reference<T>::type >::type type;
-};
-
-} // namespace std20
-
-#endif // optional_CPP11_OR_GREATER
-
-/// class optional
-
-template< typename T >
-class optional;
-
-namespace detail {
-
-// C++11 emulation:
-
-struct nulltype{};
-
-template< typename Head, typename Tail >
-struct typelist
-{
-    typedef Head head;
-    typedef Tail tail;
-};
-
-#if optional_CONFIG_MAX_ALIGN_HACK
-
-// Max align, use most restricted type for alignment:
-
-#define optional_UNIQUE(  name )       optional_UNIQUE2( name, __LINE__ )
-#define optional_UNIQUE2( name, line ) optional_UNIQUE3( name, line )
-#define optional_UNIQUE3( name, line ) name ## line
-
-#define optional_ALIGN_TYPE( type ) \
-    type optional_UNIQUE( _t ); struct_t< type > optional_UNIQUE( _st )
-
-template< typename T >
-struct struct_t { T _; };
-
-union max_align_t
-{
-    optional_ALIGN_TYPE( char );
-    optional_ALIGN_TYPE( short int );
-    optional_ALIGN_TYPE( int );
-    optional_ALIGN_TYPE( long int  );
-    optional_ALIGN_TYPE( float  );
-    optional_ALIGN_TYPE( double );
-    optional_ALIGN_TYPE( long double );
-    optional_ALIGN_TYPE( char * );
-    optional_ALIGN_TYPE( short int * );
-    optional_ALIGN_TYPE( int *  );
-    optional_ALIGN_TYPE( long int * );
-    optional_ALIGN_TYPE( float * );
-    optional_ALIGN_TYPE( double * );
-    optional_ALIGN_TYPE( long double * );
-    optional_ALIGN_TYPE( void * );
-
-#ifdef HAVE_LONG_LONG
-    optional_ALIGN_TYPE( long long );
-#endif
-
-    struct Unknown;
-
-    Unknown ( * optional_UNIQUE(_) )( Unknown );
-    Unknown * Unknown::* optional_UNIQUE(_);
-    Unknown ( Unknown::* optional_UNIQUE(_) )( Unknown );
-
-    struct_t< Unknown ( * )( Unknown)         > optional_UNIQUE(_);
-    struct_t< Unknown * Unknown::*            > optional_UNIQUE(_);
-    struct_t< Unknown ( Unknown::* )(Unknown) > optional_UNIQUE(_);
-};
-
-#undef optional_UNIQUE
-#undef optional_UNIQUE2
-#undef optional_UNIQUE3
-
-#undef optional_ALIGN_TYPE
-
-#elif defined( optional_CONFIG_ALIGN_AS ) // optional_CONFIG_MAX_ALIGN_HACK
-
-// Use user-specified type for alignment:
-
-#define optional_ALIGN_AS( unused ) \
-    optional_CONFIG_ALIGN_AS
-
-#else // optional_CONFIG_MAX_ALIGN_HACK
-
-// Determine POD type to use for alignment:
-
-#define optional_ALIGN_AS( to_align ) \
-    typename type_of_size< alignment_types, alignment_of< to_align >::value >::type
-
-template< typename T >
-struct alignment_of;
-
-template< typename T >
-struct alignment_of_hack
-{
-    char c;
-    T t;
-    alignment_of_hack();
-};
-
-template< size_t A, size_t S >
-struct alignment_logic
-{
-    enum { value = A < S ? A : S };
-};
-
-template< typename T >
-struct alignment_of
-{
-    enum { value = alignment_logic<
-        sizeof( alignment_of_hack<T> ) - sizeof(T), sizeof(T) >::value };
-};
-
-template< typename List, size_t N >
-struct type_of_size
-{
-    typedef typename std11::conditional<
-        N == sizeof( typename List::head ),
-            typename List::head,
-            typename type_of_size<typename List::tail, N >::type >::type type;
-};
-
-template< size_t N >
-struct type_of_size< nulltype, N >
-{
-    typedef optional_CONFIG_ALIGN_AS_FALLBACK type;
-};
-
-template< typename T>
-struct struct_t { T _; };
-
-#define optional_ALIGN_TYPE( type ) \
-    typelist< type , typelist< struct_t< type >
-
-struct Unknown;
-
-typedef
-    optional_ALIGN_TYPE( char ),
-    optional_ALIGN_TYPE( short ),
-    optional_ALIGN_TYPE( int ),
-    optional_ALIGN_TYPE( long ),
-    optional_ALIGN_TYPE( float ),
-    optional_ALIGN_TYPE( double ),
-    optional_ALIGN_TYPE( long double ),
-
-    optional_ALIGN_TYPE( char *),
-    optional_ALIGN_TYPE( short * ),
-    optional_ALIGN_TYPE( int * ),
-    optional_ALIGN_TYPE( long * ),
-    optional_ALIGN_TYPE( float * ),
-    optional_ALIGN_TYPE( double * ),
-    optional_ALIGN_TYPE( long double * ),
-
-    optional_ALIGN_TYPE( Unknown ( * )( Unknown ) ),
-    optional_ALIGN_TYPE( Unknown * Unknown::*     ),
-    optional_ALIGN_TYPE( Unknown ( Unknown::* )( Unknown ) ),
-
-    nulltype
-    > > > > > > >    > > > > > > >
-    > > > > > > >    > > > > > > >
-    > > > > > >
-    alignment_types;
-
-#undef optional_ALIGN_TYPE
-
-#endif // optional_CONFIG_MAX_ALIGN_HACK
-
-/// C++03 constructed union to hold value.
-
-template< typename T >
-union storage_t
-{
-//private:
-//    template< typename > friend class optional;
-
-    typedef T value_type;
-
-    storage_t() optional_is_default
-
-    explicit storage_t( value_type const & v )
-    {
-        construct_value( v );
-    }
-
-    void construct_value( value_type const & v )
-    {
-        ::new( value_ptr() ) value_type( v );
-    }
-
-#if optional_CPP11_OR_GREATER
-
-    explicit storage_t( value_type && v )
-    {
-        construct_value( std::move( v ) );
-    }
-
-    void construct_value( value_type && v )
-    {
-        ::new( value_ptr() ) value_type( std::move( v ) );
-    }
-
-    template< class... Args >
-    void emplace( Args&&... args )
-    {
-        ::new( value_ptr() ) value_type( std::forward<Args>(args)... );
-    }
-
-    template< class U, class... Args >
-    void emplace( std::initializer_list<U> il, Args&&... args )
-    {
-        ::new( value_ptr() ) value_type( il, std::forward<Args>(args)... );
-    }
-
-#endif
-
-    void destruct_value()
-    {
-        value_ptr()->~T();
-    }
-
-    optional_nodiscard value_type const * value_ptr() const
-    {
-        return as<value_type>();
-    }
-
-    value_type * value_ptr()
-    {
-        return as<value_type>();
-    }
-
-    optional_nodiscard value_type const & value() const optional_ref_qual
-    {
-        return * value_ptr();
-    }
-
-    value_type & value() optional_ref_qual
-    {
-        return * value_ptr();
-    }
-
-#if optional_HAVE( REF_QUALIFIER )
-
-    optional_nodiscard value_type const && value() const optional_refref_qual
-    {
-        return std::move( value() );
-    }
-
-    value_type && value() optional_refref_qual
-    {
-        return std::move( value() );
-    }
-
-#endif
-
-#if optional_CPP11_OR_GREATER
-
-    using aligned_storage_t = typename std::aligned_storage< sizeof(value_type), alignof(value_type) >::type;
-    aligned_storage_t data;
-
-#elif optional_CONFIG_MAX_ALIGN_HACK
-
-    typedef struct { unsigned char data[ sizeof(value_type) ]; } aligned_storage_t;
-
-    max_align_t hack;
-    aligned_storage_t data;
-
-#else
-    typedef optional_ALIGN_AS(value_type) align_as_type;
-
-    typedef struct { align_as_type data[ 1 + ( sizeof(value_type) - 1 ) / sizeof(align_as_type) ]; } aligned_storage_t;
-    aligned_storage_t data;
-
-#   undef optional_ALIGN_AS
-
-#endif // optional_CONFIG_MAX_ALIGN_HACK
-
-    optional_nodiscard void * ptr() optional_noexcept
-    {
-        return &data;
-    }
-
-    optional_nodiscard void const * ptr() const optional_noexcept
-    {
-        return &data;
-    }
-
-    template <typename U>
-    optional_nodiscard U * as()
-    {
-        return reinterpret_cast<U*>( ptr() );
-    }
-
-    template <typename U>
-    optional_nodiscard U const * as() const
-    {
-        return reinterpret_cast<U const *>( ptr() );
-    }
-};
-
-} // namespace detail
-
-/// disengaged state tag
-
-struct nullopt_t
-{
-    struct init{};
-    explicit optional_constexpr nullopt_t( init /*unused*/ ) optional_noexcept {}
-};
-
-#if optional_HAVE( CONSTEXPR_11 )
-constexpr nullopt_t nullopt{ nullopt_t::init{} };
-#else
-// extra parenthesis to prevent the most vexing parse:
-const nullopt_t nullopt(( nullopt_t::init() ));
-#endif
-
-/// optional access error
-
-#if ! optional_CONFIG_NO_EXCEPTIONS
-
-class bad_optional_access : public std::logic_error
-{
-public:
-  explicit bad_optional_access()
-  : logic_error( "bad optional access" ) {}
-};
-
-#endif //optional_CONFIG_NO_EXCEPTIONS
-
-/// optional
-
-template< typename T>
-class optional
-{
-private:
-    template< typename > friend class optional;
-
-    typedef void (optional::*safe_bool)() const;
-
-public:
-    typedef T value_type;
-
-    // x.x.3.1, constructors
-
-    // 1a - default construct
-    optional_constexpr optional() optional_noexcept
-    : has_value_( false )
-    , contained()
-    {}
-
-    // 1b - construct explicitly empty
-    // NOLINTNEXTLINE( google-explicit-constructor, hicpp-explicit-conversions )
-    optional_constexpr optional( nullopt_t /*unused*/ ) optional_noexcept
-    : has_value_( false )
-    , contained()
-    {}
-
-    // 2 - copy-construct
-#if optional_CPP11_OR_GREATER
-    // template< typename U = T
-    //     optional_REQUIRES_T(
-    //         std::is_copy_constructible<U>::value
-    //         || std11::is_trivially_copy_constructible<U>::value
-    //     )
-    // >
-#endif
-    optional_constexpr14 optional( optional const & other )
-    : has_value_( other.has_value() )
-    {
-        if ( other.has_value() )
-        {
-            contained.construct_value( other.contained.value() );
-        }
-    }
-
-#if optional_CPP11_OR_GREATER
-
-    // 3 (C++11) - move-construct from optional
-    template< typename U = T
-        optional_REQUIRES_T(
-            std::is_move_constructible<U>::value
-            || std11::is_trivially_move_constructible<U>::value
-        )
-    >
-    optional_constexpr14 optional( optional && other )
-    // NOLINTNEXTLINE( performance-noexcept-move-constructor )
-        noexcept( std::is_nothrow_move_constructible<T>::value )
-    : has_value_( other.has_value() )
-    {
-        if ( other.has_value() )
-        {
-            contained.construct_value( std::move( other.contained.value() ) );
-        }
-    }
-
-    // 4a (C++11) - explicit converting copy-construct from optional
-    template< typename U
-        optional_REQUIRES_T(
-            std::is_constructible<T, U const &>::value
-            && !std::is_constructible<T, optional<U> &          >::value
-            && !std::is_constructible<T, optional<U> &&         >::value
-            && !std::is_constructible<T, optional<U> const &    >::value
-            && !std::is_constructible<T, optional<U> const &&   >::value
-            && !std::is_convertible<     optional<U> &       , T>::value
-            && !std::is_convertible<     optional<U> &&      , T>::value
-            && !std::is_convertible<     optional<U> const & , T>::value
-            && !std::is_convertible<     optional<U> const &&, T>::value
-            && !std::is_convertible<               U const & , T>::value /*=> explicit */
-        )
-    >
-    explicit optional( optional<U> const & other )
-    : has_value_( other.has_value() )
-    {
-        if ( other.has_value() )
-        {
-            contained.construct_value( T{ other.contained.value() } );
-        }
-    }
-#endif // optional_CPP11_OR_GREATER
-
-    // 4b (C++98 and later) - non-explicit converting copy-construct from optional
-    template< typename U
-#if optional_CPP11_OR_GREATER
-        optional_REQUIRES_T(
-            std::is_constructible<T, U const &>::value
-            && !std::is_constructible<T, optional<U> &          >::value
-            && !std::is_constructible<T, optional<U> &&         >::value
-            && !std::is_constructible<T, optional<U> const &    >::value
-            && !std::is_constructible<T, optional<U> const &&   >::value
-            && !std::is_convertible<     optional<U> &       , T>::value
-            && !std::is_convertible<     optional<U> &&      , T>::value
-            && !std::is_convertible<     optional<U> const & , T>::value
-            && !std::is_convertible<     optional<U> const &&, T>::value
-            &&  std::is_convertible<               U const & , T>::value /*=> non-explicit */
-        )
-#endif // optional_CPP11_OR_GREATER
-    >
-    // NOLINTNEXTLINE( google-explicit-constructor, hicpp-explicit-conversions )
-    /*non-explicit*/ optional( optional<U> const & other )
-    : has_value_( other.has_value() )
-    {
-        if ( other.has_value() )
-        {
-            contained.construct_value( other.contained.value() );
-        }
-    }
-
-#if optional_CPP11_OR_GREATER
-
-    // 5a (C++11) - explicit converting move-construct from optional
-    template< typename U
-        optional_REQUIRES_T(
-            std::is_constructible<T, U &&>::value
-            && !std::is_constructible<T, optional<U> &          >::value
-            && !std::is_constructible<T, optional<U> &&         >::value
-            && !std::is_constructible<T, optional<U> const &    >::value
-            && !std::is_constructible<T, optional<U> const &&   >::value
-            && !std::is_convertible<     optional<U> &       , T>::value
-            && !std::is_convertible<     optional<U> &&      , T>::value
-            && !std::is_convertible<     optional<U> const & , T>::value
-            && !std::is_convertible<     optional<U> const &&, T>::value
-            && !std::is_convertible<                     U &&, T>::value /*=> explicit */
-        )
-    >
-    explicit optional( optional<U> && other
-    )
-    : has_value_( other.has_value() )
-    {
-        if ( other.has_value() )
-        {
-            contained.construct_value( T{ std::move( other.contained.value() ) } );
-        }
-    }
-
-    // 5a (C++11) - non-explicit converting move-construct from optional
-    template< typename U
-        optional_REQUIRES_T(
-            std::is_constructible<T, U &&>::value
-            && !std::is_constructible<T, optional<U> &          >::value
-            && !std::is_constructible<T, optional<U> &&         >::value
-            && !std::is_constructible<T, optional<U> const &    >::value
-            && !std::is_constructible<T, optional<U> const &&   >::value
-            && !std::is_convertible<     optional<U> &       , T>::value
-            && !std::is_convertible<     optional<U> &&      , T>::value
-            && !std::is_convertible<     optional<U> const & , T>::value
-            && !std::is_convertible<     optional<U> const &&, T>::value
-            &&  std::is_convertible<                     U &&, T>::value /*=> non-explicit */
-        )
-    >
-    // NOLINTNEXTLINE( google-explicit-constructor, hicpp-explicit-conversions )
-    /*non-explicit*/ optional( optional<U> && other )
-    : has_value_( other.has_value() )
-    {
-        if ( other.has_value() )
-        {
-            contained.construct_value( std::move( other.contained.value() ) );
-        }
-    }
-
-    // 6 (C++11) - in-place construct
-    template< typename... Args
-        optional_REQUIRES_T(
-            std::is_constructible<T, Args&&...>::value
-        )
-    >
-    optional_constexpr explicit optional( nonstd_lite_in_place_t(T), Args&&... args )
-    : has_value_( true )
-    , contained( T( std::forward<Args>(args)...) )
-    {}
-
-    // 7 (C++11) - in-place construct,  initializer-list
-    template< typename U, typename... Args
-        optional_REQUIRES_T(
-            std::is_constructible<T, std::initializer_list<U>&, Args&&...>::value
-        )
-    >
-    optional_constexpr explicit optional( nonstd_lite_in_place_t(T), std::initializer_list<U> il, Args&&... args )
-    : has_value_( true )
-    , contained( T( il, std::forward<Args>(args)...) )
-    {}
-
-    // 8a (C++11) - explicit move construct from value
-    template< typename U = T
-        optional_REQUIRES_T(
-            std::is_constructible<T, U&&>::value
-            && !std::is_same<typename std20::remove_cvref<U>::type, nonstd_lite_in_place_t(U)>::value
-            && !std::is_same<typename std20::remove_cvref<U>::type, optional<T>>::value
-            && !std::is_convertible<U&&, T>::value /*=> explicit */
-        )
-    >
-    optional_constexpr explicit optional( U && value )
-    : has_value_( true )
-    , contained( T{ std::forward<U>( value ) } )
-    {}
-
-    // 8b (C++11) - non-explicit move construct from value
-    template< typename U = T
-        optional_REQUIRES_T(
-            std::is_constructible<T, U&&>::value
-            && !std::is_same<typename std20::remove_cvref<U>::type, nonstd_lite_in_place_t(U)>::value
-            && !std::is_same<typename std20::remove_cvref<U>::type, optional<T>>::value
-            && std::is_convertible<U&&, T>::value /*=> non-explicit */
-        )
-    >
-    // NOLINTNEXTLINE( google-explicit-constructor, hicpp-explicit-conversions )
-    optional_constexpr /*non-explicit*/ optional( U && value )
-    : has_value_( true )
-    , contained( std::forward<U>( value ) )
-    {}
-
-#else // optional_CPP11_OR_GREATER
-
-    // 8 (C++98)
-    optional( value_type const & value )
-    : has_value_( true )
-    , contained( value )
-    {}
-
-#endif // optional_CPP11_OR_GREATER
-
-    // x.x.3.2, destructor
-
-    ~optional()
-    {
-        if ( has_value() )
-        {
-            contained.destruct_value();
-        }
-    }
-
-    // x.x.3.3, assignment
-
-    // 1 (C++98and later) -  assign explicitly empty
-    optional & operator=( nullopt_t /*unused*/) optional_noexcept
-    {
-        reset();
-        return *this;
-    }
-
-    // 2 (C++98and later) - copy-assign from optional
-#if optional_CPP11_OR_GREATER
-    // NOLINTNEXTLINE( cppcoreguidelines-c-copy-assignment-signature, misc-unconventional-assign-operator )
-    optional_REQUIRES_R(
-        optional &,
-        true
-//      std::is_copy_constructible<T>::value
-//      && std::is_copy_assignable<T>::value
-    )
-    operator=( optional const & other )
-        noexcept(
-            std::is_nothrow_move_assignable<T>::value
-            && std::is_nothrow_move_constructible<T>::value
-        )
-#else
-    optional & operator=( optional const & other )
-#endif
-    {
-        if      ( (has_value() == true ) && (other.has_value() == false) ) { reset(); }
-        else if ( (has_value() == false) && (other.has_value() == true ) ) { initialize( *other ); }
-        else if ( (has_value() == true ) && (other.has_value() == true ) ) { contained.value() = *other; }
-        return *this;
-    }
-
-#if optional_CPP11_OR_GREATER
-
-    // 3 (C++11) - move-assign from optional
-    // NOLINTNEXTLINE( cppcoreguidelines-c-copy-assignment-signature, misc-unconventional-assign-operator )
-    optional_REQUIRES_R(
-        optional &,
-        true
-//      std::is_move_constructible<T>::value
-//      && std::is_move_assignable<T>::value
-    )
-    operator=( optional && other ) noexcept
-    {
-        if      ( (has_value() == true ) && (other.has_value() == false) ) { reset(); }
-        else if ( (has_value() == false) && (other.has_value() == true ) ) { initialize( std::move( *other ) ); }
-        else if ( (has_value() == true ) && (other.has_value() == true ) ) { contained.value() = std::move( *other ); }
-        return *this;
-    }
-
-    // 4 (C++11) - move-assign from value
-    template< typename U = T >
-        // NOLINTNEXTLINE( cppcoreguidelines-c-copy-assignment-signature, misc-unconventional-assign-operator )
-        optional_REQUIRES_R(
-            optional &,
-            std::is_constructible<T , U>::value
-            && std::is_assignable<T&, U>::value
-            && !std::is_same<typename std20::remove_cvref<U>::type, nonstd_lite_in_place_t(U)>::value
-            && !std::is_same<typename std20::remove_cvref<U>::type, optional<T>>::value
-            && !(std::is_scalar<T>::value && std::is_same<T, typename std::decay<U>::type>::value)
-        )
-    operator=( U && value )
-    {
-        if ( has_value() )
-        {
-            contained.value() = std::forward<U>( value );
-        }
-        else
-        {
-            initialize( T( std::forward<U>( value ) ) );
-        }
-        return *this;
-    }
-
-#else // optional_CPP11_OR_GREATER
-
-    // 4 (C++98) - copy-assign from value
-    template< typename U /*= T*/ >
-    optional & operator=( U const & value )
-    {
-        if ( has_value() ) contained.value() = value;
-        else               initialize( T( value ) );
-        return *this;
-    }
-
-#endif // optional_CPP11_OR_GREATER
-
-    // 5 (C++98 and later) - converting copy-assign from optional
-    template< typename U >
-#if optional_CPP11_OR_GREATER
-        // NOLINTNEXTLINE( cppcoreguidelines-c-copy-assignment-signature, misc-unconventional-assign-operator )
-        optional_REQUIRES_R(
-            optional&,
-            std::is_constructible<  T , U const &>::value
-            &&  std::is_assignable< T&, U const &>::value
-            && !std::is_constructible<T, optional<U> &          >::value
-            && !std::is_constructible<T, optional<U> &&         >::value
-            && !std::is_constructible<T, optional<U> const &    >::value
-            && !std::is_constructible<T, optional<U> const &&   >::value
-            && !std::is_convertible<     optional<U> &       , T>::value
-            && !std::is_convertible<     optional<U> &&      , T>::value
-            && !std::is_convertible<     optional<U> const & , T>::value
-            && !std::is_convertible<     optional<U> const &&, T>::value
-            && !std::is_assignable<  T&, optional<U> &          >::value
-            && !std::is_assignable<  T&, optional<U> &&         >::value
-            && !std::is_assignable<  T&, optional<U> const &    >::value
-            && !std::is_assignable<  T&, optional<U> const &&   >::value
-        )
-#else
-    optional&
-#endif // optional_CPP11_OR_GREATER
-    operator=( optional<U> const & other )
-    {
-        return *this = optional( other );
-    }
-
-#if optional_CPP11_OR_GREATER
-
-    // 6 (C++11) -  converting move-assign from optional
-    template< typename U >
-        // NOLINTNEXTLINE( cppcoreguidelines-c-copy-assignment-signature, misc-unconventional-assign-operator )
-        optional_REQUIRES_R(
-            optional&,
-            std::is_constructible<  T , U>::value
-            &&  std::is_assignable< T&, U>::value
-            && !std::is_constructible<T, optional<U> &          >::value
-            && !std::is_constructible<T, optional<U> &&         >::value
-            && !std::is_constructible<T, optional<U> const &    >::value
-            && !std::is_constructible<T, optional<U> const &&   >::value
-            && !std::is_convertible<     optional<U> &       , T>::value
-            && !std::is_convertible<     optional<U> &&      , T>::value
-            && !std::is_convertible<     optional<U> const & , T>::value
-            && !std::is_convertible<     optional<U> const &&, T>::value
-            && !std::is_assignable<  T&, optional<U> &          >::value
-            && !std::is_assignable<  T&, optional<U> &&         >::value
-            && !std::is_assignable<  T&, optional<U> const &    >::value
-            && !std::is_assignable<  T&, optional<U> const &&   >::value
-        )
-    operator=( optional<U> && other )
-    {
-        return *this = optional( std::move( other ) );
-    }
-
-    // 7 (C++11) - emplace
-    template< typename... Args
-        optional_REQUIRES_T(
-            std::is_constructible<T, Args&&...>::value
-        )
-    >
-    T& emplace( Args&&... args )
-    {
-        *this = nullopt;
-        contained.emplace( std::forward<Args>(args)...  );
-        has_value_ = true;
-        return contained.value();
-    }
-
-    // 8 (C++11) - emplace, initializer-list
-    template< typename U, typename... Args
-        optional_REQUIRES_T(
-            std::is_constructible<T, std::initializer_list<U>&, Args&&...>::value
-        )
-    >
-    T& emplace( std::initializer_list<U> il, Args&&... args )
-    {
-        *this = nullopt;
-        contained.emplace( il, std::forward<Args>(args)...  );
-        has_value_ = true;
-        return contained.value();
-    }
-
-#endif // optional_CPP11_OR_GREATER
-
-    // x.x.3.4, swap
-
-    void swap( optional & other )
-#if optional_CPP11_OR_GREATER
-        noexcept(
-            std::is_nothrow_move_constructible<T>::value
-            && std17::is_nothrow_swappable<T>::value
-        )
-#endif
-    {
-        using std::swap;
-        if      ( (has_value() == true ) && (other.has_value() == true ) ) { swap( **this, *other ); }
-        else if ( (has_value() == false) && (other.has_value() == true ) ) { initialize( std11::move(*other) ); other.reset(); }
-        else if ( (has_value() == true ) && (other.has_value() == false) ) { other.initialize( std11::move(**this) ); reset(); }
-    }
-
-    // x.x.3.5, observers
-
-    optional_constexpr value_type const * operator ->() const
-    {
-        return assert( has_value() ),
-            contained.value_ptr();
-    }
-
-    optional_constexpr14 value_type * operator ->()
-    {
-        return assert( has_value() ),
-            contained.value_ptr();
-    }
-
-    optional_constexpr value_type const & operator *() const optional_ref_qual
-    {
-        return assert( has_value() ),
-            contained.value();
-    }
-
-    optional_constexpr14 value_type & operator *() optional_ref_qual
-    {
-        return assert( has_value() ),
-            contained.value();
-    }
-
-#if optional_HAVE( REF_QUALIFIER )
-
-    optional_constexpr value_type const && operator *() const optional_refref_qual
-    {
-        return std::move( **this );
-    }
-
-    optional_constexpr14 value_type && operator *() optional_refref_qual
-    {
-        return std::move( **this );
-    }
-
-#endif
-
-#if optional_CPP11_OR_GREATER
-    optional_constexpr explicit operator bool() const optional_noexcept
-    {
-        return has_value();
-    }
-#else
-    optional_constexpr operator safe_bool() const optional_noexcept
-    {
-        return has_value() ? &optional::this_type_does_not_support_comparisons : 0;
-    }
-#endif
-
-    // NOLINTNEXTLINE( modernize-use-nodiscard )
-    /*optional_nodiscard*/ optional_constexpr bool has_value() const optional_noexcept
-    {
-        return has_value_;
-    }
-
-    // NOLINTNEXTLINE( modernize-use-nodiscard )
-    /*optional_nodiscard*/ optional_constexpr14 value_type const & value() const optional_ref_qual
-    {
-#if optional_CONFIG_NO_EXCEPTIONS
-        assert( has_value() );
-#else
-        if ( ! has_value() )
-        {
-            throw bad_optional_access();
-        }
-#endif
-        return contained.value();
-    }
-
-    optional_constexpr14 value_type & value() optional_ref_qual
-    {
-#if optional_CONFIG_NO_EXCEPTIONS
-        assert( has_value() );
-#else
-        if ( ! has_value() )
-        {
-            throw bad_optional_access();
-        }
-#endif
-        return contained.value();
-    }
-
-#if optional_HAVE( REF_QUALIFIER )  &&  ( !optional_COMPILER_GNUC_VERSION || optional_COMPILER_GNUC_VERSION >= 490 )
-
-    // NOLINTNEXTLINE( modernize-use-nodiscard )
-    /*optional_nodiscard*/ optional_constexpr value_type const && value() const optional_refref_qual
-    {
-        return std::move( value() );
-    }
-
-    optional_constexpr14 value_type && value() optional_refref_qual
-    {
-        return std::move( value() );
-    }
-
-#endif
-
-#if optional_CPP11_OR_GREATER
-
-    template< typename U >
-    optional_constexpr value_type value_or( U && v ) const optional_ref_qual
-    {
-        return has_value() ? contained.value() : static_cast<T>(std::forward<U>( v ) );
-    }
-
-    template< typename U >
-    optional_constexpr14 value_type value_or( U && v ) optional_refref_qual
-    {
-        return has_value() ? std::move( contained.value() ) : static_cast<T>(std::forward<U>( v ) );
-    }
-
-#else
-
-    template< typename U >
-    optional_constexpr value_type value_or( U const & v ) const
-    {
-        return has_value() ? contained.value() : static_cast<value_type>( v );
-    }
-
-#endif // optional_CPP11_OR_GREATER
-
-    // x.x.3.6, modifiers
-
-    void reset() optional_noexcept
-    {
-        if ( has_value() )
-        {
-            contained.destruct_value();
-        }
-
-        has_value_ = false;
-    }
-
-private:
-    void this_type_does_not_support_comparisons() const {}
-
-    template< typename V >
-    void initialize( V const & value )
-    {
-        assert( ! has_value()  );
-        contained.construct_value( value );
-        has_value_ = true;
-    }
-
-#if optional_CPP11_OR_GREATER
-    template< typename V >
-    void initialize( V && value )
-    {
-        assert( ! has_value()  );
-        contained.construct_value( std::move( value ) );
-        has_value_ = true;
-    }
-
-#endif
-
-private:
-    bool has_value_;
-    detail::storage_t< value_type > contained;
-
-};
-
-// Relational operators
-
-template< typename T, typename U >
-inline optional_constexpr bool operator==( optional<T> const & x, optional<U> const & y )
-{
-    return bool(x) != bool(y) ? false : !bool( x ) ? true : *x == *y;
-}
-
-template< typename T, typename U >
-inline optional_constexpr bool operator!=( optional<T> const & x, optional<U> const & y )
-{
-    return !(x == y);
-}
-
-template< typename T, typename U >
-inline optional_constexpr bool operator<( optional<T> const & x, optional<U> const & y )
-{
-    return (!y) ? false : (!x) ? true : *x < *y;
-}
-
-template< typename T, typename U >
-inline optional_constexpr bool operator>( optional<T> const & x, optional<U> const & y )
-{
-    return (y < x);
-}
-
-template< typename T, typename U >
-inline optional_constexpr bool operator<=( optional<T> const & x, optional<U> const & y )
-{
-    return !(y < x);
-}
-
-template< typename T, typename U >
-inline optional_constexpr bool operator>=( optional<T> const & x, optional<U> const & y )
-{
-    return !(x < y);
-}
-
-// Comparison with nullopt
-
-template< typename T >
-inline optional_constexpr bool operator==( optional<T> const & x, nullopt_t /*unused*/ ) optional_noexcept
-{
-    return (!x);
-}
-
-template< typename T >
-inline optional_constexpr bool operator==( nullopt_t /*unused*/, optional<T> const & x ) optional_noexcept
-{
-    return (!x);
-}
-
-template< typename T >
-inline optional_constexpr bool operator!=( optional<T> const & x, nullopt_t /*unused*/ ) optional_noexcept
-{
-    return bool(x);
-}
-
-template< typename T >
-inline optional_constexpr bool operator!=( nullopt_t /*unused*/, optional<T> const & x ) optional_noexcept
-{
-    return bool(x);
-}
-
-template< typename T >
-inline optional_constexpr bool operator<( optional<T> const & /*unused*/, nullopt_t /*unused*/ ) optional_noexcept
-{
-    return false;
-}
-
-template< typename T >
-inline optional_constexpr bool operator<( nullopt_t /*unused*/, optional<T> const & x ) optional_noexcept
-{
-    return bool(x);
-}
-
-template< typename T >
-inline optional_constexpr bool operator<=( optional<T> const & x, nullopt_t /*unused*/ ) optional_noexcept
-{
-    return (!x);
-}
-
-template< typename T >
-inline optional_constexpr bool operator<=( nullopt_t /*unused*/, optional<T> const & /*unused*/ ) optional_noexcept
-{
-    return true;
-}
-
-template< typename T >
-inline optional_constexpr bool operator>( optional<T> const & x, nullopt_t /*unused*/ ) optional_noexcept
-{
-    return bool(x);
-}
-
-template< typename T >
-inline optional_constexpr bool operator>( nullopt_t /*unused*/, optional<T> const & /*unused*/ ) optional_noexcept
-{
-    return false;
-}
-
-template< typename T >
-inline optional_constexpr bool operator>=( optional<T> const & /*unused*/, nullopt_t /*unused*/ ) optional_noexcept
-{
-    return true;
-}
-
-template< typename T >
-inline optional_constexpr bool operator>=( nullopt_t /*unused*/, optional<T> const & x ) optional_noexcept
-{
-    return (!x);
-}
-
-// Comparison with T
-
-template< typename T, typename U >
-inline optional_constexpr bool operator==( optional<T> const & x, U const & v )
-{
-    return bool(x) ? *x == v : false;
-}
-
-template< typename T, typename U >
-inline optional_constexpr bool operator==( U const & v, optional<T> const & x )
-{
-    return bool(x) ? v == *x : false;
-}
-
-template< typename T, typename U >
-inline optional_constexpr bool operator!=( optional<T> const & x, U const & v )
-{
-    return bool(x) ? *x != v : true;
-}
-
-template< typename T, typename U >
-inline optional_constexpr bool operator!=( U const & v, optional<T> const & x )
-{
-    return bool(x) ? v != *x : true;
-}
-
-template< typename T, typename U >
-inline optional_constexpr bool operator<( optional<T> const & x, U const & v )
-{
-    return bool(x) ? *x < v : true;
-}
-
-template< typename T, typename U >
-inline optional_constexpr bool operator<( U const & v, optional<T> const & x )
-{
-    return bool(x) ? v < *x : false;
-}
-
-template< typename T, typename U >
-inline optional_constexpr bool operator<=( optional<T> const & x, U const & v )
-{
-    return bool(x) ? *x <= v : true;
-}
-
-template< typename T, typename U >
-inline optional_constexpr bool operator<=( U const & v, optional<T> const & x )
-{
-    return bool(x) ? v <= *x : false;
-}
-
-template< typename T, typename U >
-inline optional_constexpr bool operator>( optional<T> const & x, U const & v )
-{
-    return bool(x) ? *x > v : false;
-}
-
-template< typename T, typename U >
-inline optional_constexpr bool operator>( U const & v, optional<T> const & x )
-{
-    return bool(x) ? v > *x : true;
-}
-
-template< typename T, typename U >
-inline optional_constexpr bool operator>=( optional<T> const & x, U const & v )
-{
-    return bool(x) ? *x >= v : false;
-}
-
-template< typename T, typename U >
-inline optional_constexpr bool operator>=( U const & v, optional<T> const & x )
-{
-    return bool(x) ? v >= *x : true;
-}
-
-// Specialized algorithms
-
-template< typename T
-#if optional_CPP11_OR_GREATER
-    optional_REQUIRES_T(
-        std::is_move_constructible<T>::value
-        && std17::is_swappable<T>::value )
-#endif
->
-void swap( optional<T> & x, optional<T> & y )
-#if optional_CPP11_OR_GREATER
-    noexcept( noexcept( x.swap(y) ) )
-#endif
-{
-    x.swap( y );
-}
-
-#if optional_CPP11_OR_GREATER
-
-template< typename T >
-optional_constexpr optional< typename std::decay<T>::type > make_optional( T && value )
-{
-    return optional< typename std::decay<T>::type >( std::forward<T>( value ) );
-}
-
-template< typename T, typename...Args >
-optional_constexpr optional<T> make_optional( Args&&... args )
-{
-    return optional<T>( nonstd_lite_in_place(T), std::forward<Args>(args)...);
-}
-
-template< typename T, typename U, typename... Args >
-optional_constexpr optional<T> make_optional( std::initializer_list<U> il, Args&&... args )
-{
-    return optional<T>( nonstd_lite_in_place(T), il, std::forward<Args>(args)...);
-}
-
-#else
-
-template< typename T >
-optional<T> make_optional( T const & value )
-{
-    return optional<T>( value );
-}
-
-#endif // optional_CPP11_OR_GREATER
-
-} // namespace optional_lite
-
-using optional_lite::optional;
-using optional_lite::nullopt_t;
-using optional_lite::nullopt;
-
-#if ! optional_CONFIG_NO_EXCEPTIONS
-using optional_lite::bad_optional_access;
-#endif
-
-using optional_lite::make_optional;
-
-} // namespace nonstd
-
-#if optional_CPP11_OR_GREATER
-
-// specialize the std::hash algorithm:
-
-namespace std {
-
-template< class T >
-struct hash< nonstd::optional<T> >
-{
-public:
-    std::size_t operator()( nonstd::optional<T> const & v ) const optional_noexcept
-    {
-        return bool( v ) ? std::hash<T>{}( *v ) : 0;
-    }
-};
-
-} //namespace std
-
-#endif // optional_CPP11_OR_GREATER
-
-#if defined(__clang__)
-# pragma clang diagnostic pop
-#elif defined(__GNUC__)
-# pragma GCC   diagnostic pop
-#elif defined(_MSC_VER )
-# pragma warning( pop )
-#endif
-
-#endif // optional_USES_STD_OPTIONAL
-
-
-namespace tf { namespace nstd {
-
-template <typename T>
-using optional = nonstd::optional<T>;
-
-}}
diff --git a/bundled/taskflow-2.5.0/include/taskflow/nstd/variant.hpp b/bundled/taskflow-2.5.0/include/taskflow/nstd/variant.hpp
deleted file mode 100644 (file)
index c07ee20..0000000
+++ /dev/null
@@ -1,2631 +0,0 @@
-// The file is modified from MPark in order to use variant in C++11/14
-// We change the namespace to stick with the v1.4, in order to avoid clashing
-// problem when upstream code uses the same library.
-
-// MPark.Variant
-//
-// Copyright Michael Park, 2015-2017
-//
-// Distributed under the Boost Software License, Version 1.0.
-// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
-
-#pragma once
-
-#include <cstddef>
-#include <exception>
-#include <functional>
-#include <initializer_list>
-#include <limits>
-#include <new>
-#include <type_traits>
-#include <utility>
-#include <memory>
-
-
-// MPark.Variant
-//
-// Copyright Michael Park, 2015-2017
-//
-// Distributed under the Boost Software License, Version 1.0.
-// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
-
-// MSVC 2015 Update 3.
-#if __cplusplus < 201103L && (!defined(_MSC_VER) || _MSC_FULL_VER < 190024210)
-#error "MPark.Variant requires C++11 support."
-#endif
-
-#ifndef __has_attribute
-#define __has_attribute(x) 0
-#endif
-
-#ifndef __has_builtin
-#define __has_builtin(x) 0
-#endif
-
-#ifndef __has_include
-#define __has_include(x) 0
-#endif
-
-#ifndef __has_feature
-#define __has_feature(x) 0
-#endif
-
-#if __has_attribute(always_inline) || defined(__GNUC__)
-#define TF_ALWAYS_INLINE __attribute__((__always_inline__)) inline
-#elif defined(_MSC_VER)
-#define TF_ALWAYS_INLINE __forceinline
-#else
-#define TF_ALWAYS_INLINE inline
-#endif
-
-#if __has_builtin(__builtin_addressof) || \
-    (defined(__GNUC__) && __GNUC__ >= 7) || defined(_MSC_VER)
-#define TF_BUILTIN_ADDRESSOF
-#endif
-
-#if __has_builtin(__builtin_unreachable) || defined(__GNUC__)
-#define TF_BUILTIN_UNREACHABLE __builtin_unreachable()
-#elif defined(_MSC_VER)
-#define TF_BUILTIN_UNREACHABLE __assume(false)
-#else
-#define TF_BUILTIN_UNREACHABLE
-#endif
-
-#if __has_builtin(__type_pack_element)
-#define TF_TYPE_PACK_ELEMENT
-#endif
-
-#if defined(__cpp_constexpr) && __cpp_constexpr >= 200704 && \
-    !(defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ == 9)
-#define TF_CPP11_CONSTEXPR
-#endif
-
-#if defined(__cpp_constexpr) && __cpp_constexpr >= 201304
-#define TF_CPP14_CONSTEXPR
-#endif
-
-#if __has_feature(cxx_exceptions) || defined(__cpp_exceptions) || \
-    (defined(_MSC_VER) && defined(_CPPUNWIND))
-#define TF_EXCEPTIONS
-#endif
-
-#if defined(__cpp_generic_lambdas) || defined(_MSC_VER)
-#define TF_GENERIC_LAMBDAS
-#endif
-
-#if defined(__cpp_lib_integer_sequence)
-#define TF_INTEGER_SEQUENCE
-#endif
-
-#if (defined(__cpp_decltype_auto) && defined(__cpp_return_type_deduction)) || defined(_MSC_VER)
-#define TF_RETURN_TYPE_DEDUCTION
-#endif
-
-#if defined(__cpp_lib_transparent_operators) || defined(_MSC_VER)
-#define TF_TRANSPARENT_OPERATORS
-#endif
-
-#if defined(__cpp_variable_templates) || defined(_MSC_VER)
-#define TF_VARIABLE_TEMPLATES
-#endif
-
-#if !defined(__GLIBCXX__) || __has_include(<codecvt>)  // >= libstdc++-5
-#define TF_TRIVIALITY_TYPE_TRAITS
-#define TF_INCOMPLETE_TYPE_TRAITS
-#endif
-
-// MPark.Variant
-//
-// Copyright Michael Park, 2015-2017
-//
-// Distributed under the Boost Software License, Version 1.0.
-// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
-
-// in_place_t definition
-namespace tf { namespace nstd {
-
-  struct in_place_t { explicit in_place_t() = default; };
-
-  template <std::size_t I>
-  struct in_place_index_t { explicit in_place_index_t() = default; };
-
-  template <typename T>
-  struct in_place_type_t { explicit in_place_type_t() = default; };
-
-#ifdef TF_VARIABLE_TEMPLATES
-  constexpr in_place_t in_place{};
-
-  template <std::size_t I> constexpr in_place_index_t<I> in_place_index{};
-
-  template <typename T> constexpr in_place_type_t<T> in_place_type{};
-#endif
-
-}}  // namespace tf::nstd
-
-// MPark.Variant
-//
-// Copyright Michael Park, 2015-2017
-//
-// Distributed under the Boost Software License, Version 1.0.
-// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
-
-
-#define TF_RETURN(...) \
-  noexcept(noexcept(__VA_ARGS__)) -> decltype(__VA_ARGS__) { return __VA_ARGS__; }
-
-namespace tf { namespace nstd {
-  namespace lib {
-    template <typename T>
-    struct identity { using type = T; };
-
-    inline namespace cpp14 {
-      template <typename T, std::size_t N>
-      struct array {
-        constexpr const T &operator[](std::size_t index) const {
-          return data[index];
-        }
-
-        T data[N == 0 ? 1 : N];
-      };
-
-      template <typename T>
-      using add_pointer_t = typename std::add_pointer<T>::type;
-
-      template <typename... Ts>
-      using common_type_t = typename std::common_type<Ts...>::type;
-
-      template <typename T>
-      using decay_t = typename std::decay<T>::type;
-
-      template <bool B, typename T = void>
-      using enable_if_t = typename std::enable_if<B, T>::type;
-
-      template <typename T>
-      using remove_const_t = typename std::remove_const<T>::type;
-
-      template <typename T>
-      using remove_reference_t = typename std::remove_reference<T>::type;
-
-      template <typename T>
-      using remove_cvref_t =
-          typename std::remove_cv<remove_reference_t<T>>::type;
-
-      template <typename T>
-      inline constexpr T &&forward(remove_reference_t<T> &t) noexcept {
-        return static_cast<T &&>(t);
-      }
-
-      template <typename T>
-      inline constexpr T &&forward(remove_reference_t<T> &&t) noexcept {
-        static_assert(!std::is_lvalue_reference<T>::value,
-                      "can not forward an rvalue as an lvalue");
-        return static_cast<T &&>(t);
-      }
-
-      template <typename T>
-      inline constexpr remove_reference_t<T> &&move(T &&t) noexcept {
-        return static_cast<remove_reference_t<T> &&>(t);
-      }
-
-#ifdef TF_INTEGER_SEQUENCE
-      using std::integer_sequence;
-      using std::index_sequence;
-      using std::make_index_sequence;
-      using std::index_sequence_for;
-#else
-      template <typename T, T... Is>
-      struct integer_sequence {
-        using value_type = T;
-        static constexpr std::size_t size() noexcept { return sizeof...(Is); }
-      };
-
-      template <std::size_t... Is>
-      using index_sequence = integer_sequence<std::size_t, Is...>;
-
-      template <typename Lhs, typename Rhs>
-      struct make_index_sequence_concat;
-
-      template <std::size_t... Lhs, std::size_t... Rhs>
-      struct make_index_sequence_concat<index_sequence<Lhs...>,
-                                        index_sequence<Rhs...>>
-          : identity<index_sequence<Lhs..., (sizeof...(Lhs) + Rhs)...>> {};
-
-      template <std::size_t N>
-      struct make_index_sequence_impl;
-
-      template <std::size_t N>
-      using make_index_sequence = typename make_index_sequence_impl<N>::type;
-
-      template <std::size_t N>
-      struct make_index_sequence_impl
-          : make_index_sequence_concat<make_index_sequence<N / 2>,
-                                       make_index_sequence<N - (N / 2)>> {};
-
-      template <>
-      struct make_index_sequence_impl<0> : identity<index_sequence<>> {};
-
-      template <>
-      struct make_index_sequence_impl<1> : identity<index_sequence<0>> {};
-
-      template <typename... Ts>
-      using index_sequence_for = make_index_sequence<sizeof...(Ts)>;
-#endif
-
-      // <functional>
-#ifdef TF_TRANSPARENT_OPERATORS
-      using equal_to = std::equal_to<>;
-#else
-      struct equal_to {
-        template <typename Lhs, typename Rhs>
-        inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const
-          TF_RETURN(lib::forward<Lhs>(lhs) == lib::forward<Rhs>(rhs))
-      };
-#endif
-
-#ifdef TF_TRANSPARENT_OPERATORS
-      using not_equal_to = std::not_equal_to<>;
-#else
-      struct not_equal_to {
-        template <typename Lhs, typename Rhs>
-        inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const
-          TF_RETURN(lib::forward<Lhs>(lhs) != lib::forward<Rhs>(rhs))
-      };
-#endif
-
-#ifdef TF_TRANSPARENT_OPERATORS
-      using less = std::less<>;
-#else
-      struct less {
-        template <typename Lhs, typename Rhs>
-        inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const
-          TF_RETURN(lib::forward<Lhs>(lhs) < lib::forward<Rhs>(rhs))
-      };
-#endif
-
-#ifdef TF_TRANSPARENT_OPERATORS
-      using greater = std::greater<>;
-#else
-      struct greater {
-        template <typename Lhs, typename Rhs>
-        inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const
-          TF_RETURN(lib::forward<Lhs>(lhs) > lib::forward<Rhs>(rhs))
-      };
-#endif
-
-#ifdef TF_TRANSPARENT_OPERATORS
-      using less_equal = std::less_equal<>;
-#else
-      struct less_equal {
-        template <typename Lhs, typename Rhs>
-        inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const
-          TF_RETURN(lib::forward<Lhs>(lhs) <= lib::forward<Rhs>(rhs))
-      };
-#endif
-
-#ifdef TF_TRANSPARENT_OPERATORS
-      using greater_equal = std::greater_equal<>;
-#else
-      struct greater_equal {
-        template <typename Lhs, typename Rhs>
-        inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const
-          TF_RETURN(lib::forward<Lhs>(lhs) >= lib::forward<Rhs>(rhs))
-      };
-#endif
-    }  // namespace cpp14
-
-    inline namespace cpp17 {
-
-      // <type_traits>
-      template <bool B>
-      using bool_constant = std::integral_constant<bool, B>;
-
-      template <typename...>
-      struct voider : identity<void> {};
-
-      template <typename... Ts>
-      using void_t = typename voider<Ts...>::type;
-
-      namespace detail {
-        namespace swappable {
-
-          using std::swap;
-
-          template <typename T>
-          struct is_swappable {
-            private:
-            template <typename U,
-                      typename = decltype(swap(std::declval<U &>(),
-                                               std::declval<U &>()))>
-            inline static std::true_type test(int);
-
-            template <typename U>
-            inline static std::false_type test(...);
-
-            public:
-            static constexpr bool value = decltype(test<T>(0))::value;
-          };
-
-          template <bool IsSwappable, typename T>
-          struct is_nothrow_swappable {
-            static constexpr bool value =
-                noexcept(swap(std::declval<T &>(), std::declval<T &>()));
-          };
-
-          template <typename T>
-          struct is_nothrow_swappable<false, T> : std::false_type {};
-
-        }  // namespace swappable
-      }  // namespace detail
-
-      using detail::swappable::is_swappable;
-
-      template <typename T>
-      using is_nothrow_swappable =
-          detail::swappable::is_nothrow_swappable<is_swappable<T>::value, T>;
-
-      // <functional>
-      namespace detail {
-
-        template <typename T>
-        struct is_reference_wrapper : std::false_type {};
-
-        template <typename T>
-        struct is_reference_wrapper<std::reference_wrapper<T>>
-            : std::true_type {};
-
-        template <bool, int>
-        struct Invoke;
-
-        template <>
-        struct Invoke<true /* pmf */, 0 /* is_base_of */> {
-          template <typename R, typename T, typename Arg, typename... Args>
-          inline static constexpr auto invoke(R T::*pmf, Arg &&arg, Args &&... args)
-            TF_RETURN((lib::forward<Arg>(arg).*pmf)(lib::forward<Args>(args)...))
-        };
-
-        template <>
-        struct Invoke<true /* pmf */, 1 /* is_reference_wrapper */> {
-          template <typename R, typename T, typename Arg, typename... Args>
-          inline static constexpr auto invoke(R T::*pmf, Arg &&arg, Args &&... args)
-            TF_RETURN((lib::forward<Arg>(arg).get().*pmf)(lib::forward<Args>(args)...))
-        };
-
-        template <>
-        struct Invoke<true /* pmf */, 2 /* otherwise */> {
-          template <typename R, typename T, typename Arg, typename... Args>
-          inline static constexpr auto invoke(R T::*pmf, Arg &&arg, Args &&... args)
-            TF_RETURN(((*lib::forward<Arg>(arg)).*pmf)(lib::forward<Args>(args)...))
-        };
-
-        template <>
-        struct Invoke<false /* pmo */, 0 /* is_base_of */> {
-          template <typename R, typename T, typename Arg>
-          inline static constexpr auto invoke(R T::*pmo, Arg &&arg)
-            TF_RETURN(lib::forward<Arg>(arg).*pmo)
-        };
-
-        template <>
-        struct Invoke<false /* pmo */, 1 /* is_reference_wrapper */> {
-          template <typename R, typename T, typename Arg>
-          inline static constexpr auto invoke(R T::*pmo, Arg &&arg)
-            TF_RETURN(lib::forward<Arg>(arg).get().*pmo)
-        };
-
-        template <>
-        struct Invoke<false /* pmo */, 2 /* otherwise */> {
-          template <typename R, typename T, typename Arg>
-          inline static constexpr auto invoke(R T::*pmo, Arg &&arg)
-              TF_RETURN((*lib::forward<Arg>(arg)).*pmo)
-        };
-
-        template <typename R, typename T, typename Arg, typename... Args>
-        inline constexpr auto invoke(R T::*f, Arg &&arg, Args &&... args)
-          TF_RETURN(
-              Invoke<std::is_function<R>::value,
-                     (std::is_base_of<T, lib::decay_t<Arg>>::value
-                          ? 0
-                          : is_reference_wrapper<lib::decay_t<Arg>>::value
-                                ? 1
-                                : 2)>::invoke(f,
-                                              lib::forward<Arg>(arg),
-                                              lib::forward<Args>(args)...))
-
-#ifdef _MSC_VER
-#pragma warning(push)
-#pragma warning(disable : 4100)
-#endif
-        template <typename F, typename... Args>
-        inline constexpr auto invoke(F &&f, Args &&... args)
-          TF_RETURN(lib::forward<F>(f)(lib::forward<Args>(args)...))
-#ifdef _MSC_VER
-#pragma warning(pop)
-#endif
-      }  // namespace detail
-
-      template <typename F, typename... Args>
-      inline constexpr auto invoke(F &&f, Args &&... args)
-        TF_RETURN(detail::invoke(lib::forward<F>(f),
-                                    lib::forward<Args>(args)...))
-
-      namespace detail {
-
-        template <typename Void, typename, typename...>
-        struct invoke_result {};
-
-        template <typename F, typename... Args>
-        struct invoke_result<void_t<decltype(lib::invoke(
-                                 std::declval<F>(), std::declval<Args>()...))>,
-                             F,
-                             Args...>
-            : identity<decltype(
-                  lib::invoke(std::declval<F>(), std::declval<Args>()...))> {};
-
-      }  // namespace detail
-
-      template <typename F, typename... Args>
-      using invoke_result = detail::invoke_result<void, F, Args...>;
-
-      template <typename F, typename... Args>
-      using invoke_result_t = typename invoke_result<F, Args...>::type;
-
-      namespace detail {
-
-        template <typename Void, typename, typename...>
-        struct is_invocable : std::false_type {};
-
-        template <typename F, typename... Args>
-        struct is_invocable<void_t<invoke_result_t<F, Args...>>, F, Args...>
-            : std::true_type {};
-
-        template <typename Void, typename, typename, typename...>
-        struct is_invocable_r : std::false_type {};
-
-        template <typename R, typename F, typename... Args>
-        struct is_invocable_r<void_t<invoke_result_t<F, Args...>>,
-                              R,
-                              F,
-                              Args...>
-            : std::is_convertible<invoke_result_t<F, Args...>, R> {};
-
-      }  // namespace detail
-
-      template <typename F, typename... Args>
-      using is_invocable = detail::is_invocable<void, F, Args...>;
-
-      template <typename R, typename F, typename... Args>
-      using is_invocable_r = detail::is_invocable_r<void, R, F, Args...>;
-
-      // <memory>
-#ifdef TF_BUILTIN_ADDRESSOF
-      template <typename T>
-      inline constexpr T *addressof(T &arg) noexcept {
-        return __builtin_addressof(arg);
-      }
-#else
-      namespace detail {
-
-        namespace has_addressof_impl {
-
-          struct fail;
-
-          template <typename T>
-          inline fail operator&(T &&);
-
-          template <typename T>
-          inline static constexpr bool impl() {
-            return (std::is_class<T>::value || std::is_union<T>::value) &&
-                   !std::is_same<decltype(&std::declval<T &>()), fail>::value;
-          }
-
-        }  // namespace has_addressof_impl
-
-        template <typename T>
-        using has_addressof = bool_constant<has_addressof_impl::impl<T>()>;
-
-        template <typename T>
-        inline constexpr T *addressof(T &arg, std::true_type) noexcept {
-          return std::addressof(arg);
-        }
-
-        template <typename T>
-        inline constexpr T *addressof(T &arg, std::false_type) noexcept {
-          return &arg;
-        }
-
-      }  // namespace detail
-
-      template <typename T>
-      inline constexpr T *addressof(T &arg) noexcept {
-        return detail::addressof(arg, detail::has_addressof<T>{});
-      }
-#endif
-
-      template <typename T>
-      inline constexpr T *addressof(const T &&) = delete;
-
-    }  // namespace cpp17
-
-    template <typename T>
-    struct remove_all_extents : identity<T> {};
-
-    template <typename T, std::size_t N>
-    struct remove_all_extents<array<T, N>> : remove_all_extents<T> {};
-
-    template <typename T>
-    using remove_all_extents_t = typename remove_all_extents<T>::type;
-
-    template <std::size_t N>
-    using size_constant = std::integral_constant<std::size_t, N>;
-
-    template <std::size_t I, typename T>
-    struct indexed_type : size_constant<I> { using type = T; };
-
-    template <bool... Bs>
-    using all = std::is_same<integer_sequence<bool, true, Bs...>,
-                             integer_sequence<bool, Bs..., true>>;
-
-#ifdef TF_TYPE_PACK_ELEMENT
-    template <std::size_t I, typename... Ts>
-    using type_pack_element_t = __type_pack_element<I, Ts...>;
-#else
-    template <std::size_t I, typename... Ts>
-    struct type_pack_element_impl {
-      private:
-      template <typename>
-      struct set;
-
-      template <std::size_t... Is>
-      struct set<index_sequence<Is...>> : indexed_type<Is, Ts>... {};
-
-      template <typename T>
-      inline static std::enable_if<true, T> impl(indexed_type<I, T>);
-
-      inline static std::enable_if<false> impl(...);
-
-      public:
-      using type = decltype(impl(set<index_sequence_for<Ts...>>{}));
-    };
-
-    template <std::size_t I, typename... Ts>
-    using type_pack_element = typename type_pack_element_impl<I, Ts...>::type;
-
-    template <std::size_t I, typename... Ts>
-    using type_pack_element_t = typename type_pack_element<I, Ts...>::type;
-#endif
-
-#ifdef TF_TRIVIALITY_TYPE_TRAITS
-    using std::is_trivially_copy_constructible;
-    using std::is_trivially_move_constructible;
-    using std::is_trivially_copy_assignable;
-    using std::is_trivially_move_assignable;
-#else
-    template <typename T>
-    struct is_trivially_copy_constructible
-        : bool_constant<
-              std::is_copy_constructible<T>::value && __has_trivial_copy(T)> {};
-
-    template <typename T>
-    struct is_trivially_move_constructible : bool_constant<__is_trivial(T)> {};
-
-    template <typename T>
-    struct is_trivially_copy_assignable
-        : bool_constant<
-              std::is_copy_assignable<T>::value && __has_trivial_assign(T)> {};
-
-    template <typename T>
-    struct is_trivially_move_assignable : bool_constant<__is_trivial(T)> {};
-#endif
-
-    template <typename T, bool>
-    struct dependent_type : T {};
-
-    template <typename Is, std::size_t J>
-    struct push_back;
-
-    template <typename Is, std::size_t J>
-    using push_back_t = typename push_back<Is, J>::type;
-
-    template <std::size_t... Is, std::size_t J>
-    struct push_back<index_sequence<Is...>, J> {
-      using type = index_sequence<Is..., J>;
-    };
-
-  }  // namespace lib
-}}  // namespace tf::nstd
-
-#undef TF_RETURN
-
-
-namespace tf { namespace nstd {
-
-#ifdef TF_RETURN_TYPE_DEDUCTION
-
-#define AUTO auto
-#define AUTO_RETURN(...) { return __VA_ARGS__; }
-
-#define AUTO_REFREF auto &&
-#define AUTO_REFREF_RETURN(...) { return __VA_ARGS__; }
-
-#define DECLTYPE_AUTO decltype(auto)
-#define DECLTYPE_AUTO_RETURN(...) { return __VA_ARGS__; }
-
-#else
-
-#define AUTO auto
-#define AUTO_RETURN(...) \
-  -> lib::decay_t<decltype(__VA_ARGS__)> { return __VA_ARGS__; }
-
-#define AUTO_REFREF auto
-#define AUTO_REFREF_RETURN(...)                                           \
-  -> decltype((__VA_ARGS__)) {                                            \
-    static_assert(std::is_reference<decltype((__VA_ARGS__))>::value, ""); \
-    return __VA_ARGS__;                                                   \
-  }
-
-#define DECLTYPE_AUTO auto
-#define DECLTYPE_AUTO_RETURN(...) \
-  -> decltype(__VA_ARGS__) { return __VA_ARGS__; }
-
-#endif
-
-  class bad_variant_access : public std::exception {
-    public:
-    virtual const char *what() const noexcept override { return "bad_variant_access"; }
-  };
-
-  [[noreturn]] inline void throw_bad_variant_access() {
-#ifdef TF_EXCEPTIONS
-    throw bad_variant_access{};
-#else
-    std::terminate();
-    TF_BUILTIN_UNREACHABLE;
-#endif
-  }
-
-  template <typename... Ts>
-  class variant;
-
-  template <typename T>
-  struct variant_size;
-
-#ifdef TF_VARIABLE_TEMPLATES
-  template <typename T>
-  constexpr std::size_t variant_size_v = variant_size<T>::value;
-#endif
-
-  template <typename T>
-  struct variant_size<const T> : variant_size<T> {};
-
-  template <typename T>
-  struct variant_size<volatile T> : variant_size<T> {};
-
-  template <typename T>
-  struct variant_size<const volatile T> : variant_size<T> {};
-
-  template <typename... Ts>
-  struct variant_size<variant<Ts...>> : lib::size_constant<sizeof...(Ts)> {};
-
-  template <std::size_t I, typename T>
-  struct variant_alternative;
-
-  template <std::size_t I, typename T>
-  using variant_alternative_t = typename variant_alternative<I, T>::type;
-
-  template <std::size_t I, typename T>
-  struct variant_alternative<I, const T>
-      : std::add_const<variant_alternative_t<I, T>> {};
-
-  template <std::size_t I, typename T>
-  struct variant_alternative<I, volatile T>
-      : std::add_volatile<variant_alternative_t<I, T>> {};
-
-  template <std::size_t I, typename T>
-  struct variant_alternative<I, const volatile T>
-      : std::add_cv<variant_alternative_t<I, T>> {};
-
-  template <std::size_t I, typename... Ts>
-  struct variant_alternative<I, variant<Ts...>> {
-    static_assert(I < sizeof...(Ts),
-                  "index out of bounds in `std::variant_alternative<>`");
-    using type = lib::type_pack_element_t<I, Ts...>;
-  };
-
-  constexpr std::size_t variant_npos = static_cast<std::size_t>(-1);
-
-  namespace detail {
-
-    constexpr std::size_t not_found = static_cast<std::size_t>(-1);
-    constexpr std::size_t ambiguous = static_cast<std::size_t>(-2);
-
-#ifdef TF_CPP14_CONSTEXPR
-    template <typename T, typename... Ts>
-    inline constexpr std::size_t find_index() {
-      constexpr lib::array<bool, sizeof...(Ts)> matches = {
-          {std::is_same<T, Ts>::value...}
-      };
-      std::size_t result = not_found;
-      for (std::size_t i = 0; i < sizeof...(Ts); ++i) {
-        if (matches[i]) {
-          if (result != not_found) {
-            return ambiguous;
-          }
-          result = i;
-        }
-      }
-      return result;
-    }
-#else
-    inline constexpr std::size_t find_index_impl(std::size_t result,
-                                                 std::size_t) {
-      return result;
-    }
-
-    template <typename... Bs>
-    inline constexpr std::size_t find_index_impl(std::size_t result,
-                                                 std::size_t idx,
-                                                 bool b,
-                                                 Bs... bs) {
-      return b ? (result != not_found ? ambiguous
-                                      : find_index_impl(idx, idx + 1, bs...))
-               : find_index_impl(result, idx + 1, bs...);
-    }
-
-    template <typename T, typename... Ts>
-    inline constexpr std::size_t find_index() {
-      return find_index_impl(not_found, 0, std::is_same<T, Ts>::value...);
-    }
-#endif
-
-    template <std::size_t I>
-    using find_index_sfinae_impl =
-        lib::enable_if_t<I != not_found && I != ambiguous,
-                         lib::size_constant<I>>;
-
-    template <typename T, typename... Ts>
-    using find_index_sfinae = find_index_sfinae_impl<find_index<T, Ts...>()>;
-
-    template <std::size_t I>
-    struct find_index_checked_impl : lib::size_constant<I> {
-      static_assert(I != not_found, "the specified type is not found.");
-      static_assert(I != ambiguous, "the specified type is ambiguous.");
-    };
-
-    template <typename T, typename... Ts>
-    using find_index_checked = find_index_checked_impl<find_index<T, Ts...>()>;
-
-    struct valueless_t {};
-
-    enum class Trait { TriviallyAvailable, Available, Unavailable };
-
-    template <typename T,
-              template <typename> class IsTriviallyAvailable,
-              template <typename> class IsAvailable>
-    inline constexpr Trait trait() {
-      return IsTriviallyAvailable<T>::value
-                 ? Trait::TriviallyAvailable
-                 : IsAvailable<T>::value ? Trait::Available
-                                         : Trait::Unavailable;
-    }
-
-#ifdef TF_CPP14_CONSTEXPR
-    template <typename... Traits>
-    inline constexpr Trait common_trait(Traits... traits_) {
-      Trait result = Trait::TriviallyAvailable;
-      lib::array<Trait, sizeof...(Traits)> traits = {{traits_...}};
-      for (std::size_t i = 0; i < sizeof...(Traits); ++i) {
-        Trait t = traits[i];
-        if (static_cast<int>(t) > static_cast<int>(result)) {
-          result = t;
-        }
-      }
-      return result;
-    }
-#else
-    inline constexpr Trait common_trait_impl(Trait result) { return result; }
-
-    template <typename... Traits>
-    inline constexpr Trait common_trait_impl(Trait result,
-                                             Trait t,
-                                             Traits... ts) {
-      return static_cast<int>(t) > static_cast<int>(result)
-                 ? common_trait_impl(t, ts...)
-                 : common_trait_impl(result, ts...);
-    }
-
-    template <typename... Traits>
-    inline constexpr Trait common_trait(Traits... ts) {
-      return common_trait_impl(Trait::TriviallyAvailable, ts...);
-    }
-#endif
-
-    template <typename... Ts>
-    struct traits {
-      static constexpr Trait copy_constructible_trait =
-          common_trait(trait<Ts,
-                             lib::is_trivially_copy_constructible,
-                             std::is_copy_constructible>()...);
-
-      static constexpr Trait move_constructible_trait =
-          common_trait(trait<Ts,
-                             lib::is_trivially_move_constructible,
-                             std::is_move_constructible>()...);
-
-      static constexpr Trait copy_assignable_trait =
-          common_trait(copy_constructible_trait,
-                       trait<Ts,
-                             lib::is_trivially_copy_assignable,
-                             std::is_copy_assignable>()...);
-
-      static constexpr Trait move_assignable_trait =
-          common_trait(move_constructible_trait,
-                       trait<Ts,
-                             lib::is_trivially_move_assignable,
-                             std::is_move_assignable>()...);
-
-      static constexpr Trait destructible_trait =
-          common_trait(trait<Ts,
-                             std::is_trivially_destructible,
-                             std::is_destructible>()...);
-    };
-
-    namespace access {
-
-      struct recursive_union {
-#ifdef TF_RETURN_TYPE_DEDUCTION
-        template <typename V>
-        inline static constexpr auto &&get_alt(V &&v, in_place_index_t<0>) {
-          return lib::forward<V>(v).head_;
-        }
-
-        template <typename V, std::size_t I>
-        inline static constexpr auto &&get_alt(V &&v, in_place_index_t<I>) {
-          return get_alt(lib::forward<V>(v).tail_, in_place_index_t<I - 1>{});
-        }
-#else
-        template <std::size_t I, bool Dummy = true>
-        struct get_alt_impl {
-          template <typename V>
-          inline constexpr AUTO_REFREF operator()(V &&v) const
-            AUTO_REFREF_RETURN(get_alt_impl<I - 1>{}(lib::forward<V>(v).tail_))
-        };
-
-        template <bool Dummy>
-        struct get_alt_impl<0, Dummy> {
-          template <typename V>
-          inline constexpr AUTO_REFREF operator()(V &&v) const
-            AUTO_REFREF_RETURN(lib::forward<V>(v).head_)
-        };
-
-        template <typename V, std::size_t I>
-        inline static constexpr AUTO_REFREF get_alt(V &&v, in_place_index_t<I>)
-          AUTO_REFREF_RETURN(get_alt_impl<I>{}(lib::forward<V>(v)))
-#endif
-      };
-
-      struct base {
-        template <std::size_t I, typename V>
-        inline static constexpr AUTO_REFREF get_alt(V &&v)
-#ifdef _MSC_VER
-          AUTO_REFREF_RETURN(recursive_union::get_alt(
-              lib::forward<V>(v).data_, in_place_index_t<I>{}))
-#else
-          AUTO_REFREF_RETURN(recursive_union::get_alt(
-              data(lib::forward<V>(v)), in_place_index_t<I>{}))
-#endif
-      };
-
-      struct variant {
-        template <std::size_t I, typename V>
-        inline static constexpr AUTO_REFREF get_alt(V &&v)
-          AUTO_REFREF_RETURN(base::get_alt<I>(lib::forward<V>(v).impl_))
-      };
-
-    }  // namespace access
-
-    namespace visitation {
-
-#if defined(TF_CPP14_CONSTEXPR) && !defined(_MSC_VER)
-#define TF_VARIANT_SWITCH_VISIT
-#endif
-
-      struct base {
-        template <typename Visitor, typename... Vs>
-        using dispatch_result_t = decltype(
-            lib::invoke(std::declval<Visitor>(),
-                        access::base::get_alt<0>(std::declval<Vs>())...));
-
-        template <typename Expected>
-        struct expected {
-          template <typename Actual>
-          inline static constexpr bool but_got() {
-            return std::is_same<Expected, Actual>::value;
-          }
-        };
-
-        template <typename Expected, typename Actual>
-        struct visit_return_type_check {
-          static_assert(
-              expected<Expected>::template but_got<Actual>(),
-              "`visit` requires the visitor to have a single return type");
-
-          template <typename Visitor, typename... Alts>
-          inline static constexpr DECLTYPE_AUTO invoke(Visitor &&visitor,
-                                                       Alts &&... alts)
-            DECLTYPE_AUTO_RETURN(lib::invoke(lib::forward<Visitor>(visitor),
-                                             lib::forward<Alts>(alts)...))
-        };
-
-#ifdef TF_VARIANT_SWITCH_VISIT
-        template <bool B, typename R, typename... ITs>
-        struct dispatcher;
-
-        template <typename R, typename... ITs>
-        struct dispatcher<false, R, ITs...> {
-          template <std::size_t B, typename F, typename... Vs>
-          TF_ALWAYS_INLINE static constexpr R dispatch(
-              F &&, typename ITs::type &&..., Vs &&...) {
-            TF_BUILTIN_UNREACHABLE;
-          }
-
-          template <std::size_t I, typename F, typename... Vs>
-          TF_ALWAYS_INLINE static constexpr R dispatch_case(F &&, Vs &&...) {
-            TF_BUILTIN_UNREACHABLE;
-          }
-
-          template <std::size_t B, typename F, typename... Vs>
-          TF_ALWAYS_INLINE static constexpr R dispatch_at(std::size_t,
-                                                             F &&,
-                                                             Vs &&...) {
-            TF_BUILTIN_UNREACHABLE;
-          }
-        };
-
-        template <typename R, typename... ITs>
-        struct dispatcher<true, R, ITs...> {
-          template <std::size_t B, typename F>
-          TF_ALWAYS_INLINE static constexpr R dispatch(
-              F &&f, typename ITs::type &&... visited_vs) {
-            using Expected = R;
-            using Actual = decltype(lib::invoke(
-                lib::forward<F>(f),
-                access::base::get_alt<ITs::value>(
-                    lib::forward<typename ITs::type>(visited_vs))...));
-            return visit_return_type_check<Expected, Actual>::invoke(
-                lib::forward<F>(f),
-                access::base::get_alt<ITs::value>(
-                    lib::forward<typename ITs::type>(visited_vs))...);
-          }
-
-          template <std::size_t B, typename F, typename V, typename... Vs>
-          TF_ALWAYS_INLINE static constexpr R dispatch(
-              F &&f, typename ITs::type &&... visited_vs, V &&v, Vs &&... vs) {
-#define TF_DISPATCH(I)                                                   \
-  dispatcher<(I < lib::decay_t<V>::size()),                                 \
-             R,                                                             \
-             ITs...,                                                        \
-             lib::indexed_type<I, V>>::                                     \
-      template dispatch<0>(lib::forward<F>(f),                              \
-                           lib::forward<typename ITs::type>(visited_vs)..., \
-                           lib::forward<V>(v),                              \
-                           lib::forward<Vs>(vs)...)
-
-#define TF_DEFAULT(I)                                                      \
-  dispatcher<(I < lib::decay_t<V>::size()), R, ITs...>::template dispatch<I>( \
-      lib::forward<F>(f),                                                     \
-      lib::forward<typename ITs::type>(visited_vs)...,                        \
-      lib::forward<V>(v),                                                     \
-      lib::forward<Vs>(vs)...)
-
-            switch (v.index()) {
-              case B + 0: return TF_DISPATCH(B + 0);
-              case B + 1: return TF_DISPATCH(B + 1);
-              case B + 2: return TF_DISPATCH(B + 2);
-              case B + 3: return TF_DISPATCH(B + 3);
-              case B + 4: return TF_DISPATCH(B + 4);
-              case B + 5: return TF_DISPATCH(B + 5);
-              case B + 6: return TF_DISPATCH(B + 6);
-              case B + 7: return TF_DISPATCH(B + 7);
-              case B + 8: return TF_DISPATCH(B + 8);
-              case B + 9: return TF_DISPATCH(B + 9);
-              case B + 10: return TF_DISPATCH(B + 10);
-              case B + 11: return TF_DISPATCH(B + 11);
-              case B + 12: return TF_DISPATCH(B + 12);
-              case B + 13: return TF_DISPATCH(B + 13);
-              case B + 14: return TF_DISPATCH(B + 14);
-              case B + 15: return TF_DISPATCH(B + 15);
-              case B + 16: return TF_DISPATCH(B + 16);
-              case B + 17: return TF_DISPATCH(B + 17);
-              case B + 18: return TF_DISPATCH(B + 18);
-              case B + 19: return TF_DISPATCH(B + 19);
-              case B + 20: return TF_DISPATCH(B + 20);
-              case B + 21: return TF_DISPATCH(B + 21);
-              case B + 22: return TF_DISPATCH(B + 22);
-              case B + 23: return TF_DISPATCH(B + 23);
-              case B + 24: return TF_DISPATCH(B + 24);
-              case B + 25: return TF_DISPATCH(B + 25);
-              case B + 26: return TF_DISPATCH(B + 26);
-              case B + 27: return TF_DISPATCH(B + 27);
-              case B + 28: return TF_DISPATCH(B + 28);
-              case B + 29: return TF_DISPATCH(B + 29);
-              case B + 30: return TF_DISPATCH(B + 30);
-              case B + 31: return TF_DISPATCH(B + 31);
-              default: return TF_DEFAULT(B + 32);
-            }
-
-#undef TF_DEFAULT
-#undef TF_DISPATCH
-          }
-
-          template <std::size_t I, typename F, typename... Vs>
-          TF_ALWAYS_INLINE static constexpr R dispatch_case(F &&f,
-                                                               Vs &&... vs) {
-            using Expected = R;
-            using Actual = decltype(
-                lib::invoke(lib::forward<F>(f),
-                            access::base::get_alt<I>(lib::forward<Vs>(vs))...));
-            return visit_return_type_check<Expected, Actual>::invoke(
-                lib::forward<F>(f),
-                access::base::get_alt<I>(lib::forward<Vs>(vs))...);
-          }
-
-          template <std::size_t B, typename F, typename V, typename... Vs>
-          TF_ALWAYS_INLINE static constexpr R dispatch_at(std::size_t index,
-                                                             F &&f,
-                                                             V &&v,
-                                                             Vs &&... vs) {
-            static_assert(lib::all<(lib::decay_t<V>::size() ==
-                                    lib::decay_t<Vs>::size())...>::value,
-                          "all of the variants must be the same size.");
-#define TF_DISPATCH_AT(I)                                               \
-  dispatcher<(I < lib::decay_t<V>::size()), R>::template dispatch_case<I>( \
-      lib::forward<F>(f), lib::forward<V>(v), lib::forward<Vs>(vs)...)
-
-#define TF_DEFAULT(I)                                                 \
-  dispatcher<(I < lib::decay_t<V>::size()), R>::template dispatch_at<I>( \
-      index, lib::forward<F>(f), lib::forward<V>(v), lib::forward<Vs>(vs)...)
-
-            switch (index) {
-              case B + 0: return TF_DISPATCH_AT(B + 0);
-              case B + 1: return TF_DISPATCH_AT(B + 1);
-              case B + 2: return TF_DISPATCH_AT(B + 2);
-              case B + 3: return TF_DISPATCH_AT(B + 3);
-              case B + 4: return TF_DISPATCH_AT(B + 4);
-              case B + 5: return TF_DISPATCH_AT(B + 5);
-              case B + 6: return TF_DISPATCH_AT(B + 6);
-              case B + 7: return TF_DISPATCH_AT(B + 7);
-              case B + 8: return TF_DISPATCH_AT(B + 8);
-              case B + 9: return TF_DISPATCH_AT(B + 9);
-              case B + 10: return TF_DISPATCH_AT(B + 10);
-              case B + 11: return TF_DISPATCH_AT(B + 11);
-              case B + 12: return TF_DISPATCH_AT(B + 12);
-              case B + 13: return TF_DISPATCH_AT(B + 13);
-              case B + 14: return TF_DISPATCH_AT(B + 14);
-              case B + 15: return TF_DISPATCH_AT(B + 15);
-              case B + 16: return TF_DISPATCH_AT(B + 16);
-              case B + 17: return TF_DISPATCH_AT(B + 17);
-              case B + 18: return TF_DISPATCH_AT(B + 18);
-              case B + 19: return TF_DISPATCH_AT(B + 19);
-              case B + 20: return TF_DISPATCH_AT(B + 20);
-              case B + 21: return TF_DISPATCH_AT(B + 21);
-              case B + 22: return TF_DISPATCH_AT(B + 22);
-              case B + 23: return TF_DISPATCH_AT(B + 23);
-              case B + 24: return TF_DISPATCH_AT(B + 24);
-              case B + 25: return TF_DISPATCH_AT(B + 25);
-              case B + 26: return TF_DISPATCH_AT(B + 26);
-              case B + 27: return TF_DISPATCH_AT(B + 27);
-              case B + 28: return TF_DISPATCH_AT(B + 28);
-              case B + 29: return TF_DISPATCH_AT(B + 29);
-              case B + 30: return TF_DISPATCH_AT(B + 30);
-              case B + 31: return TF_DISPATCH_AT(B + 31);
-              default: return TF_DEFAULT(B + 32);
-            }
-
-#undef TF_DEFAULT
-#undef TF_DISPATCH_AT
-          }
-        };
-#else
-        template <typename T>
-        inline static constexpr const T &at(const T &elem) noexcept {
-          return elem;
-        }
-
-        template <typename T, std::size_t N, typename... Is>
-        inline static constexpr const lib::remove_all_extents_t<T> &at(
-            const lib::array<T, N> &elems, std::size_t i, Is... is) noexcept {
-          return at(elems[i], is...);
-        }
-
-        template <typename F, typename... Fs>
-        inline static constexpr lib::array<lib::decay_t<F>, sizeof...(Fs) + 1>
-        make_farray(F &&f, Fs &&... fs) {
-          return {{lib::forward<F>(f), lib::forward<Fs>(fs)...}};
-        }
-
-        template <typename F, typename... Vs>
-        struct make_fmatrix_impl {
-
-          template <std::size_t... Is>
-          inline static constexpr dispatch_result_t<F, Vs...> dispatch(
-              F &&f, Vs &&... vs) {
-            using Expected = dispatch_result_t<F, Vs...>;
-            using Actual = decltype(lib::invoke(
-                lib::forward<F>(f),
-                access::base::get_alt<Is>(lib::forward<Vs>(vs))...));
-            return visit_return_type_check<Expected, Actual>::invoke(
-                lib::forward<F>(f),
-                access::base::get_alt<Is>(lib::forward<Vs>(vs))...);
-          }
-
-#ifdef TF_RETURN_TYPE_DEDUCTION
-          template <std::size_t... Is>
-          inline static constexpr auto impl(lib::index_sequence<Is...>) {
-            return &dispatch<Is...>;
-          }
-
-          template <typename Is, std::size_t... Js, typename... Ls>
-          inline static constexpr auto impl(Is,
-                                            lib::index_sequence<Js...>,
-                                            Ls... ls) {
-            return make_farray(impl(lib::push_back_t<Is, Js>{}, ls...)...);
-          }
-#else
-          template <typename...>
-          struct impl;
-
-          template <std::size_t... Is>
-          struct impl<lib::index_sequence<Is...>> {
-            inline constexpr AUTO operator()() const
-              AUTO_RETURN(&dispatch<Is...>)
-          };
-
-          template <typename Is, std::size_t... Js, typename... Ls>
-          struct impl<Is, lib::index_sequence<Js...>, Ls...> {
-            inline constexpr AUTO operator()() const
-              AUTO_RETURN(
-                  make_farray(impl<lib::push_back_t<Is, Js>, Ls...>{}()...))
-          };
-#endif
-        };
-
-#ifdef TF_RETURN_TYPE_DEDUCTION
-        template <typename F, typename... Vs>
-        inline static constexpr auto make_fmatrix() {
-          return make_fmatrix_impl<F, Vs...>::impl(
-              lib::index_sequence<>{},
-              lib::make_index_sequence<lib::decay_t<Vs>::size()>{}...);
-        }
-#else
-        template <typename F, typename... Vs>
-        inline static constexpr AUTO make_fmatrix()
-          AUTO_RETURN(
-              typename make_fmatrix_impl<F, Vs...>::template impl<
-                  lib::index_sequence<>,
-                  lib::make_index_sequence<lib::decay_t<Vs>::size()>...>{}())
-#endif
-
-        template <typename F, typename... Vs>
-        struct make_fdiagonal_impl {
-          template <std::size_t I>
-          inline static constexpr dispatch_result_t<F, Vs...> dispatch(
-              F &&f, Vs &&... vs) {
-            using Expected = dispatch_result_t<F, Vs...>;
-            using Actual = decltype(
-                lib::invoke(lib::forward<F>(f),
-                            access::base::get_alt<I>(lib::forward<Vs>(vs))...));
-            return visit_return_type_check<Expected, Actual>::invoke(
-                lib::forward<F>(f),
-                access::base::get_alt<I>(lib::forward<Vs>(vs))...);
-          }
-
-          template <std::size_t... Is>
-          inline static constexpr AUTO impl(lib::index_sequence<Is...>)
-            AUTO_RETURN(make_farray(&dispatch<Is>...))
-        };
-
-        template <typename F, typename V, typename... Vs>
-        inline static constexpr auto make_fdiagonal()
-            -> decltype(make_fdiagonal_impl<F, V, Vs...>::impl(
-                lib::make_index_sequence<lib::decay_t<V>::size()>{})) {
-          static_assert(lib::all<(lib::decay_t<V>::size() ==
-                                  lib::decay_t<Vs>::size())...>::value,
-                        "all of the variants must be the same size.");
-          return make_fdiagonal_impl<F, V, Vs...>::impl(
-              lib::make_index_sequence<lib::decay_t<V>::size()>{});
-        }
-#endif
-      };
-
-#if !defined(TF_VARIANT_SWITCH_VISIT) && \
-    (!defined(_MSC_VER) || _MSC_VER >= 1910)
-      template <typename F, typename... Vs>
-      using fmatrix_t = decltype(base::make_fmatrix<F, Vs...>());
-
-      template <typename F, typename... Vs>
-      struct fmatrix {
-        static constexpr fmatrix_t<F, Vs...> value =
-            base::make_fmatrix<F, Vs...>();
-      };
-
-      template <typename F, typename... Vs>
-      constexpr fmatrix_t<F, Vs...> fmatrix<F, Vs...>::value;
-
-      template <typename F, typename... Vs>
-      using fdiagonal_t = decltype(base::make_fdiagonal<F, Vs...>());
-
-      template <typename F, typename... Vs>
-      struct fdiagonal {
-        static constexpr fdiagonal_t<F, Vs...> value =
-            base::make_fdiagonal<F, Vs...>();
-      };
-
-      template <typename F, typename... Vs>
-      constexpr fdiagonal_t<F, Vs...> fdiagonal<F, Vs...>::value;
-#endif
-
-      struct alt {
-        template <typename Visitor, typename... Vs>
-        inline static constexpr DECLTYPE_AUTO visit_alt(Visitor &&visitor,
-                                                        Vs &&... vs)
-#ifdef TF_VARIANT_SWITCH_VISIT
-          DECLTYPE_AUTO_RETURN(
-              base::dispatcher<
-                  true,
-                  base::dispatch_result_t<Visitor,
-                                          decltype(as_base(
-                                              lib::forward<Vs>(vs)))...>>::
-                  template dispatch<0>(lib::forward<Visitor>(visitor),
-                                       as_base(lib::forward<Vs>(vs))...))
-#elif !defined(_MSC_VER) || _MSC_VER >= 1910
-          DECLTYPE_AUTO_RETURN(base::at(
-              fmatrix<Visitor &&,
-                      decltype(as_base(lib::forward<Vs>(vs)))...>::value,
-              vs.index()...)(lib::forward<Visitor>(visitor),
-                             as_base(lib::forward<Vs>(vs))...))
-#else
-          DECLTYPE_AUTO_RETURN(base::at(
-              base::make_fmatrix<Visitor &&,
-                      decltype(as_base(lib::forward<Vs>(vs)))...>(),
-              vs.index()...)(lib::forward<Visitor>(visitor),
-                             as_base(lib::forward<Vs>(vs))...))
-#endif
-
-        template <typename Visitor, typename... Vs>
-        inline static constexpr DECLTYPE_AUTO visit_alt_at(std::size_t index,
-                                                           Visitor &&visitor,
-                                                           Vs &&... vs)
-#ifdef TF_VARIANT_SWITCH_VISIT
-          DECLTYPE_AUTO_RETURN(
-              base::dispatcher<
-                  true,
-                  base::dispatch_result_t<Visitor,
-                                          decltype(as_base(
-                                              lib::forward<Vs>(vs)))...>>::
-                  template dispatch_at<0>(index,
-                                          lib::forward<Visitor>(visitor),
-                                          as_base(lib::forward<Vs>(vs))...))
-#elif !defined(_MSC_VER) || _MSC_VER >= 1910
-          DECLTYPE_AUTO_RETURN(base::at(
-              fdiagonal<Visitor &&,
-                        decltype(as_base(lib::forward<Vs>(vs)))...>::value,
-              index)(lib::forward<Visitor>(visitor),
-                     as_base(lib::forward<Vs>(vs))...))
-#else
-          DECLTYPE_AUTO_RETURN(base::at(
-              base::make_fdiagonal<Visitor &&,
-                        decltype(as_base(lib::forward<Vs>(vs)))...>(),
-              index)(lib::forward<Visitor>(visitor),
-                     as_base(lib::forward<Vs>(vs))...))
-#endif
-      };
-
-      struct variant {
-        private:
-        template <typename Visitor>
-        struct visitor {
-          template <typename... Values>
-          inline static constexpr bool does_not_handle() {
-            return lib::is_invocable<Visitor, Values...>::value;
-          }
-        };
-
-        template <typename Visitor, typename... Values>
-        struct visit_exhaustiveness_check {
-          static_assert(visitor<Visitor>::template does_not_handle<Values...>(),
-                        "`visit` requires the visitor to be exhaustive.");
-
-          inline static constexpr DECLTYPE_AUTO invoke(Visitor &&visitor,
-                                                       Values &&... values)
-            DECLTYPE_AUTO_RETURN(lib::invoke(lib::forward<Visitor>(visitor),
-                                             lib::forward<Values>(values)...))
-        };
-
-        template <typename Visitor>
-        struct value_visitor {
-          Visitor &&visitor_;
-
-          template <typename... Alts>
-          inline constexpr DECLTYPE_AUTO operator()(Alts &&... alts) const
-            DECLTYPE_AUTO_RETURN(
-                visit_exhaustiveness_check<
-                    Visitor,
-                    decltype((lib::forward<Alts>(alts).value))...>::
-                    invoke(lib::forward<Visitor>(visitor_),
-                           lib::forward<Alts>(alts).value...))
-        };
-
-        template <typename Visitor>
-        inline static constexpr AUTO make_value_visitor(Visitor &&visitor)
-          AUTO_RETURN(value_visitor<Visitor>{lib::forward<Visitor>(visitor)})
-
-        public:
-        template <typename Visitor, typename... Vs>
-        inline static constexpr DECLTYPE_AUTO visit_alt(Visitor &&visitor,
-                                                        Vs &&... vs)
-          DECLTYPE_AUTO_RETURN(alt::visit_alt(lib::forward<Visitor>(visitor),
-                                              lib::forward<Vs>(vs).impl_...))
-
-        template <typename Visitor, typename... Vs>
-        inline static constexpr DECLTYPE_AUTO visit_alt_at(std::size_t index,
-                                                           Visitor &&visitor,
-                                                           Vs &&... vs)
-          DECLTYPE_AUTO_RETURN(
-              alt::visit_alt_at(index,
-                                lib::forward<Visitor>(visitor),
-                                lib::forward<Vs>(vs).impl_...))
-
-        template <typename Visitor, typename... Vs>
-        inline static constexpr DECLTYPE_AUTO visit_value(Visitor &&visitor,
-                                                          Vs &&... vs)
-          DECLTYPE_AUTO_RETURN(
-              visit_alt(make_value_visitor(lib::forward<Visitor>(visitor)),
-                        lib::forward<Vs>(vs)...))
-
-        template <typename Visitor, typename... Vs>
-        inline static constexpr DECLTYPE_AUTO visit_value_at(std::size_t index,
-                                                             Visitor &&visitor,
-                                                             Vs &&... vs)
-          DECLTYPE_AUTO_RETURN(
-              visit_alt_at(index,
-                           make_value_visitor(lib::forward<Visitor>(visitor)),
-                           lib::forward<Vs>(vs)...))
-      };
-
-    }  // namespace visitation
-
-    template <std::size_t Index, typename T>
-    struct alt {
-      using value_type = T;
-
-#ifdef _MSC_VER
-#pragma warning(push)
-#pragma warning(disable : 4244)
-#endif
-      template <typename... Args>
-      inline explicit constexpr alt(in_place_t, Args &&... args)
-          : value(lib::forward<Args>(args)...) {}
-#ifdef _MSC_VER
-#pragma warning(pop)
-#endif
-
-      T value;
-    };
-
-    template <Trait DestructibleTrait, std::size_t Index, typename... Ts>
-    union recursive_union;
-
-    template <Trait DestructibleTrait, std::size_t Index>
-    union recursive_union<DestructibleTrait, Index> {};
-
-#define TF_VARIANT_RECURSIVE_UNION(destructible_trait, destructor)      \
-  template <std::size_t Index, typename T, typename... Ts>                 \
-  union recursive_union<destructible_trait, Index, T, Ts...> {             \
-    public:                                                                \
-    inline explicit constexpr recursive_union(valueless_t) noexcept        \
-        : dummy_{} {}                                                      \
-                                                                           \
-    template <typename... Args>                                            \
-    inline explicit constexpr recursive_union(in_place_index_t<0>,         \
-                                              Args &&... args)             \
-        : head_(in_place_t{}, lib::forward<Args>(args)...) {}              \
-                                                                           \
-    template <std::size_t I, typename... Args>                             \
-    inline explicit constexpr recursive_union(in_place_index_t<I>,         \
-                                              Args &&... args)             \
-        : tail_(in_place_index_t<I - 1>{}, lib::forward<Args>(args)...) {} \
-                                                                           \
-    recursive_union(const recursive_union &) = default;                    \
-    recursive_union(recursive_union &&) = default;                         \
-                                                                           \
-    destructor                                                             \
-                                                                           \
-    recursive_union &operator=(const recursive_union &) = default;         \
-    recursive_union &operator=(recursive_union &&) = default;              \
-                                                                           \
-    private:                                                               \
-    char dummy_;                                                           \
-    alt<Index, T> head_;                                                   \
-    recursive_union<destructible_trait, Index + 1, Ts...> tail_;           \
-                                                                           \
-    friend struct access::recursive_union;                                 \
-  }
-
-    TF_VARIANT_RECURSIVE_UNION(Trait::TriviallyAvailable,
-                                  ~recursive_union() = default;);
-    TF_VARIANT_RECURSIVE_UNION(Trait::Available,
-                                  ~recursive_union() {});
-    TF_VARIANT_RECURSIVE_UNION(Trait::Unavailable,
-                                  ~recursive_union() = delete;);
-
-#undef TF_VARIANT_RECURSIVE_UNION
-
-    template <typename... Ts>
-    using index_t = typename std::conditional<
-            sizeof...(Ts) < (std::numeric_limits<unsigned char>::max)(),
-            unsigned char,
-            typename std::conditional<
-                sizeof...(Ts) < (std::numeric_limits<unsigned short>::max)(),
-                unsigned short,
-                unsigned int>::type
-            >::type;
-
-    template <Trait DestructibleTrait, typename... Ts>
-    class base {
-      public:
-      inline explicit constexpr base(valueless_t tag) noexcept
-          : data_(tag), index_(static_cast<index_t<Ts...>>(-1)) {}
-
-      template <std::size_t I, typename... Args>
-      inline explicit constexpr base(in_place_index_t<I>, Args &&... args)
-          : data_(in_place_index_t<I>{}, lib::forward<Args>(args)...),
-            index_(I) {}
-
-      inline constexpr bool valueless_by_exception() const noexcept {
-        return index_ == static_cast<index_t<Ts...>>(-1);
-      }
-
-      inline constexpr std::size_t index() const noexcept {
-        return valueless_by_exception() ? variant_npos : index_;
-      }
-
-      protected:
-      using data_t = recursive_union<DestructibleTrait, 0, Ts...>;
-
-      friend inline constexpr base &as_base(base &b) { return b; }
-      friend inline constexpr const base &as_base(const base &b) { return b; }
-      friend inline constexpr base &&as_base(base &&b) { return lib::move(b); }
-      friend inline constexpr const base &&as_base(const base &&b) { return lib::move(b); }
-
-      friend inline constexpr data_t &data(base &b) { return b.data_; }
-      friend inline constexpr const data_t &data(const base &b) { return b.data_; }
-      friend inline constexpr data_t &&data(base &&b) { return lib::move(b).data_; }
-      friend inline constexpr const data_t &&data(const base &&b) { return lib::move(b).data_; }
-
-      inline static constexpr std::size_t size() { return sizeof...(Ts); }
-
-      data_t data_;
-      index_t<Ts...> index_;
-
-      friend struct access::base;
-      friend struct visitation::base;
-    };
-
-    struct dtor {
-#ifdef _MSC_VER
-#pragma warning(push)
-#pragma warning(disable : 4100)
-#endif
-      template <typename Alt>
-      inline void operator()(Alt &alt) const noexcept { alt.~Alt(); }
-#ifdef _MSC_VER
-#pragma warning(pop)
-#endif
-    };
-
-#if !defined(_MSC_VER) || _MSC_VER >= 1910
-#define TF_INHERITING_CTOR(type, base) using base::base;
-#else
-#define TF_INHERITING_CTOR(type, base)         \
-  template <typename... Args>                     \
-  inline explicit constexpr type(Args &&... args) \
-      : base(lib::forward<Args>(args)...) {}
-#endif
-
-    template <typename Traits, Trait = Traits::destructible_trait>
-    class destructor;
-
-#define TF_VARIANT_DESTRUCTOR(destructible_trait, definition, destroy) \
-  template <typename... Ts>                                               \
-  class destructor<traits<Ts...>, destructible_trait>                     \
-      : public base<destructible_trait, Ts...> {                          \
-    using super = base<destructible_trait, Ts...>;                        \
-                                                                          \
-    public:                                                               \
-    TF_INHERITING_CTOR(destructor, super)                              \
-    using super::operator=;                                               \
-                                                                          \
-    destructor(const destructor &) = default;                             \
-    destructor(destructor &&) = default;                                  \
-    definition                                                            \
-    destructor &operator=(const destructor &) = default;                  \
-    destructor &operator=(destructor &&) = default;                       \
-                                                                          \
-    protected:                                                            \
-    destroy                                                               \
-  }
-
-    TF_VARIANT_DESTRUCTOR(
-        Trait::TriviallyAvailable,
-        ~destructor() = default;,
-        inline void destroy() noexcept {
-          this->index_ = static_cast<index_t<Ts...>>(-1);
-        });
-
-    TF_VARIANT_DESTRUCTOR(
-        Trait::Available,
-        ~destructor() { destroy(); },
-        inline void destroy() noexcept {
-          if (!this->valueless_by_exception()) {
-            visitation::alt::visit_alt(dtor{}, *this);
-          }
-          this->index_ = static_cast<index_t<Ts...>>(-1);
-        });
-
-    TF_VARIANT_DESTRUCTOR(
-        Trait::Unavailable,
-        ~destructor() = delete;,
-        inline void destroy() noexcept = delete;);
-
-#undef TF_VARIANT_DESTRUCTOR
-
-    template <typename Traits>
-    class constructor : public destructor<Traits> {
-      using super = destructor<Traits>;
-
-      public:
-      TF_INHERITING_CTOR(constructor, super)
-      using super::operator=;
-
-      protected:
-#ifndef TF_GENERIC_LAMBDAS
-      struct ctor {
-        template <typename LhsAlt, typename RhsAlt>
-        inline void operator()(LhsAlt &lhs_alt, RhsAlt &&rhs_alt) const {
-          constructor::construct_alt(lhs_alt,
-                                     lib::forward<RhsAlt>(rhs_alt).value);
-        }
-      };
-#endif
-
-      template <std::size_t I, typename T, typename... Args>
-      inline static T &construct_alt(alt<I, T> &a, Args &&... args) {
-        auto *result = ::new (static_cast<void *>(lib::addressof(a)))
-            alt<I, T>(in_place_t{}, lib::forward<Args>(args)...);
-        return result->value;
-      }
-
-      template <typename Rhs>
-      inline static void generic_construct(constructor &lhs, Rhs &&rhs) {
-        lhs.destroy();
-        if (!rhs.valueless_by_exception()) {
-          visitation::alt::visit_alt_at(
-              rhs.index(),
-#ifdef TF_GENERIC_LAMBDAS
-              [](auto &lhs_alt, auto &&rhs_alt) {
-                constructor::construct_alt(
-                    lhs_alt, lib::forward<decltype(rhs_alt)>(rhs_alt).value);
-              }
-#else
-              ctor{}
-#endif
-              ,
-              lhs,
-              lib::forward<Rhs>(rhs));
-          lhs.index_ = rhs.index_;
-        }
-      }
-    };
-
-    template <typename Traits, Trait = Traits::move_constructible_trait>
-    class move_constructor;
-
-#define TF_VARIANT_MOVE_CONSTRUCTOR(move_constructible_trait, definition) \
-  template <typename... Ts>                                                  \
-  class move_constructor<traits<Ts...>, move_constructible_trait>            \
-      : public constructor<traits<Ts...>> {                                  \
-    using super = constructor<traits<Ts...>>;                                \
-                                                                             \
-    public:                                                                  \
-    TF_INHERITING_CTOR(move_constructor, super)                           \
-    using super::operator=;                                                  \
-                                                                             \
-    move_constructor(const move_constructor &) = default;                    \
-    definition                                                               \
-    ~move_constructor() = default;                                           \
-    move_constructor &operator=(const move_constructor &) = default;         \
-    move_constructor &operator=(move_constructor &&) = default;              \
-  }
-
-    TF_VARIANT_MOVE_CONSTRUCTOR(
-        Trait::TriviallyAvailable,
-        move_constructor(move_constructor &&that) = default;);
-
-    TF_VARIANT_MOVE_CONSTRUCTOR(
-        Trait::Available,
-        move_constructor(move_constructor &&that) noexcept(
-            lib::all<std::is_nothrow_move_constructible<Ts>::value...>::value)
-            : move_constructor(valueless_t{}) {
-          this->generic_construct(*this, lib::move(that));
-        });
-
-    TF_VARIANT_MOVE_CONSTRUCTOR(
-        Trait::Unavailable,
-        move_constructor(move_constructor &&) = delete;);
-
-#undef TF_VARIANT_MOVE_CONSTRUCTOR
-
-    template <typename Traits, Trait = Traits::copy_constructible_trait>
-    class copy_constructor;
-
-#define TF_VARIANT_COPY_CONSTRUCTOR(copy_constructible_trait, definition) \
-  template <typename... Ts>                                                  \
-  class copy_constructor<traits<Ts...>, copy_constructible_trait>            \
-      : public move_constructor<traits<Ts...>> {                             \
-    using super = move_constructor<traits<Ts...>>;                           \
-                                                                             \
-    public:                                                                  \
-    TF_INHERITING_CTOR(copy_constructor, super)                           \
-    using super::operator=;                                                  \
-                                                                             \
-    definition                                                               \
-    copy_constructor(copy_constructor &&) = default;                         \
-    ~copy_constructor() = default;                                           \
-    copy_constructor &operator=(const copy_constructor &) = default;         \
-    copy_constructor &operator=(copy_constructor &&) = default;              \
-  }
-
-    TF_VARIANT_COPY_CONSTRUCTOR(
-        Trait::TriviallyAvailable,
-        copy_constructor(const copy_constructor &that) = default;);
-
-    TF_VARIANT_COPY_CONSTRUCTOR(
-        Trait::Available,
-        copy_constructor(const copy_constructor &that)
-            : copy_constructor(valueless_t{}) {
-          this->generic_construct(*this, that);
-        });
-
-    TF_VARIANT_COPY_CONSTRUCTOR(
-        Trait::Unavailable,
-        copy_constructor(const copy_constructor &) = delete;);
-
-#undef TF_VARIANT_COPY_CONSTRUCTOR
-
-    template <typename Traits>
-    class assignment : public copy_constructor<Traits> {
-      using super = copy_constructor<Traits>;
-
-      public:
-      TF_INHERITING_CTOR(assignment, super)
-      using super::operator=;
-
-      template <std::size_t I, typename... Args>
-      inline /* auto & */ auto emplace(Args &&... args)
-          -> decltype(this->construct_alt(access::base::get_alt<I>(*this),
-                                          lib::forward<Args>(args)...)) {
-        this->destroy();
-        auto &result = this->construct_alt(access::base::get_alt<I>(*this),
-                                           lib::forward<Args>(args)...);
-        this->index_ = I;
-        return result;
-      }
-
-      protected:
-#ifndef TF_GENERIC_LAMBDAS
-      template <typename That>
-      struct assigner {
-        template <typename ThisAlt, typename ThatAlt>
-        inline void operator()(ThisAlt &this_alt, ThatAlt &&that_alt) const {
-          self->assign_alt(this_alt, lib::forward<ThatAlt>(that_alt).value);
-        }
-        assignment *self;
-      };
-#endif
-
-      template <std::size_t I, typename T, typename Arg>
-      inline void assign_alt(alt<I, T> &a, Arg &&arg) {
-        if (this->index() == I) {
-#ifdef _MSC_VER
-#pragma warning(push)
-#pragma warning(disable : 4244)
-#endif
-          a.value = lib::forward<Arg>(arg);
-#ifdef _MSC_VER
-#pragma warning(pop)
-#endif
-        } else {
-          struct {
-            void operator()(std::true_type) const {
-              this_->emplace<I>(lib::forward<Arg>(arg_));
-            }
-            void operator()(std::false_type) const {
-              this_->emplace<I>(T(lib::forward<Arg>(arg_)));
-            }
-            assignment *this_;
-            Arg &&arg_;
-          } impl{this, lib::forward<Arg>(arg)};
-          impl(lib::bool_constant<
-                   std::is_nothrow_constructible<T, Arg>::value ||
-                   !std::is_nothrow_move_constructible<T>::value>{});
-        }
-      }
-
-      template <typename That>
-      inline void generic_assign(That &&that) {
-        if (this->valueless_by_exception() && that.valueless_by_exception()) {
-          // do nothing.
-        } else if (that.valueless_by_exception()) {
-          this->destroy();
-        } else {
-          visitation::alt::visit_alt_at(
-              that.index(),
-#ifdef TF_GENERIC_LAMBDAS
-              [this](auto &this_alt, auto &&that_alt) {
-                this->assign_alt(
-                    this_alt, lib::forward<decltype(that_alt)>(that_alt).value);
-              }
-#else
-              assigner<That>{this}
-#endif
-              ,
-              *this,
-              lib::forward<That>(that));
-        }
-      }
-    };
-
-    template <typename Traits, Trait = Traits::move_assignable_trait>
-    class move_assignment;
-
-#define TF_VARIANT_MOVE_ASSIGNMENT(move_assignable_trait, definition) \
-  template <typename... Ts>                                              \
-  class move_assignment<traits<Ts...>, move_assignable_trait>            \
-      : public assignment<traits<Ts...>> {                               \
-    using super = assignment<traits<Ts...>>;                             \
-                                                                         \
-    public:                                                              \
-    TF_INHERITING_CTOR(move_assignment, super)                        \
-    using super::operator=;                                              \
-                                                                         \
-    move_assignment(const move_assignment &) = default;                  \
-    move_assignment(move_assignment &&) = default;                       \
-    ~move_assignment() = default;                                        \
-    move_assignment &operator=(const move_assignment &) = default;       \
-    definition                                                           \
-  }
-
-    TF_VARIANT_MOVE_ASSIGNMENT(
-        Trait::TriviallyAvailable,
-        move_assignment &operator=(move_assignment &&that) = default;);
-
-    TF_VARIANT_MOVE_ASSIGNMENT(
-        Trait::Available,
-        move_assignment &
-        operator=(move_assignment &&that) noexcept(
-            lib::all<(std::is_nothrow_move_constructible<Ts>::value &&
-                      std::is_nothrow_move_assignable<Ts>::value)...>::value) {
-          this->generic_assign(lib::move(that));
-          return *this;
-        });
-
-    TF_VARIANT_MOVE_ASSIGNMENT(
-        Trait::Unavailable,
-        move_assignment &operator=(move_assignment &&) = delete;);
-
-#undef TF_VARIANT_MOVE_ASSIGNMENT
-
-    template <typename Traits, Trait = Traits::copy_assignable_trait>
-    class copy_assignment;
-
-#define TF_VARIANT_COPY_ASSIGNMENT(copy_assignable_trait, definition) \
-  template <typename... Ts>                                              \
-  class copy_assignment<traits<Ts...>, copy_assignable_trait>            \
-      : public move_assignment<traits<Ts...>> {                          \
-    using super = move_assignment<traits<Ts...>>;                        \
-                                                                         \
-    public:                                                              \
-    TF_INHERITING_CTOR(copy_assignment, super)                        \
-    using super::operator=;                                              \
-                                                                         \
-    copy_assignment(const copy_assignment &) = default;                  \
-    copy_assignment(copy_assignment &&) = default;                       \
-    ~copy_assignment() = default;                                        \
-    definition                                                           \
-    copy_assignment &operator=(copy_assignment &&) = default;            \
-  }
-
-    TF_VARIANT_COPY_ASSIGNMENT(
-        Trait::TriviallyAvailable,
-        copy_assignment &operator=(const copy_assignment &that) = default;);
-
-    TF_VARIANT_COPY_ASSIGNMENT(
-        Trait::Available,
-        copy_assignment &operator=(const copy_assignment &that) {
-          this->generic_assign(that);
-          return *this;
-        });
-
-    TF_VARIANT_COPY_ASSIGNMENT(
-        Trait::Unavailable,
-        copy_assignment &operator=(const copy_assignment &) = delete;);
-
-#undef TF_VARIANT_COPY_ASSIGNMENT
-
-    template <typename... Ts>
-    class impl : public copy_assignment<traits<Ts...>> {
-      using super = copy_assignment<traits<Ts...>>;
-
-      public:
-      TF_INHERITING_CTOR(impl, super)
-      using super::operator=;
-
-      impl(const impl&) = default;
-      impl(impl&&) = default;
-      ~impl() = default;
-      impl &operator=(const impl &) = default;
-      impl &operator=(impl &&) = default;
-
-      template <std::size_t I, typename Arg>
-      inline void assign(Arg &&arg) {
-        this->assign_alt(access::base::get_alt<I>(*this),
-                         lib::forward<Arg>(arg));
-      }
-
-      inline void swap(impl &that) {
-        if (this->valueless_by_exception() && that.valueless_by_exception()) {
-          // do nothing.
-        } else if (this->index() == that.index()) {
-          visitation::alt::visit_alt_at(this->index(),
-#ifdef TF_GENERIC_LAMBDAS
-                                        [](auto &this_alt, auto &that_alt) {
-                                          using std::swap;
-                                          swap(this_alt.value,
-                                               that_alt.value);
-                                        }
-#else
-                                        swapper{}
-#endif
-                                        ,
-                                        *this,
-                                        that);
-        } else {
-          impl *lhs = this;
-          impl *rhs = lib::addressof(that);
-          if (lhs->move_nothrow() && !rhs->move_nothrow()) {
-            std::swap(lhs, rhs);
-          }
-          impl tmp(lib::move(*rhs));
-#ifdef TF_EXCEPTIONS
-          // EXTENSION: When the move construction of `lhs` into `rhs` throws
-          // and `tmp` is nothrow move constructible then we move `tmp` back
-          // into `rhs` and provide the strong exception safety guarantee.
-          try {
-            this->generic_construct(*rhs, lib::move(*lhs));
-          } catch (...) {
-            if (tmp.move_nothrow()) {
-              this->generic_construct(*rhs, lib::move(tmp));
-            }
-            throw;
-          }
-#else
-          this->generic_construct(*rhs, lib::move(*lhs));
-#endif
-          this->generic_construct(*lhs, lib::move(tmp));
-        }
-      }
-
-      private:
-#ifndef TF_GENERIC_LAMBDAS
-      struct swapper {
-        template <typename ThisAlt, typename ThatAlt>
-        inline void operator()(ThisAlt &this_alt, ThatAlt &that_alt) const {
-          using std::swap;
-          swap(this_alt.value, that_alt.value);
-        }
-      };
-#endif
-
-      inline constexpr bool move_nothrow() const {
-        return this->valueless_by_exception() ||
-               lib::array<bool, sizeof...(Ts)>{
-                   {std::is_nothrow_move_constructible<Ts>::value...}
-               }[this->index()];
-      }
-    };
-
-#undef TF_INHERITING_CTOR
-
-    template <typename From, typename To>
-    struct is_non_narrowing_convertible {
-      template <typename T>
-      static std::true_type test(T(&&)[1]);
-
-      template <typename T>
-      static auto impl(int) -> decltype(test<T>({std::declval<From>()}));
-
-      template <typename>
-      static auto impl(...) -> std::false_type;
-
-      static constexpr bool value = decltype(impl<To>(0))::value;
-    };
-
-    template <typename Arg,
-              std::size_t I,
-              typename T,
-              bool = std::is_arithmetic<T>::value,
-              typename = void>
-    struct overload_leaf {};
-
-    template <typename Arg, std::size_t I, typename T>
-    struct overload_leaf<Arg, I, T, false> {
-      using impl = lib::size_constant<I> (*)(T);
-      operator impl() const { return nullptr; };
-    };
-
-    template <typename Arg, std::size_t I, typename T>
-    struct overload_leaf<
-        Arg,
-        I,
-        T,
-        true
-#if defined(__clang__) || !defined(__GNUC__) || __GNUC__ >= 5
-        ,
-        lib::enable_if_t<
-            std::is_same<lib::remove_cvref_t<T>, bool>::value
-                ? std::is_same<lib::remove_cvref_t<Arg>, bool>::value
-                : is_non_narrowing_convertible<Arg, T>::value>
-#endif
-        > {
-      using impl = lib::size_constant<I> (*)(T);
-      operator impl() const { return nullptr; };
-    };
-
-    template <typename Arg, typename... Ts>
-    struct overload_impl {
-      private:
-      template <typename>
-      struct impl;
-
-      template <std::size_t... Is>
-      struct impl<lib::index_sequence<Is...>> : overload_leaf<Arg, Is, Ts>... {};
-
-      public:
-      using type = impl<lib::index_sequence_for<Ts...>>;
-    };
-
-    template <typename Arg, typename... Ts>
-    using overload = typename overload_impl<Arg, Ts...>::type;
-
-    template <typename Arg, typename... Ts>
-    using best_match = lib::invoke_result_t<overload<Arg, Ts...>, Arg>;
-
-    template <typename T>
-    struct is_in_place_index : std::false_type {};
-
-    template <std::size_t I>
-    struct is_in_place_index<in_place_index_t<I>> : std::true_type {};
-
-    template <typename T>
-    struct is_in_place_type : std::false_type {};
-
-    template <typename T>
-    struct is_in_place_type<in_place_type_t<T>> : std::true_type {};
-
-  }  // detail
-
-  template <typename... Ts>
-  class variant {
-    static_assert(0 < sizeof...(Ts),
-                  "variant must consist of at least one alternative.");
-
-    static_assert(lib::all<!std::is_array<Ts>::value...>::value,
-                  "variant can not have an array type as an alternative.");
-
-    static_assert(lib::all<!std::is_reference<Ts>::value...>::value,
-                  "variant can not have a reference type as an alternative.");
-
-    static_assert(lib::all<!std::is_void<Ts>::value...>::value,
-                  "variant can not have a void type as an alternative.");
-
-    public:
-    template <
-        typename Front = lib::type_pack_element_t<0, Ts...>,
-        lib::enable_if_t<std::is_default_constructible<Front>::value, int> = 0>
-    inline constexpr variant() noexcept(
-        std::is_nothrow_default_constructible<Front>::value)
-        : impl_(in_place_index_t<0>{}) {}
-
-    variant(const variant &) = default;
-    variant(variant &&) = default;
-
-    template <
-        typename Arg,
-        typename Decayed = lib::decay_t<Arg>,
-        lib::enable_if_t<!std::is_same<Decayed, variant>::value, int> = 0,
-        lib::enable_if_t<!detail::is_in_place_index<Decayed>::value, int> = 0,
-        lib::enable_if_t<!detail::is_in_place_type<Decayed>::value, int> = 0,
-        std::size_t I = detail::best_match<Arg, Ts...>::value,
-        typename T = lib::type_pack_element_t<I, Ts...>,
-        lib::enable_if_t<std::is_constructible<T, Arg>::value, int> = 0>
-    inline constexpr variant(Arg &&arg) noexcept(
-        std::is_nothrow_constructible<T, Arg>::value)
-        : impl_(in_place_index_t<I>{}, lib::forward<Arg>(arg)) {}
-
-    template <
-        std::size_t I,
-        typename... Args,
-        typename T = lib::type_pack_element_t<I, Ts...>,
-        lib::enable_if_t<std::is_constructible<T, Args...>::value, int> = 0>
-    inline explicit constexpr variant(
-        in_place_index_t<I>,
-        Args &&... args) noexcept(std::is_nothrow_constructible<T,
-                                                                Args...>::value)
-        : impl_(in_place_index_t<I>{}, lib::forward<Args>(args)...) {}
-
-    template <
-        std::size_t I,
-        typename Up,
-        typename... Args,
-        typename T = lib::type_pack_element_t<I, Ts...>,
-        lib::enable_if_t<std::is_constructible<T,
-                                               std::initializer_list<Up> &,
-                                               Args...>::value,
-                         int> = 0>
-    inline explicit constexpr variant(
-        in_place_index_t<I>,
-        std::initializer_list<Up> il,
-        Args &&... args) noexcept(std::
-                                      is_nothrow_constructible<
-                                          T,
-                                          std::initializer_list<Up> &,
-                                          Args...>::value)
-        : impl_(in_place_index_t<I>{}, il, lib::forward<Args>(args)...) {}
-
-    template <
-        typename T,
-        typename... Args,
-        std::size_t I = detail::find_index_sfinae<T, Ts...>::value,
-        lib::enable_if_t<std::is_constructible<T, Args...>::value, int> = 0>
-    inline explicit constexpr variant(
-        in_place_type_t<T>,
-        Args &&... args) noexcept(std::is_nothrow_constructible<T,
-                                                                Args...>::value)
-        : impl_(in_place_index_t<I>{}, lib::forward<Args>(args)...) {}
-
-    template <
-        typename T,
-        typename Up,
-        typename... Args,
-        std::size_t I = detail::find_index_sfinae<T, Ts...>::value,
-        lib::enable_if_t<std::is_constructible<T,
-                                               std::initializer_list<Up> &,
-                                               Args...>::value,
-                         int> = 0>
-    inline explicit constexpr variant(
-        in_place_type_t<T>,
-        std::initializer_list<Up> il,
-        Args &&... args) noexcept(std::
-                                      is_nothrow_constructible<
-                                          T,
-                                          std::initializer_list<Up> &,
-                                          Args...>::value)
-        : impl_(in_place_index_t<I>{}, il, lib::forward<Args>(args)...) {}
-
-    ~variant() = default;
-
-    variant &operator=(const variant &) = default;
-    variant &operator=(variant &&) = default;
-
-    template <typename Arg,
-              lib::enable_if_t<!std::is_same<lib::decay_t<Arg>, variant>::value,
-                               int> = 0,
-              std::size_t I = detail::best_match<Arg, Ts...>::value,
-              typename T = lib::type_pack_element_t<I, Ts...>,
-              lib::enable_if_t<(std::is_assignable<T &, Arg>::value &&
-                                std::is_constructible<T, Arg>::value),
-                               int> = 0>
-    inline variant &operator=(Arg &&arg) noexcept(
-        (std::is_nothrow_assignable<T &, Arg>::value &&
-         std::is_nothrow_constructible<T, Arg>::value)) {
-      impl_.template assign<I>(lib::forward<Arg>(arg));
-      return *this;
-    }
-
-    template <
-        std::size_t I,
-        typename... Args,
-        typename T = lib::type_pack_element_t<I, Ts...>,
-        lib::enable_if_t<std::is_constructible<T, Args...>::value, int> = 0>
-    inline T &emplace(Args &&... args) {
-      return impl_.template emplace<I>(lib::forward<Args>(args)...);
-    }
-
-    template <
-        std::size_t I,
-        typename Up,
-        typename... Args,
-        typename T = lib::type_pack_element_t<I, Ts...>,
-        lib::enable_if_t<std::is_constructible<T,
-                                               std::initializer_list<Up> &,
-                                               Args...>::value,
-                         int> = 0>
-    inline T &emplace(std::initializer_list<Up> il, Args &&... args) {
-      return impl_.template emplace<I>(il, lib::forward<Args>(args)...);
-    }
-
-    template <
-        typename T,
-        typename... Args,
-        std::size_t I = detail::find_index_sfinae<T, Ts...>::value,
-        lib::enable_if_t<std::is_constructible<T, Args...>::value, int> = 0>
-    inline T &emplace(Args &&... args) {
-      return impl_.template emplace<I>(lib::forward<Args>(args)...);
-    }
-
-    template <
-        typename T,
-        typename Up,
-        typename... Args,
-        std::size_t I = detail::find_index_sfinae<T, Ts...>::value,
-        lib::enable_if_t<std::is_constructible<T,
-                                               std::initializer_list<Up> &,
-                                               Args...>::value,
-                         int> = 0>
-    inline T &emplace(std::initializer_list<Up> il, Args &&... args) {
-      return impl_.template emplace<I>(il, lib::forward<Args>(args)...);
-    }
-
-    inline constexpr bool valueless_by_exception() const noexcept {
-      return impl_.valueless_by_exception();
-    }
-
-    inline constexpr std::size_t index() const noexcept {
-      return impl_.index();
-    }
-
-    template <bool Dummy = true,
-              lib::enable_if_t<
-                  lib::all<Dummy,
-                           (lib::dependent_type<std::is_move_constructible<Ts>,
-                                                Dummy>::value &&
-                            lib::dependent_type<lib::is_swappable<Ts>,
-                                                Dummy>::value)...>::value,
-                  int> = 0>
-    inline void swap(variant &that) noexcept(
-        lib::all<(std::is_nothrow_move_constructible<Ts>::value &&
-                  lib::is_nothrow_swappable<Ts>::value)...>::value) {
-      impl_.swap(that.impl_);
-    }
-
-    private:
-    detail::impl<Ts...> impl_;
-
-    friend struct detail::access::variant;
-    friend struct detail::visitation::variant;
-  };
-
-  template <std::size_t I, typename... Ts>
-  inline constexpr bool holds_alternative(const variant<Ts...> &v) noexcept {
-    return v.index() == I;
-  }
-
-  template <typename T, typename... Ts>
-  inline constexpr bool holds_alternative(const variant<Ts...> &v) noexcept {
-    return holds_alternative<detail::find_index_checked<T, Ts...>::value>(v);
-  }
-
-  namespace detail {
-    template <std::size_t I, typename V>
-    struct generic_get_impl {
-      constexpr generic_get_impl(int) noexcept {}
-
-      constexpr AUTO_REFREF operator()(V &&v) const
-        AUTO_REFREF_RETURN(
-            access::variant::get_alt<I>(lib::forward<V>(v)).value)
-    };
-
-    template <std::size_t I, typename V>
-    inline constexpr AUTO_REFREF generic_get(V &&v)
-      AUTO_REFREF_RETURN(generic_get_impl<I, V>(
-          holds_alternative<I>(v) ? 0 : (throw_bad_variant_access(), 0))(
-          lib::forward<V>(v)))
-  }  // namespace detail
-
-  template <std::size_t I, typename... Ts>
-  inline constexpr variant_alternative_t<I, variant<Ts...>> &get(
-      variant<Ts...> &v) {
-    return detail::generic_get<I>(v);
-  }
-
-  template <std::size_t I, typename... Ts>
-  inline constexpr variant_alternative_t<I, variant<Ts...>> &&get(
-      variant<Ts...> &&v) {
-    return detail::generic_get<I>(lib::move(v));
-  }
-
-  template <std::size_t I, typename... Ts>
-  inline constexpr const variant_alternative_t<I, variant<Ts...>> &get(
-      const variant<Ts...> &v) {
-    return detail::generic_get<I>(v);
-  }
-
-  template <std::size_t I, typename... Ts>
-  inline constexpr const variant_alternative_t<I, variant<Ts...>> &&get(
-      const variant<Ts...> &&v) {
-    return detail::generic_get<I>(lib::move(v));
-  }
-
-  template <typename T, typename... Ts>
-  inline constexpr T &get(variant<Ts...> &v) {
-    return get<detail::find_index_checked<T, Ts...>::value>(v);
-  }
-
-  template <typename T, typename... Ts>
-  inline constexpr T &&get(variant<Ts...> &&v) {
-    return get<detail::find_index_checked<T, Ts...>::value>(lib::move(v));
-  }
-
-  template <typename T, typename... Ts>
-  inline constexpr const T &get(const variant<Ts...> &v) {
-    return get<detail::find_index_checked<T, Ts...>::value>(v);
-  }
-
-  template <typename T, typename... Ts>
-  inline constexpr const T &&get(const variant<Ts...> &&v) {
-    return get<detail::find_index_checked<T, Ts...>::value>(lib::move(v));
-  }
-
-  namespace detail {
-
-    template <std::size_t I, typename V>
-    inline constexpr /* auto * */ AUTO generic_get_if(V *v) noexcept
-      AUTO_RETURN(v && holds_alternative<I>(*v)
-                      ? lib::addressof(access::variant::get_alt<I>(*v).value)
-                      : nullptr)
-
-  }  // namespace detail
-
-  template <std::size_t I, typename... Ts>
-  inline constexpr lib::add_pointer_t<variant_alternative_t<I, variant<Ts...>>>
-  get_if(variant<Ts...> *v) noexcept {
-    return detail::generic_get_if<I>(v);
-  }
-
-  template <std::size_t I, typename... Ts>
-  inline constexpr lib::add_pointer_t<
-      const variant_alternative_t<I, variant<Ts...>>>
-  get_if(const variant<Ts...> *v) noexcept {
-    return detail::generic_get_if<I>(v);
-  }
-
-  template <typename T, typename... Ts>
-  inline constexpr lib::add_pointer_t<T>
-  get_if(variant<Ts...> *v) noexcept {
-    return get_if<detail::find_index_checked<T, Ts...>::value>(v);
-  }
-
-  template <typename T, typename... Ts>
-  inline constexpr lib::add_pointer_t<const T>
-  get_if(const variant<Ts...> *v) noexcept {
-    return get_if<detail::find_index_checked<T, Ts...>::value>(v);
-  }
-
-  namespace detail {
-    template <typename RelOp>
-    struct convert_to_bool {
-      template <typename Lhs, typename Rhs>
-      inline constexpr bool operator()(Lhs &&lhs, Rhs &&rhs) const {
-        static_assert(std::is_convertible<lib::invoke_result_t<RelOp, Lhs, Rhs>,
-                                          bool>::value,
-                      "relational operators must return a type"
-                      " implicitly convertible to bool");
-        return lib::invoke(
-            RelOp{}, lib::forward<Lhs>(lhs), lib::forward<Rhs>(rhs));
-      }
-    };
-  }  // namespace detail
-
-  template <typename... Ts>
-  inline constexpr bool operator==(const variant<Ts...> &lhs,
-                                   const variant<Ts...> &rhs) {
-    using detail::visitation::variant;
-    using equal_to = detail::convert_to_bool<lib::equal_to>;
-#ifdef TF_CPP14_CONSTEXPR
-    if (lhs.index() != rhs.index()) return false;
-    if (lhs.valueless_by_exception()) return true;
-    return variant::visit_value_at(lhs.index(), equal_to{}, lhs, rhs);
-#else
-    return lhs.index() == rhs.index() &&
-           (lhs.valueless_by_exception() ||
-            variant::visit_value_at(lhs.index(), equal_to{}, lhs, rhs));
-#endif
-  }
-
-  template <typename... Ts>
-  inline constexpr bool operator!=(const variant<Ts...> &lhs,
-                                   const variant<Ts...> &rhs) {
-    using detail::visitation::variant;
-    using not_equal_to = detail::convert_to_bool<lib::not_equal_to>;
-#ifdef TF_CPP14_CONSTEXPR
-    if (lhs.index() != rhs.index()) return true;
-    if (lhs.valueless_by_exception()) return false;
-    return variant::visit_value_at(lhs.index(), not_equal_to{}, lhs, rhs);
-#else
-    return lhs.index() != rhs.index() ||
-           (!lhs.valueless_by_exception() &&
-            variant::visit_value_at(lhs.index(), not_equal_to{}, lhs, rhs));
-#endif
-  }
-
-  template <typename... Ts>
-  inline constexpr bool operator<(const variant<Ts...> &lhs,
-                                  const variant<Ts...> &rhs) {
-    using detail::visitation::variant;
-    using less = detail::convert_to_bool<lib::less>;
-#ifdef TF_CPP14_CONSTEXPR
-    if (rhs.valueless_by_exception()) return false;
-    if (lhs.valueless_by_exception()) return true;
-    if (lhs.index() < rhs.index()) return true;
-    if (lhs.index() > rhs.index()) return false;
-    return variant::visit_value_at(lhs.index(), less{}, lhs, rhs);
-#else
-    return !rhs.valueless_by_exception() &&
-           (lhs.valueless_by_exception() || lhs.index() < rhs.index() ||
-            (lhs.index() == rhs.index() &&
-             variant::visit_value_at(lhs.index(), less{}, lhs, rhs)));
-#endif
-  }
-
-  template <typename... Ts>
-  inline constexpr bool operator>(const variant<Ts...> &lhs,
-                                  const variant<Ts...> &rhs) {
-    using detail::visitation::variant;
-    using greater = detail::convert_to_bool<lib::greater>;
-#ifdef TF_CPP14_CONSTEXPR
-    if (lhs.valueless_by_exception()) return false;
-    if (rhs.valueless_by_exception()) return true;
-    if (lhs.index() > rhs.index()) return true;
-    if (lhs.index() < rhs.index()) return false;
-    return variant::visit_value_at(lhs.index(), greater{}, lhs, rhs);
-#else
-    return !lhs.valueless_by_exception() &&
-           (rhs.valueless_by_exception() || lhs.index() > rhs.index() ||
-            (lhs.index() == rhs.index() &&
-             variant::visit_value_at(lhs.index(), greater{}, lhs, rhs)));
-#endif
-  }
-
-  template <typename... Ts>
-  inline constexpr bool operator<=(const variant<Ts...> &lhs,
-                                   const variant<Ts...> &rhs) {
-    using detail::visitation::variant;
-    using less_equal = detail::convert_to_bool<lib::less_equal>;
-#ifdef TF_CPP14_CONSTEXPR
-    if (lhs.valueless_by_exception()) return true;
-    if (rhs.valueless_by_exception()) return false;
-    if (lhs.index() < rhs.index()) return true;
-    if (lhs.index() > rhs.index()) return false;
-    return variant::visit_value_at(lhs.index(), less_equal{}, lhs, rhs);
-#else
-    return lhs.valueless_by_exception() ||
-           (!rhs.valueless_by_exception() &&
-            (lhs.index() < rhs.index() ||
-             (lhs.index() == rhs.index() &&
-              variant::visit_value_at(lhs.index(), less_equal{}, lhs, rhs))));
-#endif
-  }
-
-  template <typename... Ts>
-  inline constexpr bool operator>=(const variant<Ts...> &lhs,
-                                   const variant<Ts...> &rhs) {
-    using detail::visitation::variant;
-    using greater_equal = detail::convert_to_bool<lib::greater_equal>;
-#ifdef TF_CPP14_CONSTEXPR
-    if (rhs.valueless_by_exception()) return true;
-    if (lhs.valueless_by_exception()) return false;
-    if (lhs.index() > rhs.index()) return true;
-    if (lhs.index() < rhs.index()) return false;
-    return variant::visit_value_at(lhs.index(), greater_equal{}, lhs, rhs);
-#else
-    return rhs.valueless_by_exception() ||
-           (!lhs.valueless_by_exception() &&
-            (lhs.index() > rhs.index() ||
-             (lhs.index() == rhs.index() &&
-              variant::visit_value_at(
-                  lhs.index(), greater_equal{}, lhs, rhs))));
-#endif
-  }
-
-  struct monostate {};
-
-  inline constexpr bool operator<(monostate, monostate) noexcept {
-    return false;
-  }
-
-  inline constexpr bool operator>(monostate, monostate) noexcept {
-    return false;
-  }
-
-  inline constexpr bool operator<=(monostate, monostate) noexcept {
-    return true;
-  }
-
-  inline constexpr bool operator>=(monostate, monostate) noexcept {
-    return true;
-  }
-
-  inline constexpr bool operator==(monostate, monostate) noexcept {
-    return true;
-  }
-
-  inline constexpr bool operator!=(monostate, monostate) noexcept {
-    return false;
-  }
-
-#ifdef TF_CPP14_CONSTEXPR
-  namespace detail {
-
-    inline constexpr bool any(std::initializer_list<bool> bs) {
-      for (bool b : bs) {
-        if (b) {
-          return true;
-        }
-      }
-      return false;
-    }
-
-  }  // namespace detail
-
-  template <typename Visitor, typename... Vs>
-  inline constexpr decltype(auto) visit(Visitor &&visitor, Vs &&... vs) {
-    return (!detail::any({vs.valueless_by_exception()...})
-                ? (void)0
-                : throw_bad_variant_access()),
-           detail::visitation::variant::visit_value(
-               lib::forward<Visitor>(visitor), lib::forward<Vs>(vs)...);
-  }
-#else
-  namespace detail {
-
-    template <std::size_t N>
-    inline constexpr bool all_impl(const lib::array<bool, N> &bs,
-                                   std::size_t idx) {
-      return idx >= N || (bs[idx] && all_impl(bs, idx + 1));
-    }
-
-    template <std::size_t N>
-    inline constexpr bool all(const lib::array<bool, N> &bs) {
-      return all_impl(bs, 0);
-    }
-
-  }  // namespace detail
-
-  template <typename Visitor, typename... Vs>
-  inline constexpr DECLTYPE_AUTO visit(Visitor &&visitor, Vs &&... vs)
-    DECLTYPE_AUTO_RETURN(
-        (detail::all(
-             lib::array<bool, sizeof...(Vs)>{{!vs.valueless_by_exception()...}})
-             ? (void)0
-             : throw_bad_variant_access()),
-        detail::visitation::variant::visit_value(lib::forward<Visitor>(visitor),
-                                                 lib::forward<Vs>(vs)...))
-#endif
-
-  template <typename... Ts>
-  inline auto swap(variant<Ts...> &lhs,
-                   variant<Ts...> &rhs) noexcept(noexcept(lhs.swap(rhs)))
-      -> decltype(lhs.swap(rhs)) {
-    lhs.swap(rhs);
-  }
-
-  namespace detail {
-
-    template <typename T, typename...>
-    using enabled_type = T;
-
-    namespace hash {
-
-      template <typename H, typename K>
-      constexpr bool meets_requirements() noexcept {
-        return std::is_copy_constructible<H>::value &&
-               std::is_move_constructible<H>::value &&
-               lib::is_invocable_r<std::size_t, H, const K &>::value;
-      }
-
-      template <typename K>
-      constexpr bool is_enabled() noexcept {
-        using H = std::hash<K>;
-        return meets_requirements<H, K>() &&
-               std::is_default_constructible<H>::value &&
-               std::is_copy_assignable<H>::value &&
-               std::is_move_assignable<H>::value;
-      }
-
-    }  // namespace hash
-
-  }  // namespace detail
-
-#undef AUTO
-#undef AUTO_RETURN
-
-#undef AUTO_REFREF
-#undef AUTO_REFREF_RETURN
-
-#undef DECLTYPE_AUTO
-#undef DECLTYPE_AUTO_RETURN
-
-}}  // namespace tf::nstd
-
-namespace std {
-
-  template <typename... Ts>
-  struct hash<tf::nstd::detail::enabled_type<
-      tf::nstd::variant<Ts...>,
-      tf::nstd::lib::enable_if_t<tf::nstd::lib::all<tf::nstd::detail::hash::is_enabled<
-          tf::nstd::lib::remove_const_t<Ts>>()...>::value>>> {
-    using argument_type = tf::nstd::variant<Ts...>;
-    using result_type = std::size_t;
-
-    inline result_type operator()(const argument_type &v) const {
-      using tf::nstd::detail::visitation::variant;
-      std::size_t result =
-          v.valueless_by_exception()
-              ? 299792458  // Random value chosen by the universe upon creation
-              : variant::visit_alt(
-#ifdef TF_GENERIC_LAMBDAS
-                    [](const auto &alt) {
-                      using alt_type = tf::nstd::lib::decay_t<decltype(alt)>;
-                      using value_type = tf::nstd::lib::remove_const_t<
-                          typename alt_type::value_type>;
-                      return hash<value_type>{}(alt.value);
-                    }
-#else
-                    hasher{}
-#endif
-                    ,
-                    v);
-      return hash_combine(result, hash<std::size_t>{}(v.index()));
-    }
-
-    private:
-#ifndef TF_GENERIC_LAMBDAS
-    struct hasher {
-      template <typename Alt>
-      inline std::size_t operator()(const Alt &alt) const {
-        using alt_type = tf::nstd::lib::decay_t<Alt>;
-        using value_type =
-            tf::nstd::lib::remove_const_t<typename alt_type::value_type>;
-        return hash<value_type>{}(alt.value);
-      }
-    };
-#endif
-
-    static std::size_t hash_combine(std::size_t lhs, std::size_t rhs) {
-      return lhs ^= rhs + 0x9e3779b9 + (lhs << 6) + (lhs >> 2);
-    }
-  };
-
-  template <>
-  struct hash<tf::nstd::monostate> {
-    using argument_type = tf::nstd::monostate;
-    using result_type = std::size_t;
-
-    inline result_type operator()(const argument_type &) const noexcept {
-      return 66740831;  // return a fundamentally attractive random value.
-    }
-  };
-
-}  // namespace std
-
-
-
diff --git a/bundled/taskflow-2.5.0/include/taskflow/taskflow.hpp b/bundled/taskflow-2.5.0/include/taskflow/taskflow.hpp
deleted file mode 100644 (file)
index 192f8a8..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-#pragma once
-
-#include "core/executor.hpp"
-
-namespace tf {
-
-
-}  // end of namespace tf. ---------------------------------------------------
-
-
-
-
-
diff --git a/bundled/taskflow-2.5.0/include/taskflow/utility/object_pool.hpp b/bundled/taskflow-2.5.0/include/taskflow/utility/object_pool.hpp
deleted file mode 100644 (file)
index 63ca9f0..0000000
+++ /dev/null
@@ -1,776 +0,0 @@
-// 2020/03/13 - modified by Tsung-Wei Huang
-//  - fixed bug in aligning memory
-//
-// 2020/02/02 - modified by Tsung-Wei Huang
-//  - new implementation motivated by Hoard
-// 
-// 2019/07/10 - modified by Tsung-Wei Huang
-//  - replace raw pointer with smart pointer
-//
-// 2019/06/13 - created by Tsung-Wei Huang
-//  - implemented an object pool class
-
-#pragma once
-
-#include <thread>
-#include <atomic>
-#include <mutex>
-#include <vector>
-#include <cassert>
-#include <cstddef>
-
-namespace tf {
-
-#define TF_ENABLE_POOLABLE_ON_THIS                          \
-  template <typename T, size_t S> friend class ObjectPool;  \
-  void* _object_pool_block
-
-// Class: ObjectPool
-//
-// The class implements an efficient thread-safe object pool motivated
-// by the Hoard memory allocator algorithm. 
-// Different from the normal memory allocator, object pool allocates
-// only one object at a time.
-//
-// Internall, we use the following variables to maintain blocks and heaps:
-// X: size in byte of a item slot
-// M: number of items per block
-// F: emptiness threshold
-// B: number of bins per local heap (bin[B-1] is the full list)
-// W: number of items per bin
-// K: shrinkness constant
-//
-// Example scenario 1:
-// M = 30
-// F = 4
-// W = (30+4-1)/4 = 8
-// 
-// b0: 0, 1, 2, 3, 4, 5, 6, 7
-// b1: 8, 9, 10, 11, 12, 13, 14, 15
-// b2: 16, 17, 18, 19, 20, 21, 22, 23
-// b3: 24, 25, 26, 27, 28, 29
-// b4: 30 (anything equal to M)
-// 
-// Example scenario 2:
-// M = 32
-// F = 4
-// W = (32+4-1)/4 = 8
-// b0: 0, 1, 2, 3, 4, 5, 6, 7
-// b1: 8, 9, 10, 11, 12, 13, 14, 15
-// b2: 16, 17, 18, 19, 20, 21, 22, 23
-// b3: 24, 25, 26, 27, 28, 29, 30, 31
-// b4: 32 (anything equal to M)
-//
-template <typename T, size_t S = 65536>
-class ObjectPool { 
-  
-  // the data column must be sufficient to hold the pointer in freelist  
-  constexpr static size_t X = std::max(sizeof(T*), sizeof(T));
-  //constexpr static size_t X = sizeof(long double) + std::max(sizeof(T*), sizeof(T));
-  //constexpr static size_t M = (S - offsetof(Block, data)) / X;
-  constexpr static size_t M = S / X;
-  constexpr static size_t F = 4;   
-  constexpr static size_t B = F + 1;
-  constexpr static size_t W = (M + F - 1) / F;
-  constexpr static size_t K = 4;
-
-  static_assert(
-    S && (!(S & (S-1))), "block size S must be a power of two"
-  );
-
-  static_assert(
-    M >= 128, "block size S must be larger enough to pool at least 128 objects"
-  );
-  
-  struct Blocklist {
-    Blocklist* prev;
-    Blocklist* next;
-  };
-
-  class GlobalHeap {
-    friend class ObjectPool;
-    std::mutex mutex;
-    Blocklist list;
-  };
-
-  class LocalHeap {
-    friend class ObjectPool;
-    std::mutex mutex;
-    Blocklist lists[B];
-    size_t u {0};
-    size_t a {0};
-  };
-
-  struct Block {
-    LocalHeap* heap;
-    Blocklist list_node;
-    size_t i;
-    size_t u;
-    T* top;
-    // long double padding;
-    char data[S];
-  };
-
-  public:
-    
-    /**
-    @brief constructs an object pool from a number of anticipated threads
-    */
-    explicit ObjectPool(unsigned = std::thread::hardware_concurrency());
-
-    /**
-    @brief destructs the object pool
-    */
-    ~ObjectPool();
-    
-    /**
-    @brief acquires a pointer to a object constructed from a given argument list
-    */
-    template <typename... ArgsT>
-    T* animate(ArgsT&&... args);
-    
-    /**
-    @brief recycles a object pointed by @c ptr and destroys it
-    */
-    void recycle(T* ptr);
-    
-    size_t num_bins_per_local_heap() const;
-    size_t num_objects_per_bin() const;
-    size_t num_objects_per_block() const;
-    size_t num_available_objects() const;
-    size_t num_allocated_objects() const;
-    size_t capacity() const;
-    size_t num_local_heaps() const;
-    size_t num_global_heaps() const;
-    size_t num_heaps() const;
-    
-    float emptiness_threshold() const;
-
-  private:
-
-    const size_t _lheap_mask;
-
-    GlobalHeap _gheap;
-
-    std::vector<LocalHeap> _lheaps;
-
-    LocalHeap& _this_heap();
-
-    constexpr unsigned _next_power_of_two(unsigned n) const;
-
-    template <class P, class Q>
-    constexpr size_t _offset_in_class(const Q P::*member) const;
-    
-    template <class P, class Q>
-    constexpr P* _parent_class_of(Q*, const Q P::*member);
-
-    template <class P, class Q>
-    constexpr P* _parent_class_of(const Q*, const Q P::*member) const;
-
-    constexpr Block* _block_of(Blocklist*);
-    constexpr Block* _block_of(const Blocklist*) const;
-
-    size_t _bin(size_t) const;
-
-    T* _allocate(Block*);
-
-    void _deallocate(Block*, T*);
-    void _blocklist_init_head(Blocklist*);
-    void _blocklist_add_impl(Blocklist*, Blocklist*, Blocklist*);
-    void _blocklist_push_front(Blocklist*, Blocklist*);
-    void _blocklist_push_back(Blocklist*, Blocklist*);
-    void _blocklist_del_impl(Blocklist*, Blocklist*);
-    void _blocklist_del(Blocklist*);
-    void _blocklist_replace(Blocklist*, Blocklist*);
-    void _blocklist_move_front(Blocklist*, Blocklist*);
-    void _blocklist_move_back(Blocklist*, Blocklist*);
-    bool _blocklist_is_first(const Blocklist*, const Blocklist*);
-    bool _blocklist_is_last(const Blocklist*, const Blocklist*);
-    bool _blocklist_is_empty(const Blocklist*);
-    bool _blocklist_is_singular(const Blocklist*);
-
-    template <typename C>
-    void _for_each_block_safe(Blocklist*, C&&);
-
-    template <typename C>
-    void _for_each_block(Blocklist*, C&&);
-
-};
-    
-// ----------------------------------------------------------------------------
-// ObjectPool definition
-// ----------------------------------------------------------------------------
-
-// Constructor
-template <typename T, size_t S>
-ObjectPool<T, S>::ObjectPool(unsigned t) :
-  //_heap_mask   {(_next_power_of_two(t) << 1) - 1u},
-  //_heap_mask   { _next_power_of_two(t<<1) - 1u },
-  //_heap_mask   {(t << 1) - 1},
-  _lheap_mask { _next_power_of_two((t+1) << 1) - 1 },
-  _lheaps     { _lheap_mask + 1 } {
-
-  _blocklist_init_head(&_gheap.list);
-
-  for(auto& h : _lheaps) {
-    for(size_t i=0; i<B; ++i) {
-      _blocklist_init_head(&h.lists[i]);
-    }
-  }
-}
-
-// Destructor
-template <typename T, size_t S>
-ObjectPool<T, S>::~ObjectPool() {
-
-  // clear local heaps
-  for(auto& h : _lheaps) {
-    for(size_t i=0; i<B; ++i) {
-      _for_each_block_safe(&h.lists[i], [] (Block* b) { 
-        std::free(b); 
-      });
-    }
-  }
-  
-  // clear global heap
-  _for_each_block_safe(&_gheap.list, [] (Block* b) { 
-    std::free(b);
-  });
-}
-    
-// Function: num_bins_per_local_heap
-template <typename T, size_t S>
-size_t ObjectPool<T, S>::num_bins_per_local_heap() const {
-  return B;
-}
-
-// Function: num_objects_per_bin
-template <typename T, size_t S>
-size_t ObjectPool<T, S>::num_objects_per_bin() const {
-  return W;
-}
-
-// Function: num_objects_per_block
-template <typename T, size_t S>
-size_t ObjectPool<T, S>::num_objects_per_block() const {
-  return M;
-}
-
-// Function: emptiness_threshold
-template <typename T, size_t S>
-float ObjectPool<T, S>::emptiness_threshold() const {
-  return 1.0f/F;
-}
-
-// Function: num_global_heaps
-template <typename T, size_t S>
-size_t ObjectPool<T, S>::num_global_heaps() const {
-  return 1;
-}
-
-// Function: num_lheaps
-template <typename T, size_t S>
-size_t ObjectPool<T, S>::num_local_heaps() const {
-  return _lheaps.size();
-}
-
-// Function: num_heaps
-template <typename T, size_t S>
-size_t ObjectPool<T, S>::num_heaps() const {
-  return _lheaps.size() + 1;
-}
-
-// Function: capacity
-template <typename T, size_t S>
-size_t ObjectPool<T, S>::capacity() const {
-  
-  size_t n = 0;
-  
-  // global heap
-  for(auto p=_gheap.list.next; p!=&_gheap.list; p=p->next) {  
-    n += M;
-  };
-
-  // local heap
-  for(auto& h : _lheaps) {
-    n += h.a;
-  }
-
-  return n;
-}
-
-// Function: num_available_objects
-template <typename T, size_t S>
-size_t ObjectPool<T, S>::num_available_objects() const {
-
-  size_t n = 0;
-  
-  // global heap
-  for(auto p=_gheap.list.next; p!=&_gheap.list; p=p->next) {  
-    n += (M - _block_of(p)->u);
-  };
-
-  // local heap
-  for(auto& h : _lheaps) {
-    n += (h.a - h.u);
-  }
-  return n;
-}
-
-// Function: num_allocated_objects
-template <typename T, size_t S>
-size_t ObjectPool<T, S>::num_allocated_objects() const {
-  
-  size_t n = 0;
-  
-  // global heap
-  for(auto p=_gheap.list.next; p!=&_gheap.list; p=p->next) {  
-    n += _block_of(p)->u;
-  };
-
-  // local heap
-  for(auto& h : _lheaps) {
-    n += h.u;
-  }
-  return n;
-}
-
-// Function: _bin
-template <typename T, size_t S>
-size_t ObjectPool<T, S>::_bin(size_t u) const {
-  return u == M ? F : u/W;
-}
-
-// Function: _offset_in_class
-template <typename T, size_t S>
-template <class P, class Q>
-constexpr size_t ObjectPool<T, S>::_offset_in_class(
-  const Q P::*member) const {
-  return (size_t) &( reinterpret_cast<P*>(0)->*member);
-}
-
-// C macro: parent_class_of(list_pointer, Block, list)
-// C++: parent_class_of(list_pointer,  &Block::list)
-template <typename T, size_t S>
-template <class P, class Q>
-constexpr P* ObjectPool<T, S>::_parent_class_of(
-  Q* ptr, const Q P::*member
-) {
-  return (P*)( (char*)ptr - _offset_in_class(member));
-}
-
-// Function: _parent_class_of
-template <typename T, size_t S>
-template <class P, class Q>
-constexpr P* ObjectPool<T, S>::_parent_class_of(
-  const Q* ptr, const Q P::*member
-) const {
-  return (P*)( (char*)ptr - _offset_in_class(member));
-}
-
-// Function: _block_of
-template <typename T, size_t S>
-constexpr typename ObjectPool<T, S>::Block* 
-ObjectPool<T, S>::_block_of(Blocklist* list) {
-  return _parent_class_of(list, &Block::list_node);
-}
-
-// Function: _block_of
-template <typename T, size_t S>
-constexpr typename ObjectPool<T, S>::Block* 
-ObjectPool<T, S>::_block_of(const Blocklist* list) const {
-  return _parent_class_of(list, &Block::list_node);
-}
-
-// Procedure: initialize a list head
-template <typename T, size_t S>
-void ObjectPool<T, S>::_blocklist_init_head(Blocklist *list) {
-  list->next = list;
-  list->prev = list;
-}
-
-// Procedure: _blocklist_add_impl
-// Insert a new entry between two known consecutive entries.
-// 
-// This is only for internal list manipulation where we know
-// the prev/next entries already!
-template <typename T, size_t S>
-void ObjectPool<T, S>::_blocklist_add_impl(
-  Blocklist *curr, Blocklist *prev, Blocklist *next
-) {
-  next->prev = curr;
-  curr->next = next;
-  curr->prev = prev;
-  prev->next = curr;
-}
-
-// list_push_front - add a new entry
-// @curr: curr entry to be added
-// @head: list head to add it after
-// 
-// Insert a new entry after the specified head.
-// This is good for implementing stacks.
-// 
-template <typename T, size_t S>
-void ObjectPool<T, S>::_blocklist_push_front(
-  Blocklist *curr, Blocklist *head
-) {
-  _blocklist_add_impl(curr, head, head->next);
-}
-
-// list_add_tail - add a new entry
-// @curr: curr entry to be added
-// @head: list head to add it before
-// 
-// Insert a new entry before the specified head.
-// This is useful for implementing queues.
-// 
-template <typename T, size_t S>
-void ObjectPool<T, S>::_blocklist_push_back(
-  Blocklist *curr, Blocklist *head
-) {
-  _blocklist_add_impl(curr, head->prev, head);
-}
-
-// Delete a list entry by making the prev/next entries
-// point to each other.
-// 
-// This is only for internal list manipulation where we know
-// the prev/next entries already!
-// 
-template <typename T, size_t S>
-void ObjectPool<T, S>::_blocklist_del_impl(
-  Blocklist * prev, Blocklist * next
-) {
-  next->prev = prev;
-  prev->next = next;
-}
-
-// _blocklist_del - deletes entry from list.
-// @entry: the element to delete from the list.
-// Note: list_empty() on entry does not return true after this, the entry is
-// in an undefined state.
-template <typename T, size_t S>
-void ObjectPool<T, S>::_blocklist_del(Blocklist *entry) {
-  _blocklist_del_impl(entry->prev, entry->next);
-  entry->next = nullptr;
-  entry->prev = nullptr;
-}
-
-// list_replace - replace old entry by new one
-// @old : the element to be replaced
-// @curr : the new element to insert
-// 
-// If @old was empty, it will be overwritten.
-template <typename T, size_t S>
-void ObjectPool<T, S>::_blocklist_replace(
-  Blocklist *old, Blocklist *curr
-) {
-  curr->next = old->next;
-  curr->next->prev = curr;
-  curr->prev = old->prev;
-  curr->prev->next = curr;
-}
-
-// list_move - delete from one list and add as another's head
-// @list: the entry to move
-// @head: the head that will precede our entry
-template <typename T, size_t S>
-void ObjectPool<T, S>::_blocklist_move_front(
-  Blocklist *list, Blocklist *head
-) {
-  _blocklist_del_impl(list->prev, list->next);
-  _blocklist_push_front(list, head);
-}
-
-// list_move_tail - delete from one list and add as another's tail
-// @list: the entry to move
-// @head: the head that will follow our entry
-template <typename T, size_t S>
-void ObjectPool<T, S>::_blocklist_move_back(
-  Blocklist *list, Blocklist *head
-) {
-  _blocklist_del_impl(list->prev, list->next);
-  _blocklist_push_back(list, head);
-}
-
-// list_is_first - tests whether @list is the last entry in list @head
-// @list: the entry to test
-// @head: the head of the list
-template <typename T, size_t S>
-bool ObjectPool<T, S>::_blocklist_is_first(
-  const Blocklist *list, const Blocklist *head
-) {
-  return list->prev == head;
-}
-
-// list_is_last - tests whether @list is the last entry in list @head
-// @list: the entry to test
-// @head: the head of the list
-template <typename T, size_t S>
-bool ObjectPool<T, S>::_blocklist_is_last(
-  const Blocklist *list, const Blocklist *head
-) {
-  return list->next == head;
-}
-
-// list_empty - tests whether a list is empty
-// @head: the list to test.
-template <typename T, size_t S>
-bool ObjectPool<T, S>::_blocklist_is_empty(const Blocklist *head) {
-  return head->next == head;
-}
-
-// list_is_singular - tests whether a list has just one entry.
-// @head: the list to test.
-template <typename T, size_t S>
-bool ObjectPool<T, S>::_blocklist_is_singular(
-  const Blocklist *head
-) {
-  return !_blocklist_is_empty(head) && (head->next == head->prev);
-}
-
-// Procedure: _for_each_block
-template <typename T, size_t S>
-template <typename C>
-void ObjectPool<T, S>::_for_each_block(Blocklist* head, C&& c) {
-  Blocklist* p;
-  for(p=head->next; p!=head; p=p->next) {
-    c(_block_of(p));
-  }
-}
-      
-// Procedure: _for_each_block_safe
-// Iterate each item of a list - safe to free
-template <typename T, size_t S>
-template <typename C>
-void ObjectPool<T, S>::_for_each_block_safe(Blocklist* head, C&& c) {
-  Blocklist* p;
-  Blocklist* t;
-  for(p=head->next, t=p->next; p!=head; p=t, t=p->next) {
-    c(_block_of(p));
-  }
-}
-
-// Function: _allocate
-// allocate a spot from the block
-template <typename T, size_t S>
-T* ObjectPool<T, S>::_allocate(Block* s) {
-  if(s->top == nullptr) {
-    return reinterpret_cast<T*>(s->data + s->i++ * X);
-  }
-  else {
-    T* retval = s->top;
-    s->top = *(reinterpret_cast<T**>(s->top));
-    return retval;
-  }
-}
-
-// Procedure: _deallocate
-template <typename T, size_t S>
-void ObjectPool<T, S>::_deallocate(Block* s, T* ptr) {
-  *(reinterpret_cast<T**>(ptr)) = s->top;
-  s->top = ptr;
-}
-
-// Function: allocate
-template <typename T, size_t S>
-template <typename... ArgsT>
-T* ObjectPool<T, S>::animate(ArgsT&&... args) {
-
-  //std::cout << "construct a new item\n";
-    
-  // my logically mapped heap
-  LocalHeap& h = _this_heap(); 
-  
-  Block* s {nullptr};
-
-  h.mutex.lock();
-  
-  // scan the list of superblocks from most full to least
-  int f = static_cast<int>(F-1);
-  for(; f>=0; f--) {
-    if(!_blocklist_is_empty(&h.lists[f])) {
-      s = _block_of(h.lists[f].next);
-      break;
-    }
-  }
-  
-  // no superblock found
-  if(f == -1) {
-
-    // check heap 0 for a superblock
-    _gheap.mutex.lock();
-    if(!_blocklist_is_empty(&_gheap.list)) {
-      
-      s = _block_of(_gheap.list.next);
-      
-      //printf("get a superblock from global heap %lu\n", s->u);
-      assert(s->u < M && s->heap == nullptr);
-      f = static_cast<int>(_bin(s->u + 1));
-
-      _blocklist_move_front(&s->list_node, &h.lists[f]);
-
-      s->heap = &h;  // must be within the global heap lock
-      _gheap.mutex.unlock();
-
-      h.u = h.u + s->u;
-      h.a = h.a + M;
-    }
-    // create a new block
-    else {
-      //printf("create a new superblock\n");
-      _gheap.mutex.unlock();
-      f = 0;
-      s = static_cast<Block*>(std::malloc(sizeof(Block)));
-
-      if(s == nullptr) {
-        throw std::bad_alloc();
-      }
-
-      s->heap = &h;
-      s->i = 0;
-      s->u = 0;
-      s->top = nullptr;
-
-      _blocklist_push_front(&s->list_node, &h.lists[f]);
-
-      h.a = h.a + M;
-    }
-  }
-  
-  // the superblock must have at least one space
-  //assert(s->u < M);
-  //printf("%lu %lu %lu\n", h.u, h.a, s->u);
-  //assert(h.u < h.a);
-
-  h.u = h.u + 1;
-  s->u = s->u + 1;
-
-  // take one item from the superblock
-  T* mem = _allocate(s);
-  
-  int b = static_cast<int>(_bin(s->u));
-  
-  if(b != f) {
-    //printf("move superblock from list[%d] to list[%d]\n", f, b);
-    _blocklist_move_front(&s->list_node, &h.lists[b]);
-  }
-
-  //std::cout << "s.i " << s->i << '\n'
-  //          << "s.u " << s->u << '\n'
-  //          << "h.u " << h.u  << '\n'
-  //          << "h.a " << h.a  << '\n';
-
-  h.mutex.unlock();
-
-  //printf("allocate %p (s=%p)\n", mem, s);
-
-  new (mem) T(std::forward<ArgsT>(args)...);
-
-  mem->_object_pool_block = s;
-
-  return mem;
-}
-  
-// Function: destruct
-template <typename T, size_t S>
-void ObjectPool<T, S>::recycle(T* mem) {
-
-  //Block* s = *reinterpret_cast<Block**>(
-  //  reinterpret_cast<char*>(mem) - sizeof(Block**)
-  //);
-
-  //Block* s= *(reinterpret_cast<Block**>(mem) - O); //  (mem) - 1
-
-  Block* s = static_cast<Block*>(mem->_object_pool_block);
-
-  mem->~T();
-  
-  //printf("deallocate %p (s=%p) M=%lu W=%lu X=%lu\n", mem, s, M, W, X);
-
-  // here we need a loop because when we lock the heap,
-  // other threads may have removed the superblock to another heap
-  bool sync = false;
-
-  do {
-    auto h = s->heap;    
-    
-    // the block is in global heap
-    if(h == nullptr) {
-      std::lock_guard<std::mutex> glock(_gheap.mutex);
-      if(s->heap == h) {
-        sync = true;
-        _deallocate(s, mem);
-        s->u = s->u - 1;
-      }
-    }
-    else {
-      std::lock_guard<std::mutex> llock(h->mutex);
-      if(s->heap == h) {
-        sync = true;
-        // deallocate the item from the superblock
-        size_t f = _bin(s->u);
-        _deallocate(s, mem);
-        s->u = s->u - 1;
-        h->u = h->u - 1;
-
-        size_t b = _bin(s->u);
-
-        if(b != f) {
-          //printf("move superblock from list[%d] to list[%d]\n", f, b);
-          _blocklist_move_front(&s->list_node, &h->lists[b]);
-        }
-
-        // transfer a mostly-empty superblock to global heap
-        if((h->u + K*M < h->a) && (h->u < ((F-1) * h->a / F))) {
-          for(size_t i=0; i<F; i++) {
-            if(!_blocklist_is_empty(&h->lists[i])) {
-              Block* x = _block_of(h->lists[i].next);
-              //printf("transfer a block (x.u=%lu/x.i=%lu) to the global heap\n", x->u, x->i);
-              assert(h->u > x->u && h->a > M);
-              h->u = h->u - x->u;
-              h->a = h->a - M;
-              x->heap = nullptr;
-              std::lock_guard<std::mutex> glock(_gheap.mutex);
-              _blocklist_move_front(&x->list_node, &_gheap.list);
-              break;
-            }
-          }
-        }
-      }
-    }
-  } while(!sync);
-  
-  //std::cout << "s.i " << s->i << '\n'
-  //          << "s.u " << s->u << '\n';
-}
-    
-// Function: _this_heap
-template <typename T, size_t S>
-typename ObjectPool<T, S>::LocalHeap& 
-ObjectPool<T, S>::_this_heap() {
-  // here we don't use thread local since object pool might be
-  // created and destroyed multiple times
-  thread_local auto hv = std::hash<std::thread::id>()(std::this_thread::get_id());
-  return _lheaps[hv & _lheap_mask];
-
-  //return _lheaps[
-  //  std::hash<std::thread::id>()(std::this_thread::get_id()) & _lheap_mask
-  //];
-}
-
-// Function: _next_power_of_two
-template <typename T, size_t S>
-constexpr unsigned ObjectPool<T, S>::_next_power_of_two(unsigned n) const { 
-  n--; 
-  n |= n >> 1; 
-  n |= n >> 2; 
-  n |= n >> 4; 
-  n |= n >> 8; 
-  n |= n >> 16; 
-  n++; 
-  return n; 
-}  
-
-}  // end namespace tf --------------------------------------------------------
diff --git a/bundled/taskflow-2.5.0/include/taskflow/utility/os.hpp b/bundled/taskflow-2.5.0/include/taskflow/utility/os.hpp
deleted file mode 100644 (file)
index c211d87..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-#include <cstdlib>
-#include <cstdio>
-#include <string>
-
-namespace tf {
-
-// Function: get_env
-inline std::string get_env(const std::string& str) {
-#ifdef _MSC_VER
-  char *ptr = nullptr;
-  size_t len = 0;
-  
-  if(_dupenv_s(&ptr, &len, str.c_str()) == 0 && ptr != nullptr) {
-    std::string res(ptr, len);
-    free(ptr);
-    return res;
-  }
-  return "";
-
-#else
-  auto ptr = std::getenv(str.c_str());
-  return ptr ? ptr : "";
-#endif
-}
-
-
-}  // end of namespace tf -----------------------------------------------------
diff --git a/bundled/taskflow-2.5.0/include/taskflow/utility/passive_vector.hpp b/bundled/taskflow-2.5.0/include/taskflow/utility/passive_vector.hpp
deleted file mode 100644 (file)
index b5710c0..0000000
+++ /dev/null
@@ -1,213 +0,0 @@
-#pragma once
-
-#include <cstring>
-#include <cstddef>
-#include <memory>
-#include <type_traits>
-#include <limits>
-
-namespace tf {
-
-// Class: PassiveVector
-// A vector storing only passive data structure (PDS) or POD data type.
-template <typename T, size_t S = 4, typename A = std::allocator<T>>
-class PassiveVector {
-
-  static_assert(
-    std::is_trivial<T>::value && std::is_standard_layout<T>::value, 
-    "must be a plain old data type"
-  );
-
-  public:
-
-    typedef T                                     value_type;
-    typedef T &                                   reference;
-    typedef const T &                             const_reference;
-    typedef T *                                   pointer;
-    typedef const T *                             const_pointer;
-    typedef T *                                   iterator;
-    typedef const T *                             const_iterator;
-    typedef std::reverse_iterator<iterator>       reverse_iterator;
-    typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
-    typedef ptrdiff_t                             difference_type;
-    typedef size_t                                size_type;
-    
-    PassiveVector() noexcept :  
-      _data {reinterpret_cast<pointer>(_stack)},
-      _num  {0},
-      _cap  {S} {
-    }
-
-    explicit PassiveVector(size_type n) : _num {n} {
-      
-      // need to place on heap
-      if(n > S) {
-        _cap  = n << 2;
-        _data = _allocator.allocate(_cap);
-      }
-      // stack
-      else {
-        _cap = S;
-        _data = reinterpret_cast<pointer>(_stack);
-      }
-
-    }
-
-    PassiveVector(const PassiveVector& rhs) : _num {rhs._num} {
-
-      // heap
-      if(rhs._num > S) {
-        _cap = rhs._cap;
-        _data = _allocator.allocate(rhs._cap);
-      }
-      else {
-        _cap = S;
-        _data = reinterpret_cast<pointer>(_stack);
-      }
-
-      std::memcpy(_data, rhs._data, _num * sizeof(T));
-    }
-
-    PassiveVector(PassiveVector&& rhs) : _num {rhs._num} {
-
-      // rhs is in the stack
-      if(rhs.in_stack()) {
-        _cap  = S;
-        _data = reinterpret_cast<pointer>(_stack);
-        std::memcpy(_stack, rhs._stack, rhs._num*sizeof(T));
-      }
-      // rhs is in the heap
-      else {
-        _cap = rhs._cap;
-        _data = rhs._data;
-        rhs._data = reinterpret_cast<pointer>(rhs._stack);
-        rhs._cap  = S;
-      }
-
-      rhs._num = 0;
-    }
-
-    ~PassiveVector() {
-      if(!in_stack()) {
-        _allocator.deallocate(_data, _cap);
-      }
-    }
-
-    iterator begin() noexcept                         { return _data;        }
-    const_iterator begin() const noexcept             { return _data;        }
-    const_iterator cbegin() const noexcept            { return _data;        }
-    iterator end() noexcept                           { return _data + _num; }
-    const_iterator end() const noexcept               { return _data + _num; }
-    const_iterator cend() const noexcept              { return _data + _num; }
-
-    reverse_iterator rbegin() noexcept                { return _data + _num; }
-    const_reverse_iterator crbegin() const noexcept   { return _data + _num; }
-    reverse_iterator rend() noexcept                  { return _data;        }
-    const_reverse_iterator crend() const noexcept     { return _data;        }
-
-    reference operator [] (size_type idx)             { return _data[idx];   }
-    const_reference operator [] (size_type idx) const { return _data[idx];   }
-
-    reference at(size_type pos) {
-      if(pos >= _num) {
-        throw std::out_of_range("accessed position is out of range");
-      }
-      return this->operator[](pos);
-    }
-
-    const_reference at(size_type pos) const {
-      if(pos >= _num) {
-        throw std::out_of_range("accessed position is out of range");
-      }
-      return this->operator[](pos);
-    }
-
-
-    reference front()             { return _data[0];      }
-    const_reference front() const { return _data[0];      }
-    reference back()              { return _data[_num-1]; }
-    const_reference back() const  { return _data[_num-1]; }
-  
-    pointer data() noexcept             { return _data; }
-    const_pointer data() const noexcept { return _data; }
-
-    void push_back(const T& item) {
-      if(_num == _cap) {
-        _enlarge(_cap << 1);
-      }
-      _data[_num++] = item; 
-    }
-
-    void push_back(T&& item) {
-      if(_num == _cap) {
-        _enlarge(_cap << 1);
-      }
-      _data[_num++] = item;
-    }
-
-    void pop_back() {
-      if(_num > 0) {
-        --_num;
-      }
-    }
-
-    void clear() {
-      _num = 0;
-    }
-
-    void resize(size_type N) {
-      if(N > _cap) {
-        _enlarge(N<<1);
-      }
-      _num = N;
-    }
-
-    void reserve(size_type C) {
-      if(C > _cap) {
-        _enlarge(C);     
-      }
-    }
-   
-    bool empty() const    { return _num == 0; }
-    bool in_stack() const { return _data == reinterpret_cast<const_pointer>(_stack); }
-
-    size_type size() const     { return _num; }
-    size_type capacity() const { return _cap; }
-    size_type max_size() const { return std::numeric_limits<size_type>::max(); }
-
-    bool operator == (const PassiveVector& rhs) const {
-      if(_num != rhs._num) {
-        return false;
-      }
-      return std::memcmp(_data, rhs._data, _num * sizeof(T)) == 0;
-    }
-    
-  private:
-    
-    char _stack[S*sizeof(T)];
-    
-    T* _data;
-    
-    size_type _num;
-    size_type _cap;
-
-    A _allocator;
-    
-    void _enlarge(size_type new_cap) {
-
-      auto new_data = _allocator.allocate(new_cap);
-
-      std::memcpy(new_data, _data, sizeof(T) * _num);
-
-      if(!in_stack()) {
-        _allocator.deallocate(_data, _cap);
-      }
-      
-      _cap  = new_cap;
-      _data = new_data;
-    }
-};
-
-
-}  // end of namespace tf. ----------------------------------------------------
-
diff --git a/bundled/taskflow-2.5.0/include/taskflow/utility/singleton.hpp b/bundled/taskflow-2.5.0/include/taskflow/utility/singleton.hpp
deleted file mode 100644 (file)
index de85e28..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-#pragma once
-
-namespace tf {
-
-/** @class Singleton
-
-@brief class template to create a thread-safe singleton object
-
-*/
-template <typename T>
-class Singleton {
-
-  public:
-  
-  /**
-  @brief get a reference to the singleton object
-  */
-  static T& get() {
-    static T instance;
-    return instance;
-  }
-
-  private:
-
-    Singleton() = default;
-    ~Singleton() = default;
-    Singleton(const Singleton&)= delete;
-    Singleton& operator=(const Singleton&)= delete;
-};
-
-
-
-}  // end of namespace tf -----------------------------------------------------
diff --git a/bundled/taskflow-2.5.0/include/taskflow/utility/stringify.hpp b/bundled/taskflow-2.5.0/include/taskflow/utility/stringify.hpp
deleted file mode 100644 (file)
index 6efd1a8..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-#pragma once
-
-#include <iostream>
-#include <string>
-
-namespace tf {
-
-// Procedure: stringify
-template <typename T>
-void ostreamize(std::ostringstream& oss, T&& token) {
-  oss << std::forward<T>(token);  
-}
-
-// Procedure: stringify
-template <typename T, typename... Rest>
-void ostreamize(std::ostringstream& oss, T&& token, Rest&&... rest) {
-  oss << std::forward<T>(token);
-  ostreamize(oss, std::forward<Rest>(rest)...);
-}
-
-}  // end of namespace tf -----------------------------------------------------
diff --git a/bundled/taskflow-2.5.0/include/taskflow/utility/traits.hpp b/bundled/taskflow-2.5.0/include/taskflow/utility/traits.hpp
deleted file mode 100644 (file)
index 1250ddf..0000000
+++ /dev/null
@@ -1,308 +0,0 @@
-#pragma once
-
-#include <type_traits>
-#include <iterator>
-#include <iostream>
-#include <fstream>
-#include <mutex>
-#include <stack>
-#include <queue>
-#include <vector>
-#include <algorithm>
-#include <memory>
-#include <atomic>
-#include <thread>
-#include <future>
-#include <functional>
-#include <unordered_map>
-#include <unordered_set>
-#include <sstream>
-#include <list>
-#include <forward_list>
-#include <numeric>
-#include <random>
-#include <iomanip>
-#include <cassert>
-#include <cmath>
-#include <cstring>
-
-#include "../nstd/variant.hpp"
-
-namespace tf {
-
-//-----------------------------------------------------------------------------
-// Traits
-//-----------------------------------------------------------------------------
-
-// Macro to check whether a class has a member function
-#define define_has_member(member_name)                                     \
-template <typename T>                                                      \
-class has_member_##member_name                                             \
-{                                                                          \
-  typedef char yes_type;                                                   \
-  typedef long no_type;                                                    \
-  template <typename U> static yes_type test(decltype(&U::member_name));   \
-  template <typename U> static no_type  test(...);                         \
-  public:                                                                  \
-    static constexpr bool value = sizeof(test<T>(0)) == sizeof(yes_type);  \
-}
-
-#define has_member(class_, member_name)  has_member_##member_name<class_>::value
-
-// Struct: dependent_false
-template <typename... T>
-struct dependent_false { 
-  static constexpr bool value = false; 
-};
-
-template <typename... T>
-constexpr auto dependent_false_v = dependent_false<T...>::value;
-
-//-----------------------------------------------------------------------------
-// Move-On-Copy
-//-----------------------------------------------------------------------------
-
-// Struct: MoC
-template <typename T>
-struct MoC {
-
-  MoC(T&& rhs) : object(std::move(rhs)) {}
-  MoC(const MoC& other) : object(std::move(other.object)) {}
-
-  T& get() { return object; }
-  
-  mutable T object; 
-};
-
-template <typename T>
-auto make_moc(T&& m) {
-  return MoC<T>(std::forward<T>(m));
-}
-
-//-----------------------------------------------------------------------------
-// Functors.
-//-----------------------------------------------------------------------------
-
-//// Overloadded.
-//template <typename... Ts>
-//struct Functors : Ts... { 
-//  using Ts::operator()... ;
-//};
-//
-//template <typename... Ts>
-//Functors(Ts...) -> Functors<Ts...>;
-
-// ----------------------------------------------------------------------------
-// callable traits
-// ----------------------------------------------------------------------------
-
-template <typename F, typename... Args>
-struct is_invocable :
-  std::is_constructible<
-    std::function<void(Args ...)>,
-    std::reference_wrapper<typename std::remove_reference<F>::type>
-  > {
-};
-
-template <typename F, typename... Args>
-constexpr bool is_invocable_v = is_invocable<F, Args...>::value;
-
-template <typename R, typename F, typename... Args>
-struct is_invocable_r :
-  std::is_constructible<
-    std::function<R(Args ...)>,
-    std::reference_wrapper<typename std::remove_reference<F>::type>
-  > {
-};
-
-template <typename R, typename F, typename... Args>
-constexpr bool is_invocable_r_v = is_invocable_r<R, F, Args...>::value;
-
-
-// ----------------------------------------------------------------------------
-// Function Traits
-// reference: https://github.com/ros2/rclcpp
-// ----------------------------------------------------------------------------
-
-template<typename T>
-struct tuple_tail;
-
-template<typename Head, typename ... Tail>
-struct tuple_tail<std::tuple<Head, Tail ...>> {
-  using type = std::tuple<Tail ...>;
-};
-
-// std::function
-template<typename F>
-struct function_traits
-{
-  using arguments = typename tuple_tail<
-    typename function_traits<decltype(&F::operator())>::argument_tuple_type
-  >::type;
-
-  static constexpr size_t arity = std::tuple_size<arguments>::value;
-
-  template <size_t N>
-  struct argument {
-    static_assert(N < arity, "error: invalid parameter index.");
-    using type = std::tuple_element_t<N, arguments>;
-  };
-  
-  template <size_t N>
-  using argument_t = typename argument<N>::type;
-
-  using return_type = typename function_traits<decltype(&F::operator())>::return_type;
-};
-
-// Free functions
-template<typename R, typename... Args>
-struct function_traits<R(Args...)> {
-
-  using return_type = R;
-  using argument_tuple_type = std::tuple<Args...>;
-  static constexpr size_t arity = sizeof...(Args);
-  template <size_t N>
-  struct argument {
-    static_assert(N < arity, "error: invalid parameter index.");
-    using type = std::tuple_element_t<N, std::tuple<Args...>>;
-  };
-
-  template <size_t N>
-  using argument_t = typename argument<N>::type;
-};
-
-// function pointer
-template<typename R, typename... Args>
-struct function_traits<R(*)(Args...)> : function_traits<R(Args...)> {
-};
-
-// function reference
-template<typename R, typename... Args>
-struct function_traits<R(&)(Args...)> : function_traits<R(Args...)> {
-};
-
-// immutable lambda
-template<typename C, typename R, typename ... Args>
-struct function_traits<R(C::*)(Args ...) const>
-  : function_traits<R(C &, Args ...)>
-{};
-
-// mutable lambda
-template<typename C, typename R, typename ... Args>
-struct function_traits<R(C::*)(Args ...)>
-  : function_traits<R(C &, Args ...)>
-{};
-
-/*// std::bind for object methods
-template<typename C, typename R, typename ... Args, typename ... FArgs>
-#if defined _LIBCPP_VERSION  // libc++ (Clang)
-struct function_traits<std::__bind<R (C::*)(Args ...), FArgs ...>>
-#elif defined _GLIBCXX_RELEASE  // glibc++ (GNU C++ >= 7.1)
-struct function_traits<std::_Bind<R(C::*(FArgs ...))(Args ...)>>
-#elif defined __GLIBCXX__  // glibc++ (GNU C++)
-struct function_traits<std::_Bind<std::_Mem_fn<R (C::*)(Args ...)>(FArgs ...)>>
-#elif defined _MSC_VER  // MS Visual Studio
-struct function_traits<
-  std::_Binder<std::_Unforced, R (C::*)(Args ...), FArgs ...>>
-#else
-#error "Unsupported C++ compiler / standard library"
-#endif
-  : function_traits<R(Args ...)>
-{};
-
-// std::bind for object const methods
-template<typename C, typename R, typename ... Args, typename ... FArgs>
-#if defined _LIBCPP_VERSION  // libc++ (Clang)
-struct function_traits<std::__bind<R (C::*)(Args ...) const, FArgs ...>>
-#elif defined _GLIBCXX_RELEASE  // glibc++ (GNU C++ >= 7.1)
-struct function_traits<std::_Bind<R(C::*(FArgs ...))(Args ...) const>>
-#elif defined __GLIBCXX__  // glibc++ (GNU C++)
-struct function_traits<std::_Bind<std::_Mem_fn<R (C::*)(Args ...) const>(FArgs ...)>>
-#elif defined _MSC_VER  // MS Visual Studio
-struct function_traits<
-  std::_Binder<std::_Unforced, R (C::*)(Args ...) const, FArgs ...>>
-#else
-#error "Unsupported C++ compiler / standard library"
-#endif
-  : function_traits<R(Args ...)>
-{};
-
-// std::bind for free functions
-template<typename R, typename ... Args, typename ... FArgs>
-#if defined _LIBCPP_VERSION  // libc++ (Clang)
-struct function_traits<std::__bind<R( &)(Args ...), FArgs ...>>
-#elif defined __GLIBCXX__  // glibc++ (GNU C++)
-struct function_traits<std::_Bind<R(*(FArgs ...))(Args ...)>>
-#elif defined _MSC_VER  // MS Visual Studio
-struct function_traits<std::_Binder<std::_Unforced, R( &)(Args ...), FArgs ...>>
-#else
-#error "Unsupported C++ compiler / standard library"
-#endif
-  : function_traits<R(Args ...)>
-{}; */
-
-// decay to the raw type
-template <typename F>
-struct function_traits<F&> : function_traits<F> {};
-
-template <typename F>
-struct function_traits<F&&> : function_traits<F> {};
-
-
-// ----------------------------------------------------------------------------
-// nstd::variant
-// ----------------------------------------------------------------------------
-template <typename T, typename>
-struct get_index;
-
-template <size_t I, typename... Ts> 
-struct get_index_impl {};
-
-template <size_t I, typename T, typename... Ts> 
-struct get_index_impl<I, T, T, Ts...> : std::integral_constant<size_t, I>{};
-
-template <size_t I, typename T, typename U, typename... Ts> 
-struct get_index_impl<I, T, U, Ts...> : get_index_impl<I+1, T, Ts...>{};
-
-template <typename T, typename... Ts> 
-struct get_index<T, nstd::variant<Ts...>> : get_index_impl<0, T, Ts...>{};
-
-template <typename T, typename... Ts>
-constexpr auto get_index_v = get_index<T, Ts...>::value;
-
-// ----------------------------------------------------------------------------
-// is_pod
-//-----------------------------------------------------------------------------
-template <typename T>
-struct is_pod {
-  static const bool value = std::is_trivial<T>::value && 
-                            std::is_standard_layout<T>::value;
-};
-
-template <typename T>
-constexpr bool is_pod_v = is_pod<T>::value;
-
-// ----------------------------------------------------------------------------
-// bit_cast
-//-----------------------------------------------------------------------------
-template <class To, class From>
-typename std::enable_if<
-  (sizeof(To) == sizeof(From)) &&
-  std::is_trivially_copyable<From>::value &&
-  std::is_trivial<To>::value,
-  // this implementation requires that To is trivially default constructible
-  To
->::type
-// constexpr support needs compiler magic
-bit_cast(const From &src) noexcept {
-  To dst;
-  std::memcpy(&dst, &src, sizeof(To));
-  return dst;
-}
-
-}  // end of namespace tf. ---------------------------------------------------
-
-
-
diff --git a/bundled/taskflow-2.5.0/include/taskflow/utility/uuid.hpp b/bundled/taskflow-2.5.0/include/taskflow/utility/uuid.hpp
deleted file mode 100644 (file)
index c953b28..0000000
+++ /dev/null
@@ -1,236 +0,0 @@
-#pragma once
-
-#include <iostream>
-#include <cstdio>
-#include <cstdlib>
-#include <cstring>
-#include <cstddef>
-#include <random>
-#include <chrono>
-
-namespace tf {
-
-// Class: UUID
-//
-// A universally unique identifier (UUID) is an identifier standard used in software 
-// construction. A UUID is simply a 128-bit value. The meaning of each bit is defined 
-// by any of several variants.
-// For human-readable display, many systems use a canonical format using hexadecimal 
-// text with inserted hyphen characters.
-// 
-// For example: 123e4567-e89b-12d3-a456-426655440000
-//
-// The intent of UUIDs is to enable distributed systems to uniquely identify information 
-// without significant central coordination. 
-//
-//   Copyright 2006 Andy Tompkins.
-//   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)
-//
-struct UUID {
-
-  using value_type      = uint8_t;
-  using reference       = uint8_t&;
-  using const_reference = const uint8_t&;
-  using iterator        = uint8_t*;
-  using const_iterator  = const uint8_t*;
-  using size_type       = size_t;
-  using difference_type = ptrdiff_t;
-
-  inline UUID();
-
-  UUID(const UUID&) = default;
-  UUID(UUID&&) = default;
-
-  UUID& operator = (const UUID&) = default;
-  UUID& operator = (UUID&&) = default;
-    
-  inline static size_type size(); 
-  inline iterator begin(); 
-  inline const_iterator begin() const; 
-  inline iterator end(); 
-  inline const_iterator end() const; 
-
-  inline bool is_nil() const;
-  inline void swap(UUID& rhs);
-  inline size_t hash_value() const;
-
-  inline bool operator == (const UUID&) const;
-  inline bool operator <  (const UUID&) const;
-  inline bool operator >  (const UUID&) const;
-  inline bool operator != (const UUID&) const;
-  inline bool operator >= (const UUID&) const;
-  inline bool operator <= (const UUID&) const; 
-
-  uint8_t data[16] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
-
-  inline std::string to_string() const;
-};
-
-// Constructor
-inline UUID::UUID() {
-
-  static thread_local std::random_device rd;
-  static thread_local std::mt19937 engine {rd()};
-
-  std::uniform_int_distribution<unsigned long> distribution(
-    std::numeric_limits<unsigned long>::min(),
-    std::numeric_limits<unsigned long>::max()
-  );
-  
-  int i = 0;
-  auto random_value = distribution(engine);
-  for (auto it=begin(); it!=end(); ++it, ++i) {
-    if (i == sizeof(unsigned long)) {
-      random_value = distribution(engine);
-      i = 0;
-    }
-    *it = static_cast<UUID::value_type>((random_value >> (i*8)) & 0xFF);
-  }
-  
-  // set variant: must be 0b10xxxxxx
-  *(begin()+8) &= 0xBF;
-  *(begin()+8) |= 0x80;
-
-  // set version: must be 0b0100xxxx
-  *(begin()+6) &= 0x4F; //0b01001111
-  *(begin()+6) |= 0x40; //0b01000000 
-}
-  
-// Function: size
-inline typename UUID::size_type UUID::size() { 
-  return 16;          
-}
-
-// Function: begin
-inline typename UUID::iterator UUID::begin() { 
-  return data;        
-}
-
-// Function: begin
-inline typename UUID::const_iterator UUID::begin() const { 
-  return data;        
-}
-
-// Function: end
-inline typename UUID::iterator UUID::end() { 
-  return data+size(); 
-}
-
-// Function: end
-inline typename UUID::const_iterator UUID::end() const { 
-  return data+size(); 
-}
-
-// Function: is_nil
-inline bool UUID::is_nil() const {
-  for (std::size_t i = 0; i < sizeof(this->data); ++i) {
-    if (this->data[i] != 0U) {
-      return false;
-    }
-  }
-  return true;
-}
-
-// Procedure: swap
-inline void UUID::swap(UUID& rhs) {
-  UUID tmp = *this;
-  *this = rhs;
-  rhs = tmp;
-}
-
-// Function: hash_value
-inline size_t UUID::hash_value() const {
-  size_t seed = 0;
-  for(auto i=begin(); i != end(); ++i) {
-    seed ^= static_cast<size_t>(*i) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
-  }
-  return seed;
-}
-
-// Operator: ==
-inline bool UUID::operator == (const UUID& rhs) const {
-  return std::memcmp(data, rhs.data, sizeof(data)) == 0;
-}
-
-// Operator: !=
-inline bool UUID::operator != (const UUID& rhs) const {
-  return std::memcmp(data, rhs.data, sizeof(data)) != 0;
-}
-
-// Operator: <
-inline bool UUID::operator < (const UUID& rhs) const {
-  return std::memcmp(data, rhs.data, sizeof(data)) < 0;
-}
-
-// Operator: >
-inline bool UUID::operator > (const UUID& rhs) const {
-  return std::memcmp(data, rhs.data, sizeof(data)) > 0;
-}
-
-// Operator: <=
-inline bool UUID::operator <= (const UUID& rhs) const {
-  return std::memcmp(data, rhs.data, sizeof(data)) <= 0;
-}
-
-// Operator: >=
-inline bool UUID::operator >= (const UUID& rhs) const {
-  return std::memcmp(data, rhs.data, sizeof(data)) >= 0;
-}
-
-// Function: to_string
-inline std::string UUID::to_string() const {
-
-  auto to_char = [](size_t i) {
-    if (i <= 9) return static_cast<char>('0' + i);
-    return static_cast<char>('a' + (i-10));
-  };
-
-  std::string result;
-  result.reserve(36);
-
-  std::size_t i=0;
-  for (auto it = begin(); it!=end(); ++it, ++i) {
-
-    const size_t hi = ((*it) >> 4) & 0x0F;
-    result += to_char(hi);
-
-    const size_t lo = (*it) & 0x0F;
-    result += to_char(lo);
-
-    if (i == 3 || i == 5 || i == 7 || i == 9) {
-      result += '-';
-    }
-  }
-  return result;
-}
-
-// Procedure: swap
-inline void swap(UUID& lhs, UUID& rhs) {
-  lhs.swap(rhs);
-}
-
-// ostream
-inline std::ostream& operator << (std::ostream& os, const UUID& rhs) {
-  os << rhs.to_string();
-  return os;
-}
-
-}  // End of namespace tf. ----------------------------------------------------
-
-//-----------------------------------------------------------------------------
-
-
-namespace std {
-
-// Partial specialization: hash<tf::UUID>
-template <>
-struct hash<tf::UUID> {
-  size_t operator()(const tf::UUID& rhs) const { return rhs.hash_value(); }
-};
-
-
-}  // End of namespace std. ---------------------------------------------------
-
-

In the beginning the Universe was created. This has made a lot of people very angry and has been widely regarded as a bad move.

Douglas Adams


Typeset in Trocchi and Trocchi Bold Sans Serif.