Program Listing for File Duct.hpp¶
↰ Return to documentation for file (include/uit/ducts/Duct.hpp)
#pragma once
#ifndef UIT_DUCTS_DUCT_HPP_INCLUDE
#define UIT_DUCTS_DUCT_HPP_INCLUDE
#include <stddef.h>
#include <string>
#include <type_traits>
#include <utility>
#include <variant>
#include "../../../third-party/Empirical/source/base/assert.h"
#include "../../../third-party/Empirical/source/base/optional.h"
#include "../../../third-party/Empirical/source/meta/TypePack.h"
#include "../../../third-party/Empirical/source/tools/string_utils.h"
#include "../../uitsl/math/math_utils.hpp"
#include "../../uitsl/meta/HasMemberFunction.hpp"
#include "../../uitsl/mpi/mpi_utils.hpp"
#include "../../uitsl/utility/print_utils.hpp"
namespace uit {
namespace internal {
UITSL_GENERATE_HAS_MEMBER_FUNCTION( CanStep );
template<typename ImplSpec>
class Duct {
using ducts_t = typename emp::TypePack<
typename ImplSpec::IntraDuct,
typename ImplSpec::ThreadDuct,
typename ImplSpec::ProcInletDuct,
typename ImplSpec::ProcOutletDuct
>::make_unique;
typename ducts_t::template apply<std::variant> impl;
using T = typename ImplSpec::T;
bool MaybeHoldsIntraImpl() const {
return std::holds_alternative<typename ImplSpec::IntraDuct>( impl );
}
bool MaybeHoldsThreadImpl() const {
return std::holds_alternative<typename ImplSpec::ThreadDuct>( impl );
}
bool MaybeHoldsProcImpl() const {
return (
std::holds_alternative<typename ImplSpec::ProcInletDuct>( impl )
|| std::holds_alternative<typename ImplSpec::ProcOutletDuct>( impl )
);
}
bool HoldsAmbiguousImpl() const {
return uitsl::sum(
MaybeHoldsIntraImpl(),
MaybeHoldsThreadImpl(),
MaybeHoldsProcImpl()
) > 1;
}
public:
using uid_t = std::uintptr_t;
Duct(Duct& other) = default;
Duct(const Duct& other) = default;
Duct(Duct&& other) = default;
template <typename... Args>
Duct(Args&&... args)
: impl(std::forward<Args>(args)...)
{ ; }
template <typename WhichDuct, typename... Args>
void EmplaceImpl(Args&&... args) {
impl.template emplace<WhichDuct>(std::forward<Args>(args)...);
}
bool TryPut(const T& val) {
return std::visit(
[&val](auto& arg) -> bool { return arg.TryPut(val); },
impl
);
}
template<typename P>
bool TryPut(P&& val) {
return std::visit(
[&val](auto& arg) -> bool { return arg.TryPut(std::forward<P>(val)); },
impl
);
}
bool TryFlush() {
return std::visit(
[](auto& arg) -> bool { return arg.TryFlush(); },
impl
);
}
const T& Get() const {
return std::visit(
[](auto& arg) -> const T& { return arg.Get(); },
impl
);
}
T& Get() {
return std::visit(
[](auto& arg) -> T& { return arg.Get(); },
impl
);
}
size_t TryConsumeGets(const size_t requested) {
return std::visit(
[requested](auto& arg) -> size_t {
return arg.TryConsumeGets(requested);
},
impl
);
}
std::string WhichImplIsActive() const {
return std::visit(
[](auto& arg) -> std::string { return arg.GetName(); },
impl
);
}
emp::optional<bool> HoldsIntraImpl() const {
if ( MaybeHoldsIntraImpl() ) {
return HoldsAmbiguousImpl() ? std::nullopt : emp::optional<bool>{ true };
} else return false;
}
emp::optional<bool> HoldsThreadImpl() const {
if ( MaybeHoldsThreadImpl() ) {
return HoldsAmbiguousImpl() ? std::nullopt : emp::optional<bool>{ true };
} else return false;
}
emp::optional<bool> HoldsProcImpl() const {
if ( MaybeHoldsProcImpl() ) {
return HoldsAmbiguousImpl() ? std::nullopt : emp::optional<bool>{ true };
} else return false;
}
uid_t GetUID() const { return reinterpret_cast<uid_t>(this); }
bool CanStep() const {
return std::visit(
[](const auto& arg) -> bool {
using impl_t = typename std::decay<decltype(arg)>::type;
if constexpr ( HasMemberFunction_CanStep<impl_t, bool()>::value ) {
return impl_t::CanStep();
} else return false;
},
impl
);
}
std::string ToString() const {
std::stringstream ss;
ss << uitsl::format_member(
"uitsl::get_proc_id()",
uitsl::get_proc_id()
) << std::endl;
ss << uitsl::format_member(
"GetUID()",
GetUID()
) << std::endl;
ss << uitsl::format_member(
"std::variant impl",
std::visit(
[](auto& arg) -> std::string { return arg.ToString(); },
impl
)
);
return ss.str();
}
};
} // namespace internal
} // namespace uit
#endif // #ifndef UIT_DUCTS_DUCT_HPP_INCLUDE