Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions runtime-common/core/core-types/kphp_type_traits.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,11 @@
// Distributed under the GPL v3 License, see LICENSE.notice.txt

#pragma once

#include <cstddef>
#include <tuple>
#include <type_traits>
#include <utility>

#include "common/type_traits/list_of_types.h"

Expand Down Expand Up @@ -36,6 +39,18 @@ struct is_class_instance : std::false_type {};
template<typename T>
struct is_class_instance<class_instance<T>> : std::true_type {};

template<typename>
struct is_tuple : std::false_type {};

template<typename... Ts>
struct is_tuple<std::tuple<Ts...>> : std::true_type {};

template<typename>
struct is_shape : std::false_type {};

template<size_t... Is, typename... Ts>
struct is_shape<shape<std::index_sequence<Is...>, Ts...>> : std::true_type {};

template<typename T>
inline constexpr bool is_class_instance_v = is_class_instance<T>::value;

Expand Down
141 changes: 87 additions & 54 deletions runtime-light/core/reference-counter/reference-counter-functions.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,52 +4,35 @@

#pragma once

#include <cstddef>
#include <tuple>
#include <utility>

#include "common/php-functions.h"
#include "runtime-common/core/core-types/kphp_type_traits.h"
#include "runtime-common/core/runtime-core.h"
#include "runtime-light/stdlib/diagnostics/logs.h"

namespace kphp::core {

template<typename T>
void set_reference_counter_recursive(Optional<T>& obj, ExtraRefCnt rc) noexcept;

template<typename T>
void set_reference_counter_recursive(class_instance<T>& obj, ExtraRefCnt rc) noexcept;

template<typename T>
void set_reference_counter_recursive(array<T>& obj, ExtraRefCnt rc) noexcept;

template<typename T>
requires(!is_array<T>::value && !is_class_instance<T>::value && !is_optional<T>::value)
void set_reference_counter_recursive(T& /*obj*/, ExtraRefCnt /*rc*/) noexcept {}
template<typename... Ts>
void set_reference_counter_recursive(std::tuple<Ts...>& obj, ExtraRefCnt rc) noexcept;

template<typename T>
void set_reference_counter_recursive(Optional<T>& obj, ExtraRefCnt rc) noexcept {
if (obj.has_value()) {
set_reference_counter_recursive(obj.val(), rc);
}
}
template<size_t... Is, typename... Ts>
void set_reference_counter_recursive(shape<std::index_sequence<Is...>, Ts...>& obj, ExtraRefCnt rc) noexcept;

template<typename T>
void set_reference_counter_recursive(class_instance<T>& obj, ExtraRefCnt rc) noexcept {
if (!obj.is_null()) {
// TODO we need some visitor to visit all the class member
obj.set_reference_counter_to(rc);
}
}
void set_reference_counter_recursive(Optional<T>& obj, ExtraRefCnt rc) noexcept;

template<typename T>
void set_reference_counter_recursive(array<T>& obj, ExtraRefCnt rc) noexcept {
obj.set_reference_counter_to(rc);
for (const auto& it : std::as_const(obj)) {
auto key{it.get_key()};
set_reference_counter_recursive(key, rc);
auto value{it.get_value()};
set_reference_counter_recursive(value, rc);
}
}
requires(!is_class_instance<T>::value && !is_array<T>::value && !is_tuple<T>::value && !is_shape<T>::value && !is_optional<T>::value)
void set_reference_counter_recursive(T& /*obj*/, ExtraRefCnt /*rc*/) noexcept {}

template<>
inline void set_reference_counter_recursive<string>(string& obj, ExtraRefCnt rc) noexcept {
Expand All @@ -65,52 +48,69 @@ inline void set_reference_counter_recursive<mixed>(mixed& obj, ExtraRefCnt rc) n
case mixed::type::FLOAT:
return;
case mixed::type::STRING:
return set_reference_counter_recursive(obj.as_string(), rc);
case mixed::type::OBJECT:
return obj.set_reference_counter_to(rc);
kphp::log::assertion(false);
case mixed::type::ARRAY:
return set_reference_counter_recursive(obj.as_array(), rc);
}
}

// ================================================================================================

template<typename T>
bool is_reference_counter_recursive(const Optional<T>& obj, ExtraRefCnt rc) noexcept;
void set_reference_counter_recursive(class_instance<T>& obj, ExtraRefCnt /*rc*/) noexcept {
if (!obj.is_null()) {
kphp::log::assertion(false);
}
}

template<typename T>
bool is_reference_counter_recursive(const class_instance<T>& obj, ExtraRefCnt rc) noexcept;
void set_reference_counter_recursive(array<T>& obj, ExtraRefCnt rc) noexcept {
obj.set_reference_counter_to(rc);
for (const auto& it : std::as_const(obj)) {
auto key{it.get_key()};
set_reference_counter_recursive(key, rc);
auto value{it.get_value()};
set_reference_counter_recursive(value, rc);
}
}

template<typename T>
bool is_reference_counter_recursive(const array<T>& obj, ExtraRefCnt rc) noexcept;
template<typename... Ts>
void set_reference_counter_recursive(std::tuple<Ts...>& obj, ExtraRefCnt rc) noexcept {
std::apply([&rc](auto&... e) noexcept { (set_reference_counter_recursive(e, rc), ...); }, obj);
}

template<typename T>
requires(!is_array<T>::value && !is_class_instance<T>::value && !is_optional<T>::value)
bool is_reference_counter_recursive(const T& /*obj*/, ExtraRefCnt /*rc*/) noexcept {
return true;
template<size_t... Is, typename... Ts>
void set_reference_counter_recursive(shape<std::index_sequence<Is...>, Ts...>& obj, ExtraRefCnt rc) noexcept {
(set_reference_counter_recursive(obj.template get<Is>(), rc), ...);
}

template<typename T>
bool is_reference_counter_recursive(const Optional<T>& obj, ExtraRefCnt rc) noexcept {
return obj.has_value() ? is_reference_counter_recursive(obj.val(), rc) : true;
void set_reference_counter_recursive(Optional<T>& obj, ExtraRefCnt rc) noexcept {
if (obj.has_value()) {
set_reference_counter_recursive(obj.val(), rc);
}
}

// ================================================================================================

template<typename T>
bool is_reference_counter_recursive(const class_instance<T>& obj, ExtraRefCnt rc) noexcept {
// TODO we need some visitor to visit all the class members
return !obj.is_null() ? obj.is_reference_counter(rc) : true;
}
bool is_reference_counter_recursive(const class_instance<T>& obj, ExtraRefCnt rc) noexcept;

template<typename T>
bool is_reference_counter_recursive(const array<T>& obj, ExtraRefCnt rc) noexcept {
if (!obj.is_reference_counter(rc)) {
return false;
}
bool is_reference_counter_recursive(const array<T>& obj, ExtraRefCnt rc) noexcept;

for (const auto& it : obj) { // NOLINT
if (!is_reference_counter_recursive(it.get_key(), rc) || !is_reference_counter_recursive(it.get_value(), rc)) {
return false;
}
}
template<typename... Ts>
bool is_reference_counter_recursive(const std::tuple<Ts...>& obj, ExtraRefCnt rc) noexcept;

template<size_t... Is, typename... Ts>
bool is_reference_counter_recursive(const shape<std::index_sequence<Is...>, Ts...>& obj, ExtraRefCnt rc) noexcept;

template<typename T>
bool is_reference_counter_recursive(const Optional<T>& obj, ExtraRefCnt rc) noexcept;

template<typename T>
requires(!is_class_instance<T>::value && !is_array<T>::value && !is_tuple<T>::value && !is_shape<T>::value && !is_optional<T>::value)
bool is_reference_counter_recursive(const T& /*obj*/, ExtraRefCnt /*rc*/) noexcept {
return true;
}

Expand All @@ -128,11 +128,44 @@ inline bool is_reference_counter_recursive<mixed>(const mixed& obj, ExtraRefCnt
case mixed::type::FLOAT:
return true;
case mixed::type::STRING:
return is_reference_counter_recursive(obj.as_string(), rc);
case mixed::type::OBJECT:
return obj.is_reference_counter(rc);
kphp::log::assertion(false);
case mixed::type::ARRAY:
return is_reference_counter_recursive(obj.as_array(), rc);
}
}

template<typename T>
bool is_reference_counter_recursive(const class_instance<T>& obj, ExtraRefCnt /*rc*/) noexcept {
if (!obj.is_null()) {
kphp::log::assertion(false);
}
return true;
}

template<typename T>
bool is_reference_counter_recursive(const array<T>& obj, ExtraRefCnt rc) noexcept {
bool ok{obj.is_reference_counter(rc)};
for (const auto& it : obj) { // NOLINT
ok = ok && is_reference_counter_recursive(it.get_key(), rc) && is_reference_counter_recursive(it.get_value(), rc);
}
return ok;
}

template<typename... Ts>
bool is_reference_counter_recursive(const std::tuple<Ts...>& obj, ExtraRefCnt rc) noexcept {
return std::apply([&rc](auto&... e) noexcept { return (is_reference_counter_recursive(e, rc) && ...); }, obj);
}

template<size_t... Is, typename... Ts>
bool is_reference_counter_recursive(const shape<std::index_sequence<Is...>, Ts...>& obj, ExtraRefCnt rc) noexcept {
return (is_reference_counter_recursive(obj.template get<Is>(), rc) && ...);
}

template<typename T>
bool is_reference_counter_recursive(const Optional<T>& obj, ExtraRefCnt rc) noexcept {
return obj.has_value() ? is_reference_counter_recursive(obj.val(), rc) : true;
}

} // namespace kphp::core
Loading