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 <optional>
#include <stddef.h>
#include <string>
#include <type_traits>
#include <utility>
#include <variant>
#include "../../uit_emp/meta/TypePack.hpp"
#include "../../uitsl/containers/safe/unordered_map.hpp"
#include "../../uitsl/math/math_utils.hpp"
#include "../../uitsl/meta/HasMemberFunction.hpp"
#include "../../uitsl/mpi/mpi_init_utils.hpp"
#include "../../uitsl/parallel/thread_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 uit_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;
}
using uid_t_ = std::uintptr_t;
using t_registry_t = uitsl::safe::unordered_map<uid_t_, uitsl::thread_id_t>;
inline static t_registry_t inlet_thread_registry;
inline static t_registry_t outlet_thread_registry;
using p_registry_t = uitsl::safe::unordered_map<uid_t_, uitsl::proc_id_t>;
inline static p_registry_t inlet_proc_registry;
inline static p_registry_t outlet_proc_registry;
using edge_id_registry_t = uitsl::safe::unordered_map<uid_t_, size_t>;
inline static edge_id_registry_t edge_id_registry;
using node_id_registry_t = uitsl::safe::unordered_map<uid_t_, size_t>;
inline static node_id_registry_t inlet_node_id_registry;
inline static node_id_registry_t outlet_node_id_registry;
using mesh_id_registry_t = uitsl::safe::unordered_map<uid_t_, size_t>;
inline static mesh_id_registry_t mesh_id_registry;
public:
using uid_t = uid_t_;
Duct(Duct& other) = delete;
Duct(const Duct& other) = delete;
Duct(Duct&& other) = delete;
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
);
}
std::optional<bool> HoldsIntraImpl() const {
if ( MaybeHoldsIntraImpl() ) {
return HoldsAmbiguousImpl() ? std::nullopt : std::optional<bool>{ true };
} else return false;
}
std::optional<bool> HoldsThreadImpl() const {
if ( MaybeHoldsThreadImpl() ) {
return HoldsAmbiguousImpl() ? std::nullopt : std::optional<bool>{ true };
} else return false;
}
std::optional<bool> HoldsProcImpl() const {
if ( MaybeHoldsProcImpl() ) {
return HoldsAmbiguousImpl() ? std::nullopt : std::optional<bool>{ true };
} else return false;
}
std::string WhichImplHeld() const {
if ( HoldsIntraImpl().value_or(false) ) return "intra";
else if ( HoldsThreadImpl().value_or(false) ) return "thread";
else if ( HoldsProcImpl().value_or(false) ) return "proc";
else return "ambiguous";
}
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 */ // removed to silence no return from non-void warning
return false;
},
impl
);
}
void RegisterInletProc(const uitsl::proc_id_t proc) const {
inlet_proc_registry[GetUID()] = proc;
}
void RegisterOutletProc(const uitsl::proc_id_t proc) const {
outlet_proc_registry[GetUID()] = proc;
}
void RegisterInletThread(const uitsl::thread_id_t thread) const {
inlet_thread_registry[GetUID()] = thread;
}
void RegisterOutletThread(const uitsl::thread_id_t thread) const {
outlet_thread_registry[GetUID()] = thread;
}
void RegisterEdgeID(const size_t edge_id) const {
edge_id_registry[GetUID()] = edge_id;
}
void RegisterInletNodeID(const size_t node_id) const {
inlet_node_id_registry[GetUID()] = node_id;
}
void RegisterOutletNodeID(const size_t node_id) const {
outlet_node_id_registry[GetUID()] = node_id;
}
void RegisterMeshID(const size_t mesh_id) const {
mesh_id_registry[GetUID()] = mesh_id;
}
std::optional<uitsl::proc_id_t> LookupInletProc() const {
return inlet_proc_registry.contains( GetUID() )
? std::optional<uitsl::proc_id_t>{ inlet_proc_registry.at( GetUID() ) }
: std::nullopt
;
}
std::optional<uitsl::proc_id_t> LookupOutletProc() const {
return outlet_proc_registry.contains( GetUID() )
? std::optional<uitsl::proc_id_t>{ outlet_proc_registry.at( GetUID() ) }
: std::nullopt
;
}
std::optional<uitsl::thread_id_t> LookupInletThread() const {
return inlet_thread_registry.contains( GetUID() )
? std::optional<uitsl::thread_id_t>{inlet_thread_registry.at( GetUID() )}
: std::nullopt
;
}
std::optional<uitsl::thread_id_t> LookupOutletThread() const {
return outlet_thread_registry.contains( GetUID() )
? std::optional<uitsl::thread_id_t>{outlet_thread_registry.at( GetUID() )}
: std::nullopt
;
}
std::optional<size_t> LookupEdgeID() const {
return edge_id_registry.contains( GetUID() )
? std::optional<size_t>{edge_id_registry.at( GetUID() )}
: std::nullopt
;
}
std::optional<size_t> LookupInletNodeID() const {
return inlet_node_id_registry.contains( GetUID() )
? std::optional<size_t>{inlet_node_id_registry.at(GetUID())}
: std::nullopt
;
}
std::optional<size_t> LookupOutletNodeID() const {
return outlet_node_id_registry.contains( GetUID() )
? std::optional<size_t>{outlet_node_id_registry.at(GetUID())}
: std::nullopt
;
}
std::optional<size_t> LookupMeshID() const {
return mesh_id_registry.contains( GetUID() )
? std::optional<size_t>{mesh_id_registry.at(GetUID())}
: std::nullopt
;
}
std::string ToString() const {
std::stringstream ss;
ss << uitsl::format_member(
"uitsl::get_proc_id()",
uitsl::get_proc_id()
) << '\n';
ss << uitsl::format_member(
"GetUID()",
GetUID()
) << '\n';
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