Files
2026-07-13 13:17:40 +08:00

226 lines
6.3 KiB
C++

// Copyright 2020-2021 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
#include <ray/api/ray_runtime_holder.h>
#include <ray/api/serializer.h>
#include <ray/api/type_traits.h>
#include <memory>
#include <msgpack.hpp>
#include <utility>
namespace ray {
template <typename T>
class ObjectRef;
/// Common helper functions used by ObjectRef<T> and ObjectRef<void>;
inline void CheckResult(const std::shared_ptr<msgpack::sbuffer> &packed_object) {
bool has_error =
ray::internal::Serializer::HasError(packed_object->data(), packed_object->size());
if (has_error) {
auto tp = ray::internal::Serializer::Deserialize<std::tuple<int, std::string>>(
packed_object->data(), packed_object->size(), 1);
std::string err_msg = std::get<1>(tp);
throw ray::internal::RayTaskException(err_msg);
}
}
inline void CopyAndAddReference(std::string &dest_id, const std::string &id) {
dest_id = id;
ray::internal::GetRayRuntime()->AddLocalReference(id);
}
inline void SubReference(const std::string &id) {
ray::internal::GetRayRuntime()->RemoveLocalReference(id);
}
/// Represents an object in the object store..
/// \param T The type of object.
template <typename T>
class ObjectRef {
public:
ObjectRef();
~ObjectRef();
// Used to identify its type.
static bool IsObjectRef() { return true; }
ObjectRef(ObjectRef &&rhs) {
SubReference(rhs.id_);
CopyAndAddReference(id_, rhs.id_);
rhs.id_ = {};
}
ObjectRef &operator=(ObjectRef &&rhs) {
if (rhs == *this) {
return *this;
}
SubReference(id_);
CopyAndAddReference(id_, rhs.id_);
// Rvalues need to be sub after add. Otherwise, the reference_count will become 0 and
// be deleted. Cause information such as owner to be deleted.
SubReference(rhs.id_);
rhs.id_ = {};
return *this;
}
ObjectRef(const ObjectRef &rhs) { CopyAndAddReference(id_, rhs.id_); }
ObjectRef &operator=(const ObjectRef &rhs) {
if (rhs == *this) {
return *this;
}
SubReference(id_);
CopyAndAddReference(id_, rhs.id_);
return *this;
}
ObjectRef(const std::string &id);
bool operator==(const ObjectRef<T> &object) const;
/// Get a untyped ID of the object
const std::string &ID() const;
/// Get the object from the object store.
/// This method will be blocked until the object is ready.
///
/// \return shared pointer of the result.
std::shared_ptr<T> Get() const;
/// Get the object from the object store.
/// This method will be blocked until the object is ready.
///
/// \param timeout_ms The maximum amount of time in milliseconds to wait before
/// returning.
/// \return shared pointer of the result.
std::shared_ptr<T> Get(const int &timeout_ms) const;
/// Make ObjectRef serializable
MSGPACK_DEFINE(id_);
private:
std::string id_;
};
// ---------- implementation ----------
template <typename T>
inline static std::shared_ptr<T> GetFromRuntime(const ObjectRef<T> &object,
const int &timeout_ms) {
auto packed_object = internal::GetRayRuntime()->Get(object.ID(), timeout_ms);
CheckResult(packed_object);
if (ray::internal::Serializer::IsXLang(packed_object->data(), packed_object->size())) {
return ray::internal::Serializer::Deserialize<std::shared_ptr<T>>(
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());
}
template <typename T>
ObjectRef<T>::ObjectRef() {}
template <typename T>
ObjectRef<T>::ObjectRef(const std::string &id) {
CopyAndAddReference(id_, id);
}
template <typename T>
ObjectRef<T>::~ObjectRef() {
SubReference(id_);
}
template <typename T>
inline bool ObjectRef<T>::operator==(const ObjectRef<T> &object) const {
return id_ == object.id_;
}
template <typename T>
const std::string &ObjectRef<T>::ID() const {
return id_;
}
template <typename T>
inline std::shared_ptr<T> ObjectRef<T>::Get() const {
return GetFromRuntime(*this, -1);
}
template <typename T>
inline std::shared_ptr<T> ObjectRef<T>::Get(const int &timeout_ms) const {
return GetFromRuntime(*this, timeout_ms);
}
template <>
class ObjectRef<void> {
public:
ObjectRef() = default;
~ObjectRef() { SubReference(id_); }
// Used to identify its type.
static bool IsObjectRef() { return true; }
ObjectRef(const ObjectRef &rhs) { CopyAndAddReference(id_, rhs.id_); }
ObjectRef &operator=(const ObjectRef &rhs) {
CopyAndAddReference(id_, rhs.id_);
return *this;
}
ObjectRef(const std::string &id) { CopyAndAddReference(id_, id); }
bool operator==(const ObjectRef<void> &object) const { return id_ == object.id_; }
/// Get a untyped ID of the object
const std::string &ID() const { return id_; }
/// Get the object from the object store.
/// This method will be blocked until the object is ready.
///
/// \return shared pointer of the result.
void Get() const {
auto packed_object = internal::GetRayRuntime()->Get(id_);
CheckResult(packed_object);
}
/// Get the object from the object store.
/// This method will be blocked until the object is ready.
///
/// \param timeout_ms The maximum amount of time in milliseconds to wait before
/// returning.
/// \return shared pointer of the result.
void Get(const int &timeout_ms) const {
auto packed_object = internal::GetRayRuntime()->Get(id_, timeout_ms);
CheckResult(packed_object);
}
/// Make ObjectRef serializable
MSGPACK_DEFINE(id_);
private:
std::string id_;
};
} // namespace ray