| 135 | |
| 136 | // This is a wrapper around AsyncExecutorProcess. |
| 137 | class AsyncExecutor |
| 138 | { |
| 139 | private: |
| 140 | // Declare async functions as friends. |
| 141 | template <typename F> |
| 142 | friend Future<typename result_of<F()>::type> async( |
| 143 | const F& f, |
| 144 | typename std::enable_if<!std::is_void<typename result_of<F()>::type>::value>::type*); // NOLINT(whitespace/line_length) |
| 145 | |
| 146 | template <typename F> |
| 147 | friend Future<Nothing> async( |
| 148 | const F& f, |
| 149 | typename std::enable_if<std::is_void<typename result_of<F()>::type>::value>::type*); // NOLINT(whitespace/line_length) |
| 150 | |
| 151 | #define TEMPLATE(Z, N, DATA) \ |
| 152 | template <typename F, ENUM_PARAMS(N, typename A)> \ |
| 153 | friend Future<typename result_of<F(ENUM_PARAMS(N, A))>::type> async( \ |
| 154 | const F& f, \ |
| 155 | ENUM_BINARY_PARAMS(N, A, a), \ |
| 156 | typename std::enable_if<!std::is_void<typename result_of<F(ENUM_PARAMS(N, A))>::type>::value>::type*); /* NOLINT(whitespace/line_length) */ \ |
| 157 | \ |
| 158 | template <typename F, ENUM_PARAMS(N, typename A)> \ |
| 159 | friend Future<Nothing> async( \ |
| 160 | const F& f, \ |
| 161 | ENUM_BINARY_PARAMS(N, A, a), \ |
| 162 | typename std::enable_if<std::is_void<typename result_of<F(ENUM_PARAMS(N, A))>::type>::value>::type*); // NOLINT(whitespace/line_length) |
| 163 | |
| 164 | REPEAT_FROM_TO(1, 13, TEMPLATE, _) // Args A0 -> A11. |
| 165 | #undef TEMPLATE |
| 166 | |
| 167 | AsyncExecutor() |
| 168 | { |
| 169 | process = spawn(new AsyncExecutorProcess(), true); // Automatically GC. |
| 170 | } |
| 171 | |
| 172 | virtual ~AsyncExecutor() {} |
| 173 | |
| 174 | // Not copyable, not assignable. |
| 175 | AsyncExecutor(const AsyncExecutor&); |
| 176 | AsyncExecutor& operator=(const AsyncExecutor&); |
| 177 | |
| 178 | template <typename F> |
| 179 | Future<typename result_of<F()>::type> execute( |
| 180 | const F& f, |
| 181 | typename std::enable_if<!std::is_void<typename result_of<F()>::type>::value>::type* = nullptr) // NOLINT(whitespace/line_length) |
| 182 | { |
| 183 | // Need to disambiguate overloaded method. |
| 184 | typename result_of<F()>::type(AsyncExecutorProcess::*method)(const F&) = |
| 185 | &AsyncExecutorProcess::execute<F>; |
| 186 | |
| 187 | return dispatch(process, method, f); |
| 188 | } |
| 189 | |
| 190 | template <typename F> |
| 191 | Future<Nothing> execute( |
| 192 | const F& f, |
| 193 | typename std::enable_if<std::is_void<typename result_of<F()>::type>::value>::type* = nullptr) // NOLINT(whitespace/line_length) |
| 194 | { |