mirror of https://github.com/mamba-org/mamba.git
fixed `synchronized_value` equality and assignation operations + added related tests
This commit is contained in:
parent
d80a7b2032
commit
84e7be1adb
|
@ -37,6 +37,26 @@ namespace mamba::util
|
||||||
template <class T, template <class...> class U>
|
template <class T, template <class...> class U>
|
||||||
constexpr bool is_type_instance_of_v = is_type_instance_of<T, U>::value;
|
constexpr bool is_type_instance_of_v = is_type_instance_of<T, U>::value;
|
||||||
|
|
||||||
|
/// `true` if the instances of two provided types can be compared with operator==.
|
||||||
|
/// Notice that this concept is less restrictive than `std::equality_comparable_with`,
|
||||||
|
/// which requires the existence of a common reference type for T and U. This additional
|
||||||
|
/// restriction makes it impossible to use it in the context here (orginally of sparrow), where
|
||||||
|
/// we want to compare objects that are logically similar while being "physically" different.
|
||||||
|
// Source:
|
||||||
|
// https://github.com/man-group/sparrow/blob/66f70418cf1b00cc294c99bbbe04b5b4d2f83c98/include/sparrow/utils/mp_utils.hpp#L604-L619
|
||||||
|
|
||||||
|
template <class T, class U>
|
||||||
|
concept weakly_equality_comparable_with = requires(
|
||||||
|
const std::remove_reference_t<T>& t,
|
||||||
|
const std::remove_reference_t<U>& u
|
||||||
|
) {
|
||||||
|
{ t == u } -> std::convertible_to<bool>;
|
||||||
|
{ t != u } -> std::convertible_to<bool>;
|
||||||
|
{ u == t } -> std::convertible_to<bool>;
|
||||||
|
{ u != t } -> std::convertible_to<bool>;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/////////////////////////////
|
/////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
@ -293,7 +313,8 @@ namespace mamba::util
|
||||||
the call. If `SharedMutex<M> == true`, the lock is a shared-lock for the provided
|
the call. If `SharedMutex<M> == true`, the lock is a shared-lock for the provided
|
||||||
`synchronized_value`'s mutex.
|
`synchronized_value`'s mutex.
|
||||||
*/
|
*/
|
||||||
template <std::equality_comparable_with<T> U, Mutex OtherMutex>
|
template <std::default_initializable U, Mutex OtherMutex>
|
||||||
|
requires std::assignable_from<T&, U>
|
||||||
auto operator=(const synchronized_value<U, OtherMutex>& other) -> synchronized_value&;
|
auto operator=(const synchronized_value<U, OtherMutex>& other) -> synchronized_value&;
|
||||||
|
|
||||||
/** Locks and assign the provided value to the stored object.
|
/** Locks and assign the provided value to the stored object.
|
||||||
|
@ -483,12 +504,12 @@ namespace mamba::util
|
||||||
/** Locks (shared if possible) and compare equality of the stored object's value with the
|
/** Locks (shared if possible) and compare equality of the stored object's value with the
|
||||||
provided value.
|
provided value.
|
||||||
*/
|
*/
|
||||||
auto operator==(const std::equality_comparable_with<T> auto& other_value) const -> bool;
|
auto operator==(const weakly_equality_comparable_with<T> auto& other_value) const -> bool;
|
||||||
|
|
||||||
/** Locks both (shared if possible) and compare equality of the stored object's value with
|
/** Locks both (shared if possible) and compare equality of the stored object's value with
|
||||||
the provided value.
|
the provided value.
|
||||||
*/
|
*/
|
||||||
template <std::equality_comparable_with<T> U, Mutex OtherMutex>
|
template <weakly_equality_comparable_with<T> U, Mutex OtherMutex>
|
||||||
auto operator==(const synchronized_value<U, OtherMutex>& other_value) const -> bool;
|
auto operator==(const synchronized_value<U, OtherMutex>& other_value) const -> bool;
|
||||||
|
|
||||||
auto swap(synchronized_value& other) -> void;
|
auto swap(synchronized_value& other) -> void;
|
||||||
|
@ -540,7 +561,8 @@ namespace mamba::util
|
||||||
}
|
}
|
||||||
|
|
||||||
template <std::default_initializable T, Mutex M>
|
template <std::default_initializable T, Mutex M>
|
||||||
template <std::equality_comparable_with<T> U, Mutex OtherMutex>
|
template <std::default_initializable U, Mutex OtherMutex>
|
||||||
|
requires std::assignable_from<T&, U>
|
||||||
auto synchronized_value<T, M>::operator=(const synchronized_value<U, OtherMutex>& other)
|
auto synchronized_value<T, M>::operator=(const synchronized_value<U, OtherMutex>& other)
|
||||||
-> synchronized_value<T, M>&
|
-> synchronized_value<T, M>&
|
||||||
{
|
{
|
||||||
|
@ -616,7 +638,8 @@ namespace mamba::util
|
||||||
}
|
}
|
||||||
|
|
||||||
template <std::default_initializable T, Mutex M>
|
template <std::default_initializable T, Mutex M>
|
||||||
auto synchronized_value<T, M>::operator==(const std::equality_comparable_with<T> auto& other_value
|
auto
|
||||||
|
synchronized_value<T, M>::operator==(const weakly_equality_comparable_with<T> auto& other_value
|
||||||
) const -> bool
|
) const -> bool
|
||||||
{
|
{
|
||||||
auto _ = lock_as_readonly(m_mutex);
|
auto _ = lock_as_readonly(m_mutex);
|
||||||
|
@ -624,7 +647,7 @@ namespace mamba::util
|
||||||
}
|
}
|
||||||
|
|
||||||
template <std::default_initializable T, Mutex M>
|
template <std::default_initializable T, Mutex M>
|
||||||
template <std::equality_comparable_with<T> U, Mutex OtherMutex>
|
template <weakly_equality_comparable_with<T> U, Mutex OtherMutex>
|
||||||
auto
|
auto
|
||||||
synchronized_value<T, M>::operator==(const synchronized_value<U, OtherMutex>& other_value) const
|
synchronized_value<T, M>::operator==(const synchronized_value<U, OtherMutex>& other_value) const
|
||||||
-> bool
|
-> bool
|
||||||
|
@ -655,7 +678,6 @@ namespace mamba::util
|
||||||
{
|
{
|
||||||
return std::make_tuple(std::forward<SynchronizedValues>(sync_values).synchronize()...);
|
return std::make_tuple(std::forward<SynchronizedValues>(sync_values).synchronize()...);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -95,6 +95,28 @@ namespace
|
||||||
auto operator<=>(const ValueType&) const noexcept = default;
|
auto operator<=>(const ValueType&) const noexcept = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ConvertibleToValueType
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
operator ValueType() const
|
||||||
|
{
|
||||||
|
return { i };
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ComparableToValueType
|
||||||
|
{
|
||||||
|
int j = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
bool operator==(const ValueType& left, const ComparableToValueType& right)
|
||||||
|
{
|
||||||
|
return left.x == right.j;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// NOTE: We do not use TEMPLATE_TEST_CASE or TEMPLATE_LIST_TEST_CASE here because code coverage
|
// NOTE: We do not use TEMPLATE_TEST_CASE or TEMPLATE_LIST_TEST_CASE here because code coverage
|
||||||
// tools (such as gcov/lcov) do not properly attribute coverage to tests instantiated via
|
// tools (such as gcov/lcov) do not properly attribute coverage to tests instantiated via
|
||||||
// template test cases. Instead, we use individual TEST_CASEs for each mutex type, and factorize
|
// template test cases. Instead, we use individual TEST_CASEs for each mutex type, and factorize
|
||||||
|
@ -113,6 +135,23 @@ namespace
|
||||||
synchronized_value a;
|
synchronized_value a;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SECTION("compatible value assignation")
|
||||||
|
{
|
||||||
|
synchronized_value a;
|
||||||
|
a = ConvertibleToValueType{ 1234 };
|
||||||
|
REQUIRE(a->x == 1234);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("compatible comparison")
|
||||||
|
{
|
||||||
|
synchronized_value a;
|
||||||
|
ComparableToValueType x{ a->x };
|
||||||
|
REQUIRE(a == x);
|
||||||
|
ComparableToValueType y{ a->x +1 };
|
||||||
|
REQUIRE(a != y);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
static constexpr auto initial_value = ValueType{ 42 };
|
static constexpr auto initial_value = ValueType{ 42 };
|
||||||
synchronized_value sv{ initial_value };
|
synchronized_value sv{ initial_value };
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue