├── .gitignore ├── .travis.yml ├── Makefile ├── README.md ├── futures.bs └── notes ├── future_continuation_concept.cpp ├── lexicon.md ├── meetings ├── 2018_04_25__futures__face_to_face__planning__lee_bryce.md ├── 2018_04_26__futures__face_to_face__attendees.md ├── 2018_05_03__rapperswil_2018__pre_mailing_deadline__lee_bryce.md ├── 2018_06_20__futures__weekly_us.md ├── 2018_07_09__futures__biweekly_non_us.md ├── 2018_07_11__futures__weekly_us.md ├── 2018_07_13__executors__weekly.md ├── 2018_07_13__executors__weekly │ ├── receiver__ask_0.cpp │ ├── receiver__ask_1.cpp │ ├── receiver__ask_2.cpp │ ├── receiver__ask_3.cpp │ ├── receiver__ask_4.cpp │ ├── receiver__ask_5.cpp │ ├── receiver__ask_6.cpp │ └── receiver__intro.cpp ├── 2018_07_18__futures__weekly_us.md ├── 2018_07_20__executors__weekly.md ├── 2018_07_25__futures__weekly_us.md ├── 2018_07_27__executors__weekly.md └── 2018_08_01__futures__weekly_us.md ├── rapperswil_2018__pre_mailing_deadline__outline.md └── resources.md /.gitignore: -------------------------------------------------------------------------------- 1 | *.html 2 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: python 2 | python: 3 | - "2.7" 4 | install: 5 | - git clone https://github.com/tabatkins/bikeshed.git 6 | - pip install --editable $PWD/bikeshed 7 | - pip install docutils 8 | - bikeshed update 9 | script: 10 | - mkdir out 11 | - bikeshed spec futures.bs out/futures.html 12 | deploy: 13 | provider: pages 14 | skip-cleanup: true 15 | github-token: $GITHUB_TOKEN 16 | on: 17 | branch: master 18 | local-dir: out 19 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | BUILDDIR = build 2 | 3 | all: remote 4 | 5 | setup: 6 | mkdir -p $(BUILDDIR)/ 7 | 8 | remote: setup 9 | find . -name "*.bs" -type f | sed 's/\.bs$$//' | xargs -I{} -t -n 1 sh -c "curl https://api.csswg.org/bikeshed/ -F force=1 -F file=@{}.bs > $(BUILDDIR)/\`basename {}\`.html" 10 | 11 | local: setup 12 | find . -name "*.bs" -type f | sed 's/\.bs$$//' | xargs -I{} -t -n 1 sh -c "bikeshed -f spec {}.bs $(BUILDDIR)/\`basename {}\`.html" 13 | 14 | clean: 15 | rm $(BUILDDIR)/* 16 | rmdir $(BUILDDIR) 17 | 18 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # futures 2 | A proposal for a futures programming model for ISO C++. 3 | 4 | Go [here](https://api.csswg.org/bikeshed/?force=1&url=https://raw.githubusercontent.com/executors/futures/master/futures.bs) to see a rendered copy of the current draft. 5 | -------------------------------------------------------------------------------- /futures.bs: -------------------------------------------------------------------------------- 1 |
2 | Title: A Unified Futures Proposal for C++ 3 | Abstract: Proposed composable future concepts that interoperate with executors. 4 | Shortname: P1054 5 | URL: wg21.link/P1054R0 6 | Revision: 0 7 | Audience: SG1 8 | Status: D 9 | Group: WG21 10 | Issue Tracking: GitHub https://github.com/executors/futures/issues 11 | !Source: github.com/executors/futures/blob/master/futures.bs 12 | No Abstract: yes 13 | Markup Shorthands: markdown yes 14 | Markup Shorthands: biblio yes 15 | Editor: Lee Howes, Facebook, lwh@fb.com 16 | Editor: Bryce Adelstein Lelbach, NVIDIA, brycelelbach@gmail.com 17 | Editor: David S. Hollman, Sandia National Labs, dshollm@sandia.gov 18 | Editor: Michał Dominiak, Nokia, griwes@griwes.info 19 |20 | 21 | 22 | 23 | Contributors: 24 | 25 |
Marshall Cline | 28 |Carter Edwards | 29 |Jay Feldblum | 30 |
Andrii Grynenko | 33 |Jared Hoberock | 34 |Hartmut Kaiser | 35 |
Chris Kohlhoff | 38 |Chris Mysen | 39 |Eric Niebler | 40 |
Sean Parent | 43 |Cory Perry | 44 |Felix Petriconi | 45 |
Kirk Shoop | 48 |Mathias Stearn | 49 |50 | |
Template | 526 |Condition | 527 |Preconditions | 528 |
---|---|---|
531 | ```
532 | template |
536 | `is_move_constructible_v |
537 | `T` is a complete type. | 538 |
541 | ```
542 | template |
546 | `is_move_constructible_v |
547 | `T` is a complete type. | 548 |
551 | ```
552 | template |
556 | `is_future_value_continuation_v |
557 | `T` is a complete type. | 558 |
Variable | 583 |Definition | 584 |
---|---|
`T` | 587 |588 | Either: 589 | * Any (possibly cv-qualified) object type that is not an array, or 590 | * (possibly cv-qualified) `void`. 591 | | 592 |
t | 595 |a value of a type contextually convertible to `T` | 596 |
`e` | 599 |a value of type contextually convertible to `exception_ptr` | 600 |
`P |
603 | A [=promise=] type for value type `T` | 604 |
`p` | 607 |An rvalue of type `P |
608 |
Expression | 616 |Return Type | 617 |Operational semantics | 618 |
---|---|---|
`promise_value_t >` |
621 | `T` | 622 |623 | | 624 |
`p.set_value(t)` | 627 |`void` | 628 |
629 | * *Requires:* `!is_void_v |
633 |
`p.set_value()` | 636 |`void` | 637 |
638 | * *Requires:* `is_void_v |
642 |
`p.set_exception(e)` | 645 |`void` | 646 |Completes the promise and associated future with the error `e`. | 647 |
650 | `p.valid()` 651 | | 652 |Contextually convertible to `bool`. | 653 |`true` if the promise has an associated future that is incomplete, `false` otherwise. | 654 |
Variable | 776 |Definition | 777 |
---|---|
`T` | 780 |781 | Either: 782 | * Any (possibly cv-qualified) object type that is not an array, or 783 | * (possibly cv-qualified) `void`. 784 | | 785 |
`SF |
788 | A `SemiFuture` type for value type `T`. | 789 |
`sf` | 792 |An rvalue of type `SF |
793 |
`E` | 796 |
797 | An executor type, either:
798 | * A `ThenExecutor` such that `execution::can_query_v |
801 |
`e` | 804 |A value of type `E`. | 805 |
`CF |
808 |
809 | A `ContinuableFuture` type for value type `T` and executor type `E`, either:
810 | * `decltype(execution::query(e, promise_contract_t |
813 |
Expression | 821 |Return Type | 822 |Operational Semantics | 823 |
---|---|---|
`future_value_t |
826 | `T` | 827 |828 | |
`future_exception_t |
831 | Implicitly convertible to `exception_ptr`. | 832 |833 | |
`sf.via(e)` | 836 |*implementation-defined* | 837 |
838 | **Returns:** A `ContinuableFuture` for value type `T` that is bound to the executor `e` and will be made ready with the value or exception of `sf` when `sf` is made ready.
839 |
840 |
841 |
842 | **Throws:** If `!execution::query(e, promise_contract_t |
846 |
Variable | 866 |Definition | 867 |
---|---|
`E` | 870 |An executor type. | 871 |
`EI` | 874 |An executor type. | 875 |
`e` | 878 |A value of type `E`. | 879 |
`ei` | 882 |A value of type `EI`. | 883 |
`T` | 886 |887 | Either: 888 | * Any (possibly cv-qualified) object type that is not an array, or 889 | * (possibly cv-qualified) `void`. 890 | | 891 |
`CF |
894 | A `ContinuableFuture` type for value type `T` and executor type `E`. | 895 |
`cf` | 898 |A value of type `CF |
899 |
`rcf` | 902 |An rvalue of type `CF |
903 |
`val` | 906 |The value contained within the successfully completed future `rcf`. | 907 |
`ex` | 910 |The exception contained within the exceptionally completed future `rcf`. | 911 |
`G` | 914 |Any type such that `is_future_continuation_v |
915 |
`g` | 918 |An object of type `G`. | 919 |
`R` 922 | |
923 | Either:
924 | * If `is_same_v |
928 |
`SF |
931 | A `SemiFuture` type for value type `T`. | 932 |
`NORMAL` | 935 |
936 | Either:
937 | * If `is_same_v |
940 |
`EXCEPTIONAL` | 943 |
944 | The expression `DECAY_COPY(std::forward |
946 |
Expression | 954 |Return Type | 955 |Operational Semantics | 956 |
---|---|---|
`cf.get_executor()` | 959 |`E` | 960 |961 | **Returns:** A copy of the executor that the future is bound to. 962 | | 963 |
`rcf.then(g)` | 966 |`CF |
967 | 968 | **Returns:** A `ContinuableFuture` that is bound to the executor `e` and 969 | that wraps the type returned by execution of either the value or exception 970 | operations implemented in the continuation. 971 | 972 | **Effects:** 973 | When `rcf` becomes nonexceptionally ready, and if `NORMAL` is a 974 | well-formed expression, creates an execution agent which invokes `NORMAL` 975 | at most once, with the call to `DECAY_COPY` being evaluated in the thread 976 | that called `.then`. 977 | 978 | Otherwise, when `rcf` becomes exceptionally ready, if `EXCEPTIONAL` is a 979 | well-formed expression, creates an execution agent which invokes 980 | `EXCEPTIONAL` at most once, with the call to `DECAY_COPY` being evaluated 981 | in the thread that called `.then`. 982 | 983 | If `NORMAL` and `EXCEPTIONAL` are both well-formed expressions, 984 | `decltype(EXCEPTIONAL)` shall be convertible to `R`. 985 | 986 | If `NORMAL` is not a well-formed expression and `EXCEPTIONAL` is a 987 | well-formed expression, `decltype(EXCEPTIONAL)` shall be convertible to 988 | `decltype(val)`. 989 | 990 | If neither `NORMAL` nor `EXCEPTIONAL` are well-formed expressions, the 991 | invocation of `.then` shall be ill-formed. 992 | 993 | May block pending completion of `NORMAL` or `EXCEPTIONAL`. 994 | 995 | The invocation of `.then` synchronizes with 996 | (C++Std [intro.multithread]) the invocation of `g`. 997 | 998 | [=Fulfills=] the `ContinuableFuture` with the result of the `NORMAL` or 999 | `EXCEPTIONAL` expression, or any exception thrown by either. 1000 | Otherwise, [=fulfills=] the `ContinuableFuture` with either `val` or `e`. 1001 | 1002 | 1003 | 1004 | **Synchronization:** The destruction of the continuation that generates 1005 | `rcf`'s value synchronizes with the invocation of `g` and with the destruction 1006 | of `g`. 1007 | 1008 | **Postconditions:** For a returned future `f`, `f.get_executor()` returns an executor that compares equal to that returned by `rcf.get_executor()` before the call to `.then`. 1009 | | 1010 |
Variable | 1030 |Definition | 1031 |
---|---|
`E` | 1034 |An executor type. | 1035 |
`EI` | 1038 |An executor type. | 1039 |
`e` | 1042 |A value of type `E`. | 1043 |
`ei` | 1046 |A value of type `EI`. | 1047 |
`T` | 1050 |Any (possibly cv-qualified) object type that is not an array. | 1051 |
`CF |
1054 | A `ContinuableFuture` type for executor type `E` and value type `T`. | 1055 |
`SHF |
1058 | A `SharedFuture` type for executor type `E` and value type `T`. | 1059 |
`shf` | 1062 |A value of type `SHF |
1063 |
`NORMAL` | 1066 |
1067 | The expression `DECAY_COPY(std::forward |
1070 |
`EXCEPTIONAL` | 1073 |
1074 | The expression
1075 | `DECAY_COPY(std::forward |
1077 |
Expression | 1085 |Return Type | 1086 |Operational Semantics | 1087 |
---|---|---|
`shf.then(g)` | 1090 |
1091 | **If** `T` is non-void and `INVOKE(declval |
1100 | 1101 | **Returns:** A `ContinuableFuture` that is bound to the executor `e` and 1102 | that wraps the type returned by execution of either the value or exception 1103 | operations implemented in the continuation. 1104 | 1105 | **Effects:** 1106 | When `shf` becomes nonexceptionally ready, and if `NORMAL` is a 1107 | well-formed expression, creates an execution agent which invokes `NORMAL` 1108 | at most once, with the call to `DECAY_COPY` being evaluated in the thread 1109 | that called `.then`. 1110 | 1111 | Otherwise, when `shf` becomes exceptionally ready, if `EXCEPTIONAL` is a 1112 | well-formed expression, creates an execution agent which invokes 1113 | `EXCEPTIONAL` at most once, with the call to `DECAY_COPY` being evaluated 1114 | in the thread that called `.then`. 1115 | 1116 | If `NORMAL` and `EXCEPTIONAL` are both well-formed expressions, 1117 | `decltype(EXCEPTIONAL)` shall be convertible to `R`. 1118 | 1119 | If `NORMAL` is not a well-formed expression and `EXCEPTIONAL` is a 1120 | well-formed expression, `decltype(EXCEPTIONAL)` shall be convertible to 1121 | `decltype(val)`. 1122 | 1123 | If neither `NORMAL` nor `EXCEPTIONAL` are well-formed expressions, the 1124 | invocation of `.then` shall be ill-formed. 1125 | 1126 | May block pending completion of `NORMAL` or `EXCEPTIONAL`. 1127 | 1128 | The invocation of `.then` synchronizes with 1129 | (C++Std [intro.multithread]) the invocation of `g`. 1130 | 1131 | [=Fulfills=] the `ContinuableFuture` with the result of the `NORMAL` or 1132 | `EXCEPTIONAL` expression, or any exception thrown by either. 1133 | Otherwise, [=fulfills=] the `ContinuableFuture` with either `val` or `e`. 1134 | 1135 | **Postconditions:** 1136 | * Has no observable affect on `sfh`. 1137 | * For a returned future `f`, `f.get_executor()` returns an executor that compares equal tothat returned by `rcf.get_executor()` before the call to `.then`. 1138 | | 1139 |
`shf.via(e)` | 1142 |Implementation-defined | 1143 |1144 | **Returns:** A `ContinuableFuture` for type `T` that is bound to the executor `e`. 1145 | 1146 | **Effect:** Returns an implementation-defined `ContinuableFuture` onto which continuations can be attached that will run on `e`. 1147 | 1148 | **Success:** Succeeds if: 1149 | * `e` is a `ThenExecutor` where `execution::query(e, promise_contract_t{})` or `execution::query(e, cancellable_promise_contract_t{ cancel })` is well-formed for some function `cancel`. 1150 | * `e` is a `OnewayExecutor` or is convertible to a OnewayExecutor. 1151 | 1152 | Fails at compile-time otherwise. 1153 | 1154 | **Postconditions:** 1155 | * Has no observable affect on `sfh`. 1156 | * For a returned future `f`, `f.get_executor()` returns an executor that compares equal to `e`. 1157 | | 1158 |
1963 | A type that satisfies the `Future` requirements for the value type `R`. 1964 |1965 | 1966 | **With:** 1967 | 1968 |
1969 | A type that satisfies the `ContinuableFuture` requirements for the value type `R`. 1970 |1971 | 1972 | 1973 | In the *Operational Semantics* column: 1974 | 1975 | **Replace:** 1976 | 1977 |
1978 | in the associated shared state of the resulting `Future`. 1979 |1980 | 1981 | **With:** 1982 | 1983 |
1984 | in the resulting `ContinuableFuture`. 1985 |1986 | 1987 | ### `ThenExecutor` Requirements ### {#wording_p0443_then_executor} 1988 | 1989 | In the type requirements list: 1990 | 1991 | **Replace:** 1992 | 1993 |
1994 | * `fut` denotes a future object satisfying the `Future` requirements, 1995 | 1996 |1997 | 1998 | **With:** 1999 | 2000 |
2001 | * `fut` denotes a future object that: 2002 | * was returned by a call to `x.twoway_execute`, `x.bulk_twoway_execute`, 2003 | `x.then_execute`, or `x.bulk_then_execute` and meets the 2004 | `ContinuableFuture` requirements. 2005 | * was returned by a call to `execution::query(x, promise_contract_t2009 | 2010 | In the *Return Type* column: 2011 | 2012 | **Replace:** 2013 | 2014 |)` or 2006 | `execution::query(x, cancellable_promise_contract_t )`. 2007 | 2008 |
2015 | A type that satisfies the `Future` requirements for the value type `R`. 2016 |2017 | 2018 | **With:** 2019 | 2020 |
2021 | A type that satisfies the `ContinuableFuture` requirements for the value type `R`. 2022 |2023 | 2024 | In the *Operational Semantics* column: 2025 | 2026 | **Replace:** 2027 | 2028 |
2029 | in the associated shared state of the resulting `Future`. 2030 |2031 | 2032 | **With:** 2033 | 2034 |
2035 | in the resulting `ContinuableFuture`. 2036 |2037 | 2038 | ### `BulkTwoWayExecutor` Requirements ### {#wording_p0443_bulk_two_way_executor} 2039 | 2040 | In the *Return Type* column: 2041 | 2042 | **Replace:** 2043 | 2044 |
2045 | A type that satisfies the `Future` requirements for the value type `R`. 2046 |2047 | 2048 | **With:** 2049 |
2050 | A type that satisfies the `ContinuableFuture` requirements for the value type `R`. 2051 |2052 | 2053 | In the *Operational Semantics* column: 2054 | 2055 | **Replace:** 2056 | 2057 |
2058 | in the associated shared state of the resulting `Future`. 2059 |2060 | 2061 | **With:** 2062 | 2063 |
2064 | in the resulting `ContinuableFuture`. 2065 |2066 | 2067 | ### `BulkThenExecutor` Requirements ### {#wording_p0443_bulk_then_executor} 2068 | 2069 | In the type requirements list: 2070 | 2071 | **Replace:** 2072 | 2073 |
2074 | * fut denotes a future object satisfying the Future requirements, 2075 | 2076 |2077 | 2078 | **With:** 2079 | 2080 |
2081 | * fut denotes a future object that: 2082 | * was returned by a call to `x.twoway_execute`, `x.bulk_twoway_execute`, 2083 | `x.then_execute`, or `x.bulk_then_execute` and meets the 2084 | `ContinuableFuture` requirements. 2085 | * was returned by a call to `execution::query(x, promise_contract_t2089 | 2090 | In the *Return Type* column: 2091 | 2092 | **Replace:** 2093 | 2094 |)` or 2086 | `execution::query(x, cancellable_promise_contract_t )`. 2087 | 2088 |
2095 | A type that satisfies the `Future` requirements for the value type `R`. 2096 |2097 | 2098 | **With:** 2099 | 2100 |
2101 | A type that satisfies the `ContinuableFuture` requirements for the value type `R` 2102 |2103 | 2104 | In the *Operational Semantics* column: 2105 | 2106 | **Replace:** 2107 | 2108 |
2109 | in the associated shared state of the resulting Future. 2110 |2111 | 2112 | **With:** 2113 | 2114 |
2115 | in the resulting ContinuableFuture. 2116 |2117 | 2118 | ### `twoway_t` Customization Points ### {#wording_p0443_twoway_t} 2119 | 2120 | **Replace:** 2121 | 2122 |
2123 | it is `std::experimental::future2125 | 2126 | **With:** 2127 | 2128 |` 2124 |
2129 | it is a `execution::continuable_future2131 | 2132 | ### `single_t` Customization Points ### {#wording_p0443_single_t} 2133 | 2134 | **Replace:** 2135 | 2136 |` 2130 |
2137 | it is `std::experimental::future2139 | 2140 | **With:** 2141 | 2142 |` 2138 |
2143 | it is `execution::continuable_future2145 | 2146 | ### Properties To Indicate If Blocking And Directionality May Be Adapted ### {#wording_p0443_blocking_and_directionality_properties} 2147 | 2148 | Remove `twoway_t` from the **Requirements** column of the Table. 2149 | 2150 | ### Class Template `executor` ### {#wording_p0443_erasing_executor} 2151 | 2152 | **Replace:** 2153 | 2154 |` 2144 |
2155 | ``` 2156 | template2161 | 2162 | **With:** 2163 | 2164 |2157 | std::experimental::future ()>> 2158 | twoway_execute(Function&& f) const 2159 | ``` 2160 |
2165 | ``` 2166 | template2171 | 2172 | **Replace:** 2173 | 2174 |2167 | execution::semi_future ()>> 2168 | twoway_execute(Function&& f) const 2169 | ``` 2170 |
2175 | ``` 2176 | template2181 | 2182 | **With:** 2183 | 2184 |2177 | std::experimental::future ()>> 2178 | bulk_twoway_execute(Function&& f, size_t n, ResultFactory&& rf, SharedFactory&& sf) const; 2179 | ``` 2180 |
2185 | ``` 2186 | template2191 | 2192 | 2193 | 2194 | ### `executor` Operations ### {#wording_p0443_erasing_executor_operations} 2195 | 2196 | **Replace:** 2197 | 2198 |2187 | execution::semi_future ()>> 2188 | bulk_twoway_execute(Function&& f, size_t n, ResultFactory&& rf, SharedFactory&& sf) const; 2189 | ``` 2190 |
2199 | ``` 2200 | template2205 | 2206 | **With:** 2207 | 2208 |2201 | std::experimental::future ()>> 2202 | twoway_execute(Function&& f) const 2203 | ``` 2204 |
2209 | ``` 2210 | template2215 | 2216 | **Replace:** 2217 | 2218 |2211 | /* implementation-defined future type */ 2212 | twoway_execute(Function&& f) const 2213 | ``` 2214 |
2219 | *Returns:* 2220 | A future, whose shared state is made ready when the future returned by 2221 | `e.twoway_execute(f2)` is made ready, containing the result of `f1()` or any 2222 | exception thrown by `f1()`. 2223 | [ *Note:* 2224 | `e2.twoway_execute(f2)` may return any future type that satisfies the `Future` requirements, and not necessarily 2225 | One possible implementation approach is for the polymorphic wrapper to attach a 2226 | continuation to the inner future via that object's `then()` member function. 2227 | When invoked, this continuation stores the result in the outer future's 2228 | associated shared state and makes that shared state ready. 2229 | — *end note* ] 2230 |2231 | 2232 | **With:** 2233 | 2234 |
2235 | *Returns:* 2236 | A value whose type satisfies the `ContinuableFuture` requirements. 2237 | The returned future is [=fulfilled=] when `f1()` completes execution, with 2238 | the result of `f1()` (if `decltype(f1())` is non-void), valueless completion 2239 | (if `decltype(f1())` is `void`), or any exception thrown by `f1()`. 2240 |2241 | 2242 | **Replace:** 2243 | 2244 |
2245 | ``` 2246 | template2251 | 2252 | **With:** 2253 | 2254 |2247 | std::experimental::future ()>> 2248 | void bulk_twoway_execute(Function&& f, size_t n, ResultFactory&& rf, SharedFactory&& sf) const; 2249 | ``` 2250 |
2255 | ``` 2256 | template2261 | 2262 | **Replace:** 2263 | 2264 |2257 | /* implementation-defined future type */ 2258 | bulk_twoway_execute(Function&& f, size_t n, ResultFactory&& rf, SharedFactory&& sf) const; 2259 | ``` 2260 |
2265 | *Returns:* 2266 | A future, whose shared state is made ready when the future returned 2267 | by e.bulk_twoway_execute(f2, n, rf2, sf2) is made ready, containing the result 2268 | in r1 (if decltype(rf1()) is non-void) or any exception thrown by an 2269 | invocation `f1`. 2270 | [ *Note:* 2271 | `e.bulk_twoway_execute(f2)` may return any future type that satisfies the 2272 | `Future` requirements, and not necessarily `std::experimental::future`. 2273 | One possible implementation approach is for the polymorphic wrapper to attach a 2274 | continuation to the inner future via that object's `then()` member function. 2275 | When invoked, this continuation stores the result in the outer future's 2276 | associated shared state and makes that shared state ready. 2277 | — *end note* ] 2278 |2279 | 2280 | **With:** 2281 | 2282 | *Returns:* 2283 | 2284 |
2285 | A value whose type satisfies the `ContinuableFuture` requirements. 2286 | The returned future is [=fulfilled=] when `f1()` completes execution, with 2287 | the result in `r1` (if `decltype(rf1())` is non-void), valueless completion 2288 | (if `decltype(rf1())` is void), or any exception thrown by an invocation `f1`. 2289 |2290 | 2291 | ### `static_thread_pool` Executor Type ### {#wording_p0443_static_thread_pool} 2292 | 2293 | **Replace:** 2294 | 2295 |
2296 | ``` 2297 | template2313 | 2314 | **With:** 2315 | 2316 |2298 | std::experimental::future ()>> 2299 | twoway_execute(Function&& f) const 2300 | 2301 | template 2302 | std::experimental::future (decay_t )>> 2303 | then_execute(Function&& f, Future&& pred) const; 2304 | 2305 | template 2306 | void bulk_execute(Function&& f, size_t n, SharedFactory&& sf) const; 2307 | 2308 | template 2309 | std::experimental::future ()>> 2310 | void bulk_twoway_execute(Function&& f, size_t n, ResultFactory&& rf, SharedFactory&& sf) const; 2311 | ``` 2312 |
2317 | ``` 2318 | template2336 | -------------------------------------------------------------------------------- /notes/future_continuation_concept.cpp: -------------------------------------------------------------------------------- 1 | #include2319 | std::execution::continuable_future ()>, C> 2320 | twoway_execute(Function&& f) const 2321 | 2322 | template 2323 | execution::continuable_future (decay_t )>, C> 2324 | then_execute(Function&& f, Future&& pred) const; 2325 | 2326 | template 2327 | void bulk_execute(Function&& f, size_t n, SharedFactory&& sf) const; 2328 | 2329 | template 2330 | execution::continuable_future ()>>, C> 2331 | void bulk_twoway_execute(Function&& f, size_t n, ResultFactory&& rf, SharedFactory&& sf) const 2332 | ``` 2333 | 2334 | Replace the same instances in the documentation section below the main code block. 2335 |