mirror of
https://github.com/vale981/ray
synced 2025-03-05 18:11:42 -05:00
Support arbitrary arguments for c++ worker normal tasks and actor tasks (#14233)
This commit is contained in:
parent
be9a584a94
commit
277b6f5d3c
15 changed files with 210 additions and 492 deletions
|
@ -37,6 +37,7 @@ cc_library(
|
|||
"//:ray_common",
|
||||
"//:ray_util",
|
||||
"@boost//:asio",
|
||||
"@boost//:callable_traits",
|
||||
"@boost//:thread",
|
||||
"@com_google_absl//absl/synchronization",
|
||||
"@msgpack",
|
||||
|
|
|
@ -1,11 +1,9 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <ray/api/generated/actor_funcs.generated.h>
|
||||
#include <ray/api/generated/create_funcs.generated.h>
|
||||
#include <ray/api/generated/funcs.generated.h>
|
||||
#include <ray/api/ray_runtime.h>
|
||||
|
||||
#include <boost/callable_traits.hpp>
|
||||
#include <memory>
|
||||
#include <msgpack.hpp>
|
||||
|
||||
|
@ -15,6 +13,17 @@ namespace api {
|
|||
|
||||
template <typename T>
|
||||
class ObjectRef;
|
||||
|
||||
template <typename T>
|
||||
struct FilterArgType {
|
||||
using type = T;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct FilterArgType<ObjectRef<T>> {
|
||||
using type = T;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class ActorHandle;
|
||||
template <typename ReturnType>
|
||||
|
@ -28,6 +37,12 @@ class ActorCreator;
|
|||
|
||||
class WaitResult;
|
||||
|
||||
template <typename ActorType, typename ReturnType, typename... Args>
|
||||
using ActorFunc = ReturnType (ActorType::*)(Args...);
|
||||
|
||||
template <typename ReturnType, typename... Args>
|
||||
using CreateActorFunc = ReturnType *(*)(Args...);
|
||||
|
||||
class Ray {
|
||||
public:
|
||||
/// Initialize Ray runtime.
|
||||
|
@ -78,10 +93,26 @@ class Ray {
|
|||
static WaitResult Wait(const std::vector<ObjectID> &ids, int num_objects,
|
||||
int timeout_ms);
|
||||
|
||||
/// Include the `Call` methods for calling remote functions.
|
||||
#include "api/generated/call_funcs.generated.h"
|
||||
/// Create a `TaskCaller` for calling remote function.
|
||||
/// It is used for normal task, such as Ray::Task(Plus1, 1), Ray::Task(Plus, 1, 2).
|
||||
/// \param[in] func The function to be remote executed.
|
||||
/// \param[in] args The function arguments passed by a value or ObjectRef.
|
||||
/// \return TaskCaller.
|
||||
template <typename F, typename... Args>
|
||||
static TaskCaller<boost::callable_traits::return_type_t<F>> Task(F func, Args... args);
|
||||
|
||||
/// Generic version of creating an actor
|
||||
/// It is used for creating an actor, such as: ActorCreator<Counter> creator =
|
||||
/// Ray::Actor(Counter::FactoryCreate, 1).
|
||||
template <typename ActorType, typename... Args>
|
||||
static ActorCreator<ActorType> Actor(
|
||||
CreateActorFunc<ActorType, typename FilterArgType<Args>::type...> create_func,
|
||||
Args... args);
|
||||
|
||||
/// TODO: The bellow specific version of creating an actor will be replaced with generic
|
||||
/// version later.
|
||||
#include <ray/api/generated/create_funcs.generated.h>
|
||||
|
||||
/// Include the `Actor` methods for creating actors.
|
||||
#include "api/generated/create_actors.generated.h"
|
||||
|
||||
private:
|
||||
|
@ -107,9 +138,14 @@ class Ray {
|
|||
ActorHandle<ActorType> &actor,
|
||||
ArgTypes &... args);
|
||||
|
||||
/// Include the `Call` methods for calling actor methods.
|
||||
/// Used by ActorHandle to implement .Call()
|
||||
#include "api/generated/call_actors.generated.h"
|
||||
/// Include the `Call` methods for calling actor methods.
|
||||
/// Used by ActorHandle to implement .Call()
|
||||
/// It is called by ActorHandle: Ray::Task(&Counter::Add, counter/*instance of
|
||||
/// Counter*/, 1);
|
||||
template <typename ReturnType, typename ActorType, typename... Args>
|
||||
static ActorTaskCaller<ReturnType> Task(
|
||||
ActorFunc<ActorType, ReturnType, typename FilterArgType<Args>::type...> actor_func,
|
||||
ActorHandle<ActorType> &actor, Args... args);
|
||||
|
||||
template <typename T>
|
||||
friend class ObjectRef;
|
||||
|
@ -222,21 +258,41 @@ inline ActorTaskCaller<ReturnType> Ray::CallActorInternal(FuncType &actor_func,
|
|||
std::move(task_args));
|
||||
}
|
||||
|
||||
// TODO(barakmich): These includes are generated files that do not contain their
|
||||
// relevant headers. Since they're only used here, they must appear in this
|
||||
// particular order, which is a code smell and breaks lint.
|
||||
//
|
||||
// The generated files, and their generator, should be fixed. Until then, we can
|
||||
// force the order by way of comments
|
||||
//
|
||||
// #1
|
||||
#include <ray/api/generated/exec_funcs.generated.h>
|
||||
// #2
|
||||
#include <ray/api/generated/call_funcs_impl.generated.h>
|
||||
// #3
|
||||
#include <ray/api/exec_funcs.h>
|
||||
/// Normal task.
|
||||
template <typename F, typename... Args>
|
||||
TaskCaller<boost::callable_traits::return_type_t<F>> Ray::Task(F func, Args... args) {
|
||||
using ReturnType = boost::callable_traits::return_type_t<F>;
|
||||
return TaskInternal<ReturnType>(
|
||||
func, NormalExecFunction<ReturnType, typename FilterArgType<Args>::type...>,
|
||||
args...);
|
||||
}
|
||||
|
||||
/// Generic version of creating an actor.
|
||||
template <typename ActorType, typename... Args>
|
||||
ActorCreator<ActorType> Ray::Actor(
|
||||
CreateActorFunc<ActorType, typename FilterArgType<Args>::type...> create_func,
|
||||
Args... args) {
|
||||
return CreateActorInternal<ActorType>(
|
||||
create_func,
|
||||
CreateActorExecFunction<ActorType *, typename FilterArgType<Args>::type...>,
|
||||
args...);
|
||||
}
|
||||
|
||||
/// TODO: The bellow specific version of creating an actor will be replaced with generic
|
||||
/// version later.
|
||||
#include <ray/api/generated/create_actors_impl.generated.h>
|
||||
// #4
|
||||
#include <ray/api/generated/call_actors_impl.generated.h>
|
||||
|
||||
/// Actor task.
|
||||
template <typename ReturnType, typename ActorType, typename... Args>
|
||||
ActorTaskCaller<ReturnType> Ray::Task(
|
||||
ActorFunc<ActorType, ReturnType, typename FilterArgType<Args>::type...> actor_func,
|
||||
ActorHandle<ActorType> &actor, Args... args) {
|
||||
return CallActorInternal<ReturnType, ActorType>(
|
||||
actor_func,
|
||||
ActorExecFunction<ReturnType, ActorType, typename FilterArgType<Args>::type...>,
|
||||
actor, args...);
|
||||
}
|
||||
|
||||
} // namespace api
|
||||
} // namespace ray
|
||||
|
|
|
@ -6,8 +6,6 @@
|
|||
namespace ray {
|
||||
namespace api {
|
||||
|
||||
#include <ray/api/generated/actor_funcs.generated.h>
|
||||
|
||||
/// A handle to an actor which can be used to invoke a remote actor method, with the
|
||||
/// `Call` method.
|
||||
/// \param ActorType The type of the concrete actor class.
|
||||
|
@ -23,7 +21,11 @@ class ActorHandle {
|
|||
const ActorID &ID() const;
|
||||
|
||||
/// Include the `Call` methods for calling remote functions.
|
||||
#include <ray/api/generated/actor_call.generated.h>
|
||||
|
||||
template <typename ReturnType, typename... Args>
|
||||
ActorTaskCaller<ReturnType> Task(
|
||||
ActorFunc<ActorType, ReturnType, typename FilterArgType<Args>::type...> actor_func,
|
||||
Args... args);
|
||||
|
||||
/// Make ActorHandle serializable
|
||||
MSGPACK_DEFINE(id_);
|
||||
|
@ -47,6 +49,13 @@ const ActorID &ActorHandle<ActorType>::ID() const {
|
|||
return id_;
|
||||
}
|
||||
|
||||
#include <ray/api/generated/actor_call_impl.generated.h>
|
||||
template <typename ActorType>
|
||||
template <typename ReturnType, typename... Args>
|
||||
ActorTaskCaller<ReturnType> ActorHandle<ActorType>::Task(
|
||||
ActorFunc<ActorType, ReturnType, typename FilterArgType<Args>::type...> actor_func,
|
||||
Args... args) {
|
||||
return Ray::Task(actor_func, *this, args...);
|
||||
}
|
||||
|
||||
} // namespace api
|
||||
} // namespace ray
|
||||
|
|
91
cpp/include/ray/api/exec_funcs.h
Normal file
91
cpp/include/ray/api/exec_funcs.h
Normal file
|
@ -0,0 +1,91 @@
|
|||
// Copyright 2017 The Ray Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#pragma once
|
||||
|
||||
/// The following execution functions are wrappers of remote functions.
|
||||
/// Execution functions make remote functions executable in distributed system.
|
||||
/// NormalExecFunction the wrapper of normal remote function.
|
||||
/// CreateActorExecFunction the wrapper of actor creation function.
|
||||
/// ActorExecFunction the wrapper of actor member function.
|
||||
|
||||
template <typename ReturnType, typename CastReturnType, typename... OtherArgTypes>
|
||||
std::shared_ptr<msgpack::sbuffer> ExecuteNormalFunction(
|
||||
uintptr_t base_addr, size_t func_offset,
|
||||
const std::vector<std::shared_ptr<RayObject>> &args_buffer, TaskType task_type,
|
||||
std::shared_ptr<OtherArgTypes> &&... args) {
|
||||
int arg_index = 0;
|
||||
Arguments::UnwrapArgs(args_buffer, arg_index, &args...);
|
||||
|
||||
ReturnType return_value;
|
||||
typedef ReturnType (*Func)(OtherArgTypes...);
|
||||
Func func = (Func)(base_addr + func_offset);
|
||||
return_value = (*func)(*args...);
|
||||
|
||||
// TODO: No need use shared_ptr here, refactor later.
|
||||
return std::make_shared<msgpack::sbuffer>(
|
||||
Serializer::Serialize((CastReturnType)(return_value)));
|
||||
}
|
||||
|
||||
template <typename ReturnType, typename ActorType, typename... OtherArgTypes>
|
||||
std::shared_ptr<msgpack::sbuffer> ExecuteActorFunction(
|
||||
uintptr_t base_addr, size_t func_offset,
|
||||
const std::vector<std::shared_ptr<RayObject>> &args_buffer,
|
||||
std::shared_ptr<msgpack::sbuffer> &actor_buffer,
|
||||
std::shared_ptr<OtherArgTypes> &&... args) {
|
||||
uintptr_t actor_ptr = Serializer::Deserialize<uintptr_t>(
|
||||
(const char *)actor_buffer->data(), actor_buffer->size());
|
||||
ActorType *actor_object = (ActorType *)actor_ptr;
|
||||
|
||||
int arg_index = 0;
|
||||
Arguments::UnwrapArgs(args_buffer, arg_index, &args...);
|
||||
|
||||
ReturnType return_value;
|
||||
typedef ReturnType (ActorType::*Func)(OtherArgTypes...);
|
||||
MemberFunctionPtrHolder holder;
|
||||
holder.value[0] = base_addr + func_offset;
|
||||
holder.value[1] = 0;
|
||||
Func func = *((Func *)&holder);
|
||||
return_value = (actor_object->*func)(*args...);
|
||||
|
||||
// TODO: No need use shared_ptr here, refactor later.
|
||||
return std::make_shared<msgpack::sbuffer>(Serializer::Serialize(return_value));
|
||||
}
|
||||
|
||||
template <typename ReturnType, typename... Args>
|
||||
std::shared_ptr<msgpack::sbuffer> NormalExecFunction(
|
||||
uintptr_t base_addr, size_t func_offset,
|
||||
const std::vector<std::shared_ptr<RayObject>> &args_buffer) {
|
||||
return ExecuteNormalFunction<ReturnType, ReturnType, Args...>(
|
||||
base_addr, func_offset, args_buffer, TaskType::NORMAL_TASK,
|
||||
std::shared_ptr<Args>{}...);
|
||||
}
|
||||
|
||||
template <typename ReturnType, typename... Args>
|
||||
std::shared_ptr<msgpack::sbuffer> CreateActorExecFunction(
|
||||
uintptr_t base_addr, size_t func_offset,
|
||||
const std::vector<std::shared_ptr<RayObject>> &args_buffer) {
|
||||
return ExecuteNormalFunction<ReturnType, uintptr_t>(base_addr, func_offset, args_buffer,
|
||||
TaskType::ACTOR_CREATION_TASK,
|
||||
std::shared_ptr<Args>{}...);
|
||||
}
|
||||
|
||||
template <typename ReturnType, typename ActorType, typename... Args>
|
||||
std::shared_ptr<msgpack::sbuffer> ActorExecFunction(
|
||||
uintptr_t base_addr, size_t func_offset,
|
||||
const std::vector<std::shared_ptr<RayObject>> &args_buffer,
|
||||
std::shared_ptr<msgpack::sbuffer> &actor_buffer) {
|
||||
return ExecuteActorFunction<ReturnType, ActorType>(
|
||||
base_addr, func_offset, args_buffer, actor_buffer, std::shared_ptr<Args>{}...);
|
||||
}
|
|
@ -1,41 +0,0 @@
|
|||
/// This file is auto-generated. DO NOT EDIT.
|
||||
/// The following `Call` methods are used to call remote functions of actors.
|
||||
/// Their arguments and return types are as following:
|
||||
/// \param[in] actor_func The function pointer to be remote execution.
|
||||
/// \param[in] arg1...argn The function arguments passed by a value or ObjectRef.
|
||||
/// \return ActorTaskCaller.
|
||||
|
||||
// TODO(Guyang Song): code generation
|
||||
|
||||
// 0 args
|
||||
template <typename ReturnType>
|
||||
ActorTaskCaller<ReturnType> Task(ActorFunc0<ActorType, ReturnType> actor_func);
|
||||
// 1 arg
|
||||
template <typename ReturnType, typename Arg1Type>
|
||||
ActorTaskCaller<ReturnType> Task(ActorFunc1<ActorType, ReturnType, Arg1Type> actor_func,
|
||||
Arg1Type arg1);
|
||||
|
||||
template <typename ReturnType, typename Arg1Type>
|
||||
ActorTaskCaller<ReturnType> Task(ActorFunc1<ActorType, ReturnType, Arg1Type> actor_func,
|
||||
ObjectRef<Arg1Type> &arg1);
|
||||
|
||||
// 2 args
|
||||
template <typename ReturnType, typename Arg1Type, typename Arg2Type>
|
||||
ActorTaskCaller<ReturnType> Task(
|
||||
ActorFunc2<ActorType, ReturnType, Arg1Type, Arg2Type> actor_func, Arg1Type arg1,
|
||||
Arg2Type arg2);
|
||||
|
||||
template <typename ReturnType, typename Arg1Type, typename Arg2Type>
|
||||
ActorTaskCaller<ReturnType> Task(
|
||||
ActorFunc2<ActorType, ReturnType, Arg1Type, Arg2Type> actor_func,
|
||||
ObjectRef<Arg1Type> &arg1, Arg2Type arg2);
|
||||
|
||||
template <typename ReturnType, typename Arg1Type, typename Arg2Type>
|
||||
ActorTaskCaller<ReturnType> Task(
|
||||
ActorFunc2<ActorType, ReturnType, Arg1Type, Arg2Type> actor_func, Arg1Type arg1,
|
||||
ObjectRef<Arg2Type> &arg2);
|
||||
|
||||
template <typename ReturnType, typename Arg1Type, typename Arg2Type>
|
||||
ActorTaskCaller<ReturnType> Task(
|
||||
ActorFunc2<ActorType, ReturnType, Arg1Type, Arg2Type> actor_func,
|
||||
ObjectRef<Arg1Type> &arg1, ObjectRef<Arg2Type> &arg2);
|
|
@ -1,57 +0,0 @@
|
|||
// TODO(Guyang Song): code generation
|
||||
|
||||
// 0 args
|
||||
template <typename ActorType>
|
||||
template <typename ReturnType>
|
||||
ActorTaskCaller<ReturnType> ActorHandle<ActorType>::Task(
|
||||
ActorFunc0<ActorType, ReturnType> actor_func) {
|
||||
return Ray::Task(actor_func, *this);
|
||||
}
|
||||
|
||||
// 1 arg
|
||||
template <typename ActorType>
|
||||
template <typename ReturnType, typename Arg1Type>
|
||||
ActorTaskCaller<ReturnType> ActorHandle<ActorType>::Task(
|
||||
ActorFunc1<ActorType, ReturnType, Arg1Type> actor_func, Arg1Type arg1) {
|
||||
return Ray::Task(actor_func, *this, arg1);
|
||||
}
|
||||
|
||||
template <typename ActorType>
|
||||
template <typename ReturnType, typename Arg1Type>
|
||||
ActorTaskCaller<ReturnType> ActorHandle<ActorType>::Task(
|
||||
ActorFunc1<ActorType, ReturnType, Arg1Type> actor_func, ObjectRef<Arg1Type> &arg1) {
|
||||
return Ray::Task(actor_func, *this, arg1);
|
||||
}
|
||||
|
||||
// 2 args
|
||||
template <typename ActorType>
|
||||
template <typename ReturnType, typename Arg1Type, typename Arg2Type>
|
||||
ActorTaskCaller<ReturnType> ActorHandle<ActorType>::Task(
|
||||
ActorFunc2<ActorType, ReturnType, Arg1Type, Arg2Type> actor_func, Arg1Type arg1,
|
||||
Arg2Type arg2) {
|
||||
return Ray::Task(actor_func, *this, arg1, arg2);
|
||||
}
|
||||
|
||||
template <typename ActorType>
|
||||
template <typename ReturnType, typename Arg1Type, typename Arg2Type>
|
||||
ActorTaskCaller<ReturnType> ActorHandle<ActorType>::Task(
|
||||
ActorFunc2<ActorType, ReturnType, Arg1Type, Arg2Type> actor_func,
|
||||
ObjectRef<Arg1Type> &arg1, Arg2Type arg2) {
|
||||
return Ray::Task(actor_func, *this, arg1, arg2);
|
||||
}
|
||||
|
||||
template <typename ActorType>
|
||||
template <typename ReturnType, typename Arg1Type, typename Arg2Type>
|
||||
ActorTaskCaller<ReturnType> ActorHandle<ActorType>::Task(
|
||||
ActorFunc2<ActorType, ReturnType, Arg1Type, Arg2Type> actor_func, Arg1Type arg1,
|
||||
ObjectRef<Arg2Type> &arg2) {
|
||||
return Ray::Task(actor_func, *this, arg1, arg2);
|
||||
}
|
||||
|
||||
template <typename ActorType>
|
||||
template <typename ReturnType, typename Arg1Type, typename Arg2Type>
|
||||
ActorTaskCaller<ReturnType> ActorHandle<ActorType>::Task(
|
||||
ActorFunc2<ActorType, ReturnType, Arg1Type, Arg2Type> actor_func,
|
||||
ObjectRef<Arg1Type> &arg1, ObjectRef<Arg2Type> &arg2) {
|
||||
return Ray::Task(actor_func, *this, arg1, arg2);
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
|
||||
|
||||
// TODO(Guyang Song): code generation
|
||||
|
||||
// 0 args
|
||||
template <typename ActorType, typename ReturnType>
|
||||
using ActorFunc0 = ReturnType (ActorType::*)();
|
||||
|
||||
// 1 arg
|
||||
template <typename ActorType, typename ReturnType, typename Arg1Type>
|
||||
using ActorFunc1 = ReturnType (ActorType::*)(Arg1Type);
|
||||
|
||||
// 2 args
|
||||
template <typename ActorType, typename ReturnType, typename Arg1Type, typename Arg2Type>
|
||||
using ActorFunc2 = ReturnType (ActorType::*)(Arg1Type, Arg2Type);
|
|
@ -1,40 +0,0 @@
|
|||
|
||||
|
||||
// TODO(Guyang Song): code generation
|
||||
|
||||
// 0 args
|
||||
template <typename ReturnType, typename ActorType>
|
||||
static ActorTaskCaller<ReturnType> Task(ActorFunc0<ActorType, ReturnType> actor_func,
|
||||
ActorHandle<ActorType> &actor);
|
||||
|
||||
// 1 arg
|
||||
template <typename ReturnType, typename ActorType, typename Arg1Type>
|
||||
static ActorTaskCaller<ReturnType> Task(
|
||||
ActorFunc1<ActorType, ReturnType, Arg1Type> actor_func, ActorHandle<ActorType> &actor,
|
||||
Arg1Type arg1);
|
||||
|
||||
template <typename ReturnType, typename ActorType, typename Arg1Type>
|
||||
static ActorTaskCaller<ReturnType> Task(
|
||||
ActorFunc1<ActorType, ReturnType, Arg1Type> actor_func, ActorHandle<ActorType> &actor,
|
||||
ObjectRef<Arg1Type> &arg1);
|
||||
|
||||
// 2 args
|
||||
template <typename ReturnType, typename ActorType, typename Arg1Type, typename Arg2Type>
|
||||
static ActorTaskCaller<ReturnType> Task(
|
||||
ActorFunc2<ActorType, ReturnType, Arg1Type, Arg2Type> actor_func,
|
||||
ActorHandle<ActorType> &actor, Arg1Type arg1, Arg2Type arg2);
|
||||
|
||||
template <typename ReturnType, typename ActorType, typename Arg1Type, typename Arg2Type>
|
||||
static ActorTaskCaller<ReturnType> Task(
|
||||
ActorFunc2<ActorType, ReturnType, Arg1Type, Arg2Type> actor_func,
|
||||
ActorHandle<ActorType> &actor, ObjectRef<Arg1Type> &arg1, Arg2Type arg2);
|
||||
|
||||
template <typename ReturnType, typename ActorType, typename Arg1Type, typename Arg2Type>
|
||||
static ActorTaskCaller<ReturnType> Task(
|
||||
ActorFunc2<ActorType, ReturnType, Arg1Type, Arg2Type> actor_func,
|
||||
ActorHandle<ActorType> &actor, Arg1Type arg1, ObjectRef<Arg2Type> &arg2);
|
||||
|
||||
template <typename ReturnType, typename ActorType, typename Arg1Type, typename Arg2Type>
|
||||
static ActorTaskCaller<ReturnType> Task(
|
||||
ActorFunc2<ActorType, ReturnType, Arg1Type, Arg2Type> actor_func,
|
||||
ActorHandle<ActorType> &actor, ObjectRef<Arg1Type> &arg1, ObjectRef<Arg2Type> &arg2);
|
|
@ -1,62 +0,0 @@
|
|||
// TODO(Guyang Song): code generation
|
||||
// 0 args
|
||||
template <typename ReturnType, typename ActorType>
|
||||
ActorTaskCaller<ReturnType> Ray::Task(ActorFunc0<ActorType, ReturnType> actor_func,
|
||||
ActorHandle<ActorType> &actor) {
|
||||
return CallActorInternal<ReturnType, ActorType>(
|
||||
actor_func, ActorExecFunction<ReturnType, ActorType>, actor);
|
||||
}
|
||||
|
||||
// 1 arg
|
||||
template <typename ReturnType, typename ActorType, typename Arg1Type>
|
||||
ActorTaskCaller<ReturnType> Ray::Task(
|
||||
ActorFunc1<ActorType, ReturnType, Arg1Type> actor_func, ActorHandle<ActorType> &actor,
|
||||
Arg1Type arg1) {
|
||||
return CallActorInternal<ReturnType, ActorType>(
|
||||
actor_func, ActorExecFunction<ReturnType, ActorType, Arg1Type>, actor, arg1);
|
||||
}
|
||||
|
||||
template <typename ReturnType, typename ActorType, typename Arg1Type>
|
||||
ActorTaskCaller<ReturnType> Ray::Task(
|
||||
ActorFunc1<ActorType, ReturnType, Arg1Type> actor_func, ActorHandle<ActorType> &actor,
|
||||
ObjectRef<Arg1Type> &arg1) {
|
||||
return CallActorInternal<ReturnType, ActorType>(
|
||||
actor_func, ActorExecFunction<ReturnType, ActorType, Arg1Type>, actor, arg1);
|
||||
}
|
||||
|
||||
// 2 args
|
||||
template <typename ReturnType, typename ActorType, typename Arg1Type, typename Arg2Type>
|
||||
ActorTaskCaller<ReturnType> Ray::Task(
|
||||
ActorFunc2<ActorType, ReturnType, Arg1Type, Arg2Type> actor_func,
|
||||
ActorHandle<ActorType> &actor, Arg1Type arg1, Arg2Type arg2) {
|
||||
return CallActorInternal<ReturnType, ActorType>(
|
||||
actor_func, ActorExecFunction<ReturnType, ActorType, Arg1Type, Arg2Type>, actor,
|
||||
arg1, arg2);
|
||||
}
|
||||
|
||||
template <typename ReturnType, typename ActorType, typename Arg1Type, typename Arg2Type>
|
||||
ActorTaskCaller<ReturnType> Ray::Task(
|
||||
ActorFunc2<ActorType, ReturnType, Arg1Type, Arg2Type> actor_func,
|
||||
ActorHandle<ActorType> &actor, ObjectRef<Arg1Type> &arg1, Arg2Type arg2) {
|
||||
return CallActorInternal<ReturnType, ActorType>(
|
||||
actor_func, ActorExecFunction<ReturnType, ActorType, Arg1Type, Arg2Type>, actor,
|
||||
arg1, arg2);
|
||||
}
|
||||
|
||||
template <typename ReturnType, typename ActorType, typename Arg1Type, typename Arg2Type>
|
||||
ActorTaskCaller<ReturnType> Ray::Task(
|
||||
ActorFunc2<ActorType, ReturnType, Arg1Type, Arg2Type> actor_func,
|
||||
ActorHandle<ActorType> &actor, Arg1Type arg1, ObjectRef<Arg2Type> &arg2) {
|
||||
return CallActorInternal<ReturnType, ActorType>(
|
||||
actor_func, ActorExecFunction<ReturnType, ActorType, Arg1Type, Arg2Type>, actor,
|
||||
arg1, arg2);
|
||||
}
|
||||
|
||||
template <typename ReturnType, typename ActorType, typename Arg1Type, typename Arg2Type>
|
||||
ActorTaskCaller<ReturnType> Ray::Task(
|
||||
ActorFunc2<ActorType, ReturnType, Arg1Type, Arg2Type> actor_func,
|
||||
ActorHandle<ActorType> &actor, ObjectRef<Arg1Type> &arg1, ObjectRef<Arg2Type> &arg2) {
|
||||
return CallActorInternal<ReturnType, ActorType>(
|
||||
actor_func, ActorExecFunction<ReturnType, ActorType, Arg1Type, Arg2Type>, actor,
|
||||
arg1, arg2);
|
||||
}
|
|
@ -1,37 +0,0 @@
|
|||
/// This file is auto-generated. DO NOT EDIT.
|
||||
/// The following `Call` methods are used to call remote functions.
|
||||
/// Their arguments and return types are as following:
|
||||
/// \param[in] func The function pointer to be remote execution.
|
||||
/// \param[in] arg1...argn The function arguments passed by a value or ObjectRef.
|
||||
/// \return TaskCaller.
|
||||
|
||||
// TODO(Guyang Song): code generation
|
||||
|
||||
// 0 args
|
||||
template <typename ReturnType>
|
||||
static TaskCaller<ReturnType> Task(Func0<ReturnType> func);
|
||||
|
||||
// 1 arg
|
||||
template <typename ReturnType, typename Arg1Type>
|
||||
static TaskCaller<ReturnType> Task(Func1<ReturnType, Arg1Type> func, Arg1Type arg1);
|
||||
|
||||
template <typename ReturnType, typename Arg1Type>
|
||||
static TaskCaller<ReturnType> Task(Func1<ReturnType, Arg1Type> func,
|
||||
ObjectRef<Arg1Type> &arg1);
|
||||
|
||||
// 2 args
|
||||
template <typename ReturnType, typename Arg1Type, typename Arg2Type>
|
||||
static TaskCaller<ReturnType> Task(Func2<ReturnType, Arg1Type, Arg2Type> func,
|
||||
Arg1Type arg1, Arg2Type arg2);
|
||||
|
||||
template <typename ReturnType, typename Arg1Type, typename Arg2Type>
|
||||
static TaskCaller<ReturnType> Task(Func2<ReturnType, Arg1Type, Arg2Type> func,
|
||||
ObjectRef<Arg1Type> &arg1, Arg2Type arg2);
|
||||
|
||||
template <typename ReturnType, typename Arg1Type, typename Arg2Type>
|
||||
static TaskCaller<ReturnType> Task(Func2<ReturnType, Arg1Type, Arg2Type> func,
|
||||
Arg1Type arg1, ObjectRef<Arg2Type> &arg2);
|
||||
|
||||
template <typename ReturnType, typename Arg1Type, typename Arg2Type>
|
||||
static TaskCaller<ReturnType> Task(Func2<ReturnType, Arg1Type, Arg2Type> func,
|
||||
ObjectRef<Arg1Type> &arg1, ObjectRef<Arg2Type> &arg2);
|
|
@ -1,48 +0,0 @@
|
|||
// TODO(Guyang Song): code generation
|
||||
|
||||
// 0 args
|
||||
template <typename ReturnType>
|
||||
TaskCaller<ReturnType> Ray::Task(Func0<ReturnType> func) {
|
||||
return TaskInternal<ReturnType>(func, NormalExecFunction<ReturnType>);
|
||||
}
|
||||
|
||||
// 1 arg
|
||||
template <typename ReturnType, typename Arg1Type>
|
||||
TaskCaller<ReturnType> Ray::Task(Func1<ReturnType, Arg1Type> func, Arg1Type arg1) {
|
||||
return TaskInternal<ReturnType>(func, NormalExecFunction<ReturnType, Arg1Type>, arg1);
|
||||
}
|
||||
|
||||
template <typename ReturnType, typename Arg1Type>
|
||||
TaskCaller<ReturnType> Ray::Task(Func1<ReturnType, Arg1Type> func,
|
||||
ObjectRef<Arg1Type> &arg1) {
|
||||
return TaskInternal<ReturnType>(func, NormalExecFunction<ReturnType, Arg1Type>, arg1);
|
||||
}
|
||||
|
||||
// 2 args
|
||||
template <typename ReturnType, typename Arg1Type, typename Arg2Type>
|
||||
TaskCaller<ReturnType> Ray::Task(Func2<ReturnType, Arg1Type, Arg2Type> func,
|
||||
Arg1Type arg1, Arg2Type arg2) {
|
||||
return TaskInternal<ReturnType>(
|
||||
func, NormalExecFunction<ReturnType, Arg1Type, Arg2Type>, arg1, arg2);
|
||||
}
|
||||
|
||||
template <typename ReturnType, typename Arg1Type, typename Arg2Type>
|
||||
TaskCaller<ReturnType> Ray::Task(Func2<ReturnType, Arg1Type, Arg2Type> func,
|
||||
ObjectRef<Arg1Type> &arg1, Arg2Type arg2) {
|
||||
return TaskInternal<ReturnType>(
|
||||
func, NormalExecFunction<ReturnType, Arg1Type, Arg2Type>, arg1, arg2);
|
||||
}
|
||||
|
||||
template <typename ReturnType, typename Arg1Type, typename Arg2Type>
|
||||
TaskCaller<ReturnType> Ray::Task(Func2<ReturnType, Arg1Type, Arg2Type> func,
|
||||
Arg1Type arg1, ObjectRef<Arg2Type> &arg2) {
|
||||
return TaskInternal<ReturnType>(
|
||||
func, NormalExecFunction<ReturnType, Arg1Type, Arg2Type>, arg1, arg2);
|
||||
}
|
||||
|
||||
template <typename ReturnType, typename Arg1Type, typename Arg2Type>
|
||||
TaskCaller<ReturnType> Ray::Task(Func2<ReturnType, Arg1Type, Arg2Type> func,
|
||||
ObjectRef<Arg1Type> &arg1, ObjectRef<Arg2Type> &arg2) {
|
||||
return TaskInternal<ReturnType>(
|
||||
func, NormalExecFunction<ReturnType, Arg1Type, Arg2Type>, arg1, arg2);
|
||||
}
|
|
@ -1,145 +0,0 @@
|
|||
/// This file is auto-generated. DO NOT EDIT.
|
||||
/// The following execution functions are wrappers of remote functions.
|
||||
/// Execution functions make remote functions executable in distributed system.
|
||||
/// NormalExecFunction the wrapper of normal remote function.
|
||||
/// CreateActorExecFunction the wrapper of actor creation function.
|
||||
/// ActorExecFunction the wrapper of actor member function.
|
||||
|
||||
// TODO(Guyang Song): code generation
|
||||
|
||||
template <typename ReturnType, typename CastReturnType, typename... OtherArgTypes>
|
||||
std::shared_ptr<msgpack::sbuffer> ExecuteNormalFunction(
|
||||
uintptr_t base_addr, size_t func_offset,
|
||||
const std::vector<std::shared_ptr<RayObject>> &args_buffer, TaskType task_type,
|
||||
std::shared_ptr<OtherArgTypes> &... args) {
|
||||
int arg_index = 0;
|
||||
Arguments::UnwrapArgs(args_buffer, arg_index, &args...);
|
||||
|
||||
ReturnType return_value;
|
||||
typedef ReturnType (*Func)(OtherArgTypes...);
|
||||
Func func = (Func)(base_addr + func_offset);
|
||||
return_value = (*func)(*args...);
|
||||
|
||||
// TODO: No need use shared_ptr here, refactor later.
|
||||
return std::make_shared<msgpack::sbuffer>(
|
||||
Serializer::Serialize((CastReturnType)(return_value)));
|
||||
}
|
||||
|
||||
template <typename ReturnType, typename ActorType, typename... OtherArgTypes>
|
||||
std::shared_ptr<msgpack::sbuffer> ExecuteActorFunction(
|
||||
uintptr_t base_addr, size_t func_offset,
|
||||
const std::vector<std::shared_ptr<RayObject>> &args_buffer,
|
||||
std::shared_ptr<msgpack::sbuffer> &actor_buffer,
|
||||
std::shared_ptr<OtherArgTypes> &... args) {
|
||||
uintptr_t actor_ptr = Serializer::Deserialize<uintptr_t>(
|
||||
(const char *)actor_buffer->data(), actor_buffer->size());
|
||||
ActorType *actor_object = (ActorType *)actor_ptr;
|
||||
|
||||
int arg_index = 0;
|
||||
Arguments::UnwrapArgs(args_buffer, arg_index, &args...);
|
||||
|
||||
ReturnType return_value;
|
||||
typedef ReturnType (ActorType::*Func)(OtherArgTypes...);
|
||||
MemberFunctionPtrHolder holder;
|
||||
holder.value[0] = base_addr + func_offset;
|
||||
holder.value[1] = 0;
|
||||
Func func = *((Func *)&holder);
|
||||
return_value = (actor_object->*func)(*args...);
|
||||
|
||||
// TODO: No need use shared_ptr here, refactor later.
|
||||
return std::make_shared<msgpack::sbuffer>(Serializer::Serialize(return_value));
|
||||
}
|
||||
|
||||
// 0 args
|
||||
template <typename ReturnType>
|
||||
std::shared_ptr<msgpack::sbuffer> NormalExecFunction(
|
||||
uintptr_t base_addr, size_t func_offset,
|
||||
const std::vector<std::shared_ptr<RayObject>> &args_buffer) {
|
||||
return ExecuteNormalFunction<ReturnType, ReturnType>(
|
||||
base_addr, func_offset, args_buffer, TaskType::NORMAL_TASK);
|
||||
}
|
||||
|
||||
// 1 arg
|
||||
template <typename ReturnType, typename Arg1Type>
|
||||
std::shared_ptr<msgpack::sbuffer> NormalExecFunction(
|
||||
uintptr_t base_addr, size_t func_offset,
|
||||
const std::vector<std::shared_ptr<RayObject>> &args_buffer) {
|
||||
std::shared_ptr<Arg1Type> arg1_ptr;
|
||||
return ExecuteNormalFunction<ReturnType, ReturnType>(
|
||||
base_addr, func_offset, args_buffer, TaskType::NORMAL_TASK, arg1_ptr);
|
||||
}
|
||||
|
||||
// 2 args
|
||||
template <typename ReturnType, typename Arg1Type, typename Arg2Type>
|
||||
std::shared_ptr<msgpack::sbuffer> NormalExecFunction(
|
||||
uintptr_t base_addr, size_t func_offset,
|
||||
const std::vector<std::shared_ptr<RayObject>> &args_buffer) {
|
||||
std::shared_ptr<Arg1Type> arg1_ptr;
|
||||
std::shared_ptr<Arg2Type> arg2_ptr;
|
||||
return ExecuteNormalFunction<ReturnType, ReturnType>(
|
||||
base_addr, func_offset, args_buffer, TaskType::NORMAL_TASK, arg1_ptr, arg2_ptr);
|
||||
}
|
||||
|
||||
// 0 args
|
||||
template <typename ReturnType>
|
||||
std::shared_ptr<msgpack::sbuffer> CreateActorExecFunction(
|
||||
uintptr_t base_addr, size_t func_offset,
|
||||
const std::vector<std::shared_ptr<RayObject>> &args_buffer) {
|
||||
return ExecuteNormalFunction<ReturnType, uintptr_t>(base_addr, func_offset, args_buffer,
|
||||
TaskType::ACTOR_CREATION_TASK);
|
||||
}
|
||||
|
||||
// 1 arg
|
||||
template <typename ReturnType, typename Arg1Type>
|
||||
std::shared_ptr<msgpack::sbuffer> CreateActorExecFunction(
|
||||
uintptr_t base_addr, size_t func_offset,
|
||||
const std::vector<std::shared_ptr<RayObject>> &args_buffer) {
|
||||
std::shared_ptr<Arg1Type> arg1_ptr;
|
||||
return ExecuteNormalFunction<ReturnType, uintptr_t>(
|
||||
base_addr, func_offset, args_buffer, TaskType::ACTOR_CREATION_TASK, arg1_ptr);
|
||||
}
|
||||
|
||||
// 2 args
|
||||
template <typename ReturnType, typename Arg1Type, typename Arg2Type>
|
||||
std::shared_ptr<msgpack::sbuffer> CreateActorExecFunction(
|
||||
uintptr_t base_addr, size_t func_offset,
|
||||
const std::vector<std::shared_ptr<RayObject>> &args_buffer) {
|
||||
std::shared_ptr<Arg1Type> arg1_ptr;
|
||||
std::shared_ptr<Arg2Type> arg2_ptr;
|
||||
return ExecuteNormalFunction<ReturnType, uintptr_t>(base_addr, func_offset, args_buffer,
|
||||
TaskType::ACTOR_CREATION_TASK,
|
||||
arg1_ptr, arg2_ptr);
|
||||
}
|
||||
|
||||
// 0 args
|
||||
template <typename ReturnType, typename ActorType>
|
||||
std::shared_ptr<msgpack::sbuffer> ActorExecFunction(
|
||||
uintptr_t base_addr, size_t func_offset,
|
||||
const std::vector<std::shared_ptr<RayObject>> &args_buffer,
|
||||
std::shared_ptr<msgpack::sbuffer> &actor_buffer) {
|
||||
return ExecuteActorFunction<ReturnType, ActorType>(base_addr, func_offset, args_buffer,
|
||||
actor_buffer);
|
||||
}
|
||||
|
||||
// 1 arg
|
||||
template <typename ReturnType, typename ActorType, typename Arg1Type>
|
||||
std::shared_ptr<msgpack::sbuffer> ActorExecFunction(
|
||||
uintptr_t base_addr, size_t func_offset,
|
||||
const std::vector<std::shared_ptr<RayObject>> &args_buffer,
|
||||
std::shared_ptr<msgpack::sbuffer> &actor_buffer) {
|
||||
std::shared_ptr<Arg1Type> arg1_ptr;
|
||||
return ExecuteActorFunction<ReturnType, ActorType>(base_addr, func_offset, args_buffer,
|
||||
actor_buffer, arg1_ptr);
|
||||
}
|
||||
|
||||
// 2 args
|
||||
template <typename ReturnType, typename ActorType, typename Arg1Type, typename Arg2Type>
|
||||
std::shared_ptr<msgpack::sbuffer> ActorExecFunction(
|
||||
uintptr_t base_addr, size_t func_offset,
|
||||
const std::vector<std::shared_ptr<RayObject>> &args_buffer,
|
||||
std::shared_ptr<msgpack::sbuffer> &actor_buffer) {
|
||||
std::shared_ptr<Arg1Type> arg1_ptr;
|
||||
std::shared_ptr<Arg2Type> arg2_ptr;
|
||||
return ExecuteActorFunction<ReturnType, ActorType>(base_addr, func_offset, args_buffer,
|
||||
actor_buffer, arg1_ptr, arg2_ptr);
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
|
||||
|
||||
// TODO(Guyang Song): code generation
|
||||
|
||||
// 0 args
|
||||
template <typename ReturnType>
|
||||
using Func0 = ReturnType (*)();
|
||||
|
||||
// 1 arg
|
||||
template <typename ReturnType, typename Arg1Type>
|
||||
using Func1 = ReturnType (*)(Arg1Type);
|
||||
|
||||
// 2 args
|
||||
template <typename ReturnType, typename Arg1Type, typename Arg2Type>
|
||||
using Func2 = ReturnType (*)(Arg1Type, Arg2Type);
|
|
@ -18,6 +18,13 @@ class ObjectRef {
|
|||
ObjectRef();
|
||||
~ObjectRef();
|
||||
|
||||
ObjectRef(const ObjectRef &rhs) { CopyAndAddRefrence(rhs.id_); }
|
||||
|
||||
ObjectRef &operator=(const ObjectRef &rhs) {
|
||||
CopyAndAddRefrence(rhs.id_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
ObjectRef(const ObjectID &id);
|
||||
|
||||
bool operator==(const ObjectRef<T> &object) const;
|
||||
|
@ -35,6 +42,13 @@ class ObjectRef {
|
|||
MSGPACK_DEFINE(id_);
|
||||
|
||||
private:
|
||||
void CopyAndAddRefrence(const ObjectID &id) {
|
||||
id_ = id;
|
||||
if (CoreWorkerProcess::IsInitialized()) {
|
||||
auto &core_worker = CoreWorkerProcess::GetCoreWorker();
|
||||
core_worker.AddLocalReference(id_);
|
||||
}
|
||||
}
|
||||
ObjectID id_;
|
||||
};
|
||||
|
||||
|
@ -46,12 +60,9 @@ ObjectRef<T>::ObjectRef() {}
|
|||
|
||||
template <typename T>
|
||||
ObjectRef<T>::ObjectRef(const ObjectID &id) {
|
||||
id_ = id;
|
||||
if (CoreWorkerProcess::IsInitialized()) {
|
||||
auto &core_worker = CoreWorkerProcess::GetCoreWorker();
|
||||
core_worker.AddLocalReference(id_);
|
||||
}
|
||||
CopyAndAddRefrence(id);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
ObjectRef<T>::~ObjectRef() {
|
||||
if (CoreWorkerProcess::IsInitialized()) {
|
||||
|
|
|
@ -12,6 +12,8 @@ int Plus1(int x) { return x + 1; }
|
|||
|
||||
int Plus(int x, int y) { return x + y; }
|
||||
|
||||
int Triple(int x, int y, int z) { return x + y + z; }
|
||||
|
||||
class Counter {
|
||||
public:
|
||||
int count;
|
||||
|
@ -29,6 +31,8 @@ class Counter {
|
|||
|
||||
int Plus(int x, int y) { return x + y; }
|
||||
|
||||
int Triple(int x, int y, int z) { return x + y + z; }
|
||||
|
||||
int Add(int x) {
|
||||
count += x;
|
||||
return count;
|
||||
|
@ -76,14 +80,17 @@ TEST(RayApiTest, CallWithValueTest) {
|
|||
auto r0 = Ray::Task(Return1).Remote();
|
||||
auto r1 = Ray::Task(Plus1, 3).Remote();
|
||||
auto r2 = Ray::Task(Plus, 2, 3).Remote();
|
||||
auto r3 = Ray::Task(Triple, 1, 2, 3).Remote();
|
||||
|
||||
int result0 = *(r0.Get());
|
||||
int result1 = *(r1.Get());
|
||||
int result2 = *(r2.Get());
|
||||
int result3 = *(r3.Get());
|
||||
|
||||
EXPECT_EQ(result0, 1);
|
||||
EXPECT_EQ(result1, 4);
|
||||
EXPECT_EQ(result2, 5);
|
||||
EXPECT_EQ(result3, 6);
|
||||
}
|
||||
|
||||
TEST(RayApiTest, CallWithObjectTest) {
|
||||
|
@ -113,16 +120,19 @@ TEST(RayApiTest, ActorTest) {
|
|||
auto rt2 = actor.Task(&Counter::Add, 2).Remote();
|
||||
auto rt3 = actor.Task(&Counter::Add, 3).Remote();
|
||||
auto rt4 = actor.Task(&Counter::Add, rt3).Remote();
|
||||
auto rt5 = actor.Task(&Counter::Triple, 1, 2, 3).Remote();
|
||||
|
||||
int return1 = *(rt1.Get());
|
||||
int return2 = *(rt2.Get());
|
||||
int return3 = *(rt3.Get());
|
||||
int return4 = *(rt4.Get());
|
||||
int return5 = *(rt5.Get());
|
||||
|
||||
EXPECT_EQ(return1, 1);
|
||||
EXPECT_EQ(return2, 3);
|
||||
EXPECT_EQ(return3, 6);
|
||||
EXPECT_EQ(return4, 12);
|
||||
EXPECT_EQ(return5, 6);
|
||||
}
|
||||
|
||||
TEST(RayApiTest, CompareWithFuture) {
|
||||
|
|
Loading…
Add table
Reference in a new issue