|
16 | 16 | #include "orc-rt-c/WrapperFunction.h"
|
17 | 17 | #include "orc-rt/CallableTraitsHelper.h"
|
18 | 18 | #include "orc-rt/Error.h"
|
| 19 | +#include "orc-rt/ExecutorAddress.h" |
19 | 20 | #include "orc-rt/bind.h"
|
| 21 | +#include "orc-rt/move_only_function.h" |
20 | 22 |
|
21 | 23 | #include <utility>
|
22 | 24 |
|
@@ -205,6 +207,128 @@ struct ResultDeserializer<std::tuple<Error>, Serializer> {
|
205 | 207 | /// wrapper functions in C++.
|
206 | 208 | struct WrapperFunction {
|
207 | 209 |
|
| 210 | + /// Wraps an asynchronous method (a method returning void, and taking a |
| 211 | + /// return callback as its first argument) for use with |
| 212 | + /// WrapperFunction::handle. |
| 213 | + /// |
| 214 | + /// AsyncMethod's call operator takes an ExecutorAddr as its second argument, |
| 215 | + /// casts it to a ClassT*, and then calls the wrapped method on that pointer, |
| 216 | + /// forwarding the return callback and any subsequent arguments (after the |
| 217 | + /// second argument representing the object address). |
| 218 | + /// |
| 219 | + /// This utility removes some of the boilerplate from writing wrappers for |
| 220 | + /// method calls. |
| 221 | + template <typename ClassT, typename ReturnT, typename... ArgTs> |
| 222 | + struct AsyncMethod { |
| 223 | + AsyncMethod(void (ClassT::*M)(ReturnT, ArgTs...)) : M(M) {} |
| 224 | + void operator()(ReturnT &&Return, ExecutorAddr Obj, ArgTs &&...Args) { |
| 225 | + (Obj.toPtr<ClassT *>()->*M)(std::forward<ReturnT>(Return), |
| 226 | + std::forward<ArgTs>(Args)...); |
| 227 | + } |
| 228 | + |
| 229 | + private: |
| 230 | + void (ClassT::*M)(ReturnT, ArgTs...); |
| 231 | + }; |
| 232 | + |
| 233 | + /// Create an AsyncMethod wrapper for the given method pointer. The given |
| 234 | + /// method should be asynchronous: returning void, and taking a return |
| 235 | + /// callback as its first argument. |
| 236 | + /// |
| 237 | + /// The handWithAsyncMethod function can be used to remove some of the |
| 238 | + /// boilerplate from writing wrappers for method calls: |
| 239 | + /// |
| 240 | + /// @code{.cpp} |
| 241 | + /// class MyClass { |
| 242 | + /// public: |
| 243 | + /// void myMethod(move_only_function<void(std::string)> Return, |
| 244 | + // uint32_t X, bool Y) { ... } |
| 245 | + /// }; |
| 246 | + /// |
| 247 | + /// // SPS Method signature -- note MyClass object address as first |
| 248 | + /// // argument. |
| 249 | + /// using SPSMyMethodWrapperSignature = |
| 250 | + /// SPSString(SPSExecutorAddr, uint32_t, bool); |
| 251 | + /// |
| 252 | + /// |
| 253 | + /// static void adder_add_async_sps_wrapper( |
| 254 | + /// orc_rt_SessionRef Session, void *CallCtx, |
| 255 | + /// orc_rt_WrapperFunctionReturn Return, |
| 256 | + /// orc_rt_WrapperFunctionBuffer ArgBytes) { |
| 257 | + /// using SPSSig = SPSString(SPSExecutorAddr, int32_t, bool); |
| 258 | + /// SPSWrapperFunction<SPSSig>::handle( |
| 259 | + /// Session, CallCtx, Return, ArgBytes, |
| 260 | + /// WrapperFunction::handleWithAsyncMethod(&MyClass::myMethod)); |
| 261 | + /// } |
| 262 | + /// @endcode |
| 263 | + /// |
| 264 | + template <typename ClassT, typename ReturnT, typename... ArgTs> |
| 265 | + static AsyncMethod<ClassT, ReturnT, ArgTs...> |
| 266 | + handleWithAsyncMethod(void (ClassT::*M)(ReturnT, ArgTs...)) { |
| 267 | + return AsyncMethod<ClassT, ReturnT, ArgTs...>(M); |
| 268 | + } |
| 269 | + |
| 270 | + /// Wraps a synchronous method (an ordinary method that returns its result, |
| 271 | + /// as opposed to an asynchronous method, see AsyncMethod) for use with |
| 272 | + /// WrapperFunction::handle. |
| 273 | + /// |
| 274 | + /// SyncMethod's call operator takes a return callback as its first argument |
| 275 | + /// and an ExecutorAddr as its second argument. The ExecutorAddr argument is |
| 276 | + /// cast to a ClassT*, and then called passing the subsequent arguments |
| 277 | + /// (after the second argument representing the object address). The Return |
| 278 | + /// callback is then called on the value returned from the method. |
| 279 | + /// |
| 280 | + /// This utility removes some of the boilerplate from writing wrappers for |
| 281 | + /// method calls. |
| 282 | + template <typename ClassT, typename RetT, typename... ArgTs> |
| 283 | + class SyncMethod { |
| 284 | + public: |
| 285 | + SyncMethod(RetT (ClassT::*M)(ArgTs...)) : M(M) {} |
| 286 | + |
| 287 | + void operator()(move_only_function<void(RetT)> Return, ExecutorAddr Obj, |
| 288 | + ArgTs &&...Args) { |
| 289 | + Return((Obj.toPtr<ClassT *>()->*M)(std::forward<ArgTs>(Args)...)); |
| 290 | + } |
| 291 | + |
| 292 | + private: |
| 293 | + RetT (ClassT::*M)(ArgTs...); |
| 294 | + }; |
| 295 | + |
| 296 | + /// Create an SyncMethod wrapper for the given method pointer. The given |
| 297 | + /// method should be synchronous, i.e. returning its result (as opposed to |
| 298 | + /// asynchronous, see AsyncMethod). |
| 299 | + /// |
| 300 | + /// The handWithAsyncMethod function can be used to remove some of the |
| 301 | + /// boilerplate from writing wrappers for method calls: |
| 302 | + /// |
| 303 | + /// @code{.cpp} |
| 304 | + /// class MyClass { |
| 305 | + /// public: |
| 306 | + /// std::string myMethod(uint32_t X, bool Y) { ... } |
| 307 | + /// }; |
| 308 | + /// |
| 309 | + /// // SPS Method signature -- note MyClass object address as first |
| 310 | + /// // argument. |
| 311 | + /// using SPSMyMethodWrapperSignature = |
| 312 | + /// SPSString(SPSExecutorAddr, uint32_t, bool); |
| 313 | + /// |
| 314 | + /// |
| 315 | + /// static void adder_add_sync_sps_wrapper( |
| 316 | + /// orc_rt_SessionRef Session, void *CallCtx, |
| 317 | + /// orc_rt_WrapperFunctionReturn Return, |
| 318 | + /// orc_rt_WrapperFunctionBuffer ArgBytes) { |
| 319 | + /// using SPSSig = SPSString(SPSExecutorAddr, int32_t, bool); |
| 320 | + /// SPSWrapperFunction<SPSSig>::handle( |
| 321 | + /// Session, CallCtx, Return, ArgBytes, |
| 322 | + /// WrapperFunction::handleWithSyncMethod(&Adder::addSync)); |
| 323 | + /// } |
| 324 | + /// @endcode |
| 325 | + /// |
| 326 | + template <typename ClassT, typename RetT, typename... ArgTs> |
| 327 | + static SyncMethod<ClassT, RetT, ArgTs...> |
| 328 | + handleWithSyncMethod(RetT (ClassT::*M)(ArgTs...)) { |
| 329 | + return SyncMethod<ClassT, RetT, ArgTs...>(M); |
| 330 | + } |
| 331 | + |
208 | 332 | /// Make a call to a wrapper function.
|
209 | 333 | ///
|
210 | 334 | /// This utility serializes and deserializes arguments and return values
|
|
0 commit comments