Support arbitrary arguments for c++ worker normal tasks and actor tasks (#14233)

This commit is contained in:
qicosmos 2021-03-01 16:27:03 +08:00 committed by GitHub
parent be9a584a94
commit 277b6f5d3c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 210 additions and 492 deletions

View file

@ -37,6 +37,7 @@ cc_library(
"//:ray_common",
"//:ray_util",
"@boost//:asio",
"@boost//:callable_traits",
"@boost//:thread",
"@com_google_absl//absl/synchronization",
"@msgpack",

View file

@ -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

View file

@ -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

View 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>{}...);
}

View file

@ -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);

View file

@ -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);
}

View file

@ -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);

View file

@ -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);

View file

@ -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);
}

View file

@ -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);

View file

@ -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);
}

View file

@ -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);
}

View file

@ -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);

View file

@ -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()) {

View file

@ -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) {