[C++ worker]Support ActorHandle type return value (#28077)

Before we support `ActorHandle` type as parameter, this PR adds support for `ActorHandle` type as return type.
This commit is contained in:
Tao Wang 2022-08-25 10:05:05 +08:00 committed by GitHub
parent 7e560ad92c
commit b6fe6156f5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 41 additions and 17 deletions

View file

@ -17,6 +17,7 @@
#include <ray/api/actor_creator.h>
#include <ray/api/actor_handle.h>
#include <ray/api/actor_task_caller.h>
#include <ray/api/function_manager.h>
#include <ray/api/logging.h>
#include <ray/api/object_ref.h>
#include <ray/api/ray_config.h>
@ -270,7 +271,8 @@ inline ray::internal::TaskCaller<F> Task(F func) {
static_assert(!ray::internal::is_python_v<F>, "Must be a cpp function.");
static_assert(!std::is_member_function_pointer_v<F>,
"Incompatible type: member function cannot be called with ray::Task.");
ray::internal::RemoteFunctionHolder remote_func_holder(std::move(func));
auto func_name = internal::FunctionManager::Instance().GetFunctionName(func);
ray::internal::RemoteFunctionHolder remote_func_holder(std::move(func_name));
return ray::internal::TaskCaller<F>(ray::internal::GetRayRuntime().get(),
std::move(remote_func_holder));
}
@ -278,7 +280,8 @@ inline ray::internal::TaskCaller<F> Task(F func) {
/// Creating an actor.
template <typename F>
inline ray::internal::ActorCreator<F> Actor(F create_func) {
ray::internal::RemoteFunctionHolder remote_func_holder(std::move(create_func));
auto func_name = internal::FunctionManager::Instance().GetFunctionName(create_func);
ray::internal::RemoteFunctionHolder remote_func_holder(std::move(func_name));
return ray::internal::ActorCreator<F>(ray::internal::GetRayRuntime().get(),
std::move(remote_func_holder));
}

View file

@ -15,6 +15,7 @@
#pragma once
#include <ray/api/actor_task_caller.h>
#include <ray/api/function_manager.h>
#include <ray/api/ray_runtime_holder.h>
namespace ray {
@ -47,7 +48,8 @@ class ActorHandle {
static_assert(
std::is_same<ActorType, Self>::value || std::is_base_of<Self, ActorType>::value,
"Class types must be same.");
ray::internal::RemoteFunctionHolder remote_func_holder(actor_func);
auto func_name = internal::FunctionManager::Instance().GetFunctionName(actor_func);
ray::internal::RemoteFunctionHolder remote_func_holder(func_name);
return ray::internal::ActorTaskCaller<F>(
internal::GetRayRuntime().get(), id_, std::move(remote_func_holder));
}

View file

@ -42,5 +42,15 @@ struct TaskArg {
std::string_view meta_str;
};
using ArgsBuffer = msgpack::sbuffer;
using ArgsBufferList = std::vector<ArgsBuffer>;
using RemoteFunction = std::function<msgpack::sbuffer(const ArgsBufferList &)>;
using RemoteFunctionMap_t = std::unordered_map<std::string, RemoteFunction>;
using RemoteMemberFunction =
std::function<msgpack::sbuffer(msgpack::sbuffer *, const ArgsBufferList &)>;
using RemoteMemberFunctionMap_t = std::unordered_map<std::string, RemoteMemberFunction>;
} // namespace internal
} // namespace ray

View file

@ -15,6 +15,7 @@
#pragma once
#include <ray/api/common_types.h>
#include <ray/api/ray_runtime_holder.h>
#include <ray/api/serializer.h>
#include <ray/api/type_traits.h>
@ -33,6 +34,11 @@ namespace internal {
template <typename T>
inline static std::enable_if_t<!std::is_pointer<T>::value, msgpack::sbuffer>
PackReturnValue(T result) {
if constexpr (is_actor_handle_v<T>) {
auto serialized_actor_handle =
RayRuntimeHolder::Instance().Runtime()->SerializeActorHandle(result.ID());
return Serializer::Serialize(serialized_actor_handle);
}
return Serializer::Serialize(std::move(result));
}
@ -48,16 +54,6 @@ inline static msgpack::sbuffer PackVoid() {
msgpack::sbuffer PackError(std::string error_msg);
using ArgsBuffer = msgpack::sbuffer;
using ArgsBufferList = std::vector<ArgsBuffer>;
using RemoteFunction = std::function<msgpack::sbuffer(const ArgsBufferList &)>;
using RemoteFunctionMap_t = std::unordered_map<std::string, RemoteFunction>;
using RemoteMemberFunction =
std::function<msgpack::sbuffer(msgpack::sbuffer *, const ArgsBufferList &)>;
using RemoteMemberFunctionMap_t = std::unordered_map<std::string, RemoteMemberFunction>;
/// It's help to invoke functions and member functions, the class Invoker<Function> help
/// do type erase.
template <typename Function>

View file

@ -16,6 +16,7 @@
#include <ray/api/ray_runtime_holder.h>
#include <ray/api/serializer.h>
#include <ray/api/type_traits.h>
#include <memory>
#include <msgpack.hpp>
@ -118,6 +119,12 @@ inline static std::shared_ptr<T> GetFromRuntime(const ObjectRef<T> &object) {
packed_object->data(), packed_object->size(), internal::XLANG_HEADER_LEN);
}
if constexpr (ray::internal::is_actor_handle_v<T>) {
auto actor_handle = ray::internal::Serializer::Deserialize<std::string>(
packed_object->data(), packed_object->size());
return std::make_shared<T>(T::FromBytes(actor_handle));
}
return ray::internal::Serializer::Deserialize<std::shared_ptr<T>>(
packed_object->data(), packed_object->size());
}

View file

@ -14,7 +14,7 @@
#pragma once
#include <ray/api/function_manager.h>
#include <ray/api/common_types.h>
#include <ray/api/task_options.h>
#include <ray/api/xlang_function.h>
@ -38,9 +38,7 @@ struct RemoteFunctionHolder {
this->class_name = class_name;
this->lang_type = lang_type;
}
template <typename F>
RemoteFunctionHolder(F func) {
auto func_name = FunctionManager::Instance().GetFunctionName(func);
RemoteFunctionHolder(std::string func_name) {
if (func_name.empty()) {
throw RayException(
"Function not found. Please use RAY_REMOTE to register this function.");

View file

@ -14,6 +14,8 @@
#pragma once
#include <ray/api/ray_exception.h>
#include <cmath>
namespace ray {

View file

@ -242,9 +242,15 @@ TEST(RayClusterModeTest, ActorHandleTest) {
auto actor1 = ray::Actor(RAY_FUNC(Counter::FactoryCreate)).Remote();
auto obj1 = actor1.Task(&Counter::Plus1).Remote();
EXPECT_EQ(1, *obj1.Get());
// Test `ActorHandle` type object as parameter.
auto actor2 = ray::Actor(RAY_FUNC(Counter::FactoryCreate)).Remote();
auto obj2 = actor2.Task(&Counter::Plus1ForActor).Remote(actor1);
EXPECT_EQ(2, *obj2.Get());
// Test `ActorHandle` type object as return value.
std::string child_actor_name = "child_actor_name";
auto child_actor =
actor1.Task(&Counter::CreateChildActor).Remote(child_actor_name).Get();
EXPECT_EQ(1, *child_actor->Task(&Counter::Plus1).Remote().Get());
}
TEST(RayClusterModeTest, PythonInvocationTest) {