Program Listing for File Outlet.hpp¶
↰ Return to documentation for file (include/uit/spouts/Outlet.hpp)
#pragma once
#ifndef UIT_SPOUTS_OUTLET_HPP_INCLUDE
#define UIT_SPOUTS_OUTLET_HPP_INCLUDE
#include <cstdint>
#include <iostream>
#include <limits>
#include <memory>
#include <stddef.h>
#include <utility>
#include "../../../third-party/Empirical/source/base/optional.h"
#include "../../uitsl/debug/occupancy_audit.hpp"
#include "../../uitsl/nonce/CircularIndex.hpp"
#include "../../uitsl/parallel/thread_utils.hpp"
#include "../ducts/Duct.hpp"
namespace uit {
template<typename ImplSpec_>
class Outlet {
public:
using ImplSpec = ImplSpec_;
private:
using T = typename ImplSpec::T;
constexpr inline static size_t N{ImplSpec::N};
using index_t = uitsl::CircularIndex<N>;
using duct_t = internal::Duct<ImplSpec>;
std::shared_ptr<duct_t> duct;
// TODO move this to ImplSpec?
static_assert(N > 0);
mutable size_t read_count{0};
size_t revision_count{0};
size_t net_flux{0};
uitsl_occupancy_auditor;
size_t TryConsumeGets(const size_t n) {
uitsl_occupancy_audit(1);
return LogStep( duct->TryConsumeGets(n) );
}
size_t LogStep(const size_t n) {
revision_count += (n > 0);
net_flux += n;
return n;
}
void LogRead() const { ++read_count; }
public:
Outlet(
std::shared_ptr<duct_t> duct_
) : duct(duct_) { ; }
size_t TryStep(const size_t num_steps=1) {
return TryConsumeGets(num_steps);
}
size_t Jump() {
return TryConsumeGets( std::numeric_limits<size_t>::max() );
}
const T& Get() const { LogRead(); return duct->Get(); }
T& Get() { LogRead(); return duct->Get(); }
const T& JumpGet() {
uitsl_occupancy_audit(1);
Jump();
return Get();
}
const T& GetNext() {
uitsl_occupancy_audit(1);
while (TryStep() == 0);
return Get();
}
using optional_ref_t = emp::optional<std::reference_wrapper<const T>>;
optional_ref_t GetNextOrNullopt() {
uitsl_occupancy_audit(1);
return TryStep()
? optional_ref_t{ std::reference_wrapper{ Get() } }
: std::nullopt;
}
size_t GetReadCount() const { return read_count; }
size_t GetRevisionCount() const { return revision_count; }
size_t GetNetFlux() const { return net_flux; }
template <typename WhichDuct, typename... Args>
void EmplaceDuct(Args&&... args) {
duct->template EmplaceImpl<WhichDuct>(std::forward<Args>(args)...);
}
template <typename WhichDuct, typename... Args>
void SplitDuct(Args&&... args) {
duct = std::make_shared<duct_t>(
std::in_place_type_t<WhichDuct>{},
std::forward<Args>(args)...
);
}
typename duct_t::uid_t GetDuctUID() const { return duct->GetUID(); }
emp::optional<bool> HoldsIntraImpl() const { return duct->HoldsIntraImpl(); }
emp::optional<bool> HoldsThreadImpl() const {
return duct->HoldsThreadImpl();
}
emp::optional<bool> HoldsProcImpl() const { return duct->HoldsProcImpl(); }
bool CanStep() const { return duct->CanStep(); }
std::string ToString() const {
std::stringstream ss;
ss << uitsl::format_member("std::shared_ptr<duct_t> duct", *duct) << std::endl;
ss << uitsl::format_member("size_t read_count", read_count) << std::endl;
ss << uitsl::format_member("size_t revision_count", revision_count) << std::endl;
ss << uitsl::format_member("size_t net_flux", net_flux);
return ss.str();
}
};
} // namespace uit
#endif // #ifndef UIT_SPOUTS_OUTLET_HPP_INCLUDE