Program Listing for File CachingInletWrapper.hpp

Return to documentation for file (include/uit/spouts/wrappers/inlet/CachingInletWrapper.hpp)

#pragma once
#ifndef UIT_SPOUTS_WRAPPERS_INLET_CACHINGINLETWRAPPER_HPP_INCLUDE
#define UIT_SPOUTS_WRAPPERS_INLET_CACHINGINLETWRAPPER_HPP_INCLUDE

#include <cstddef>
#include <utility>

#include "../../../../../third-party/Empirical/source/base/optional.h"
#include "../../../../../third-party/Empirical/source/tools/QueueCache.h"

#include "../../../../uitsl/distributed/CachePacket.hpp"

namespace uit {
namespace internal {

template<typename Inlet>
class CachingInletWrapper {

  size_t uid_stepper{ 1 };

  using ImplSpec = typename Inlet::ImplSpec;

  using inlet_t = Inlet;
  inlet_t inlet;

  using value_type = typename ImplSpec::value_type;

  emp::QueueCache<
    value_type,
    size_t,
    ImplSpec::SpoutCacheSize
  > cache;

  void DoProcPut(const value_type& val) {
    bool hit{ true };

    const size_t uid = cache.Get(
      val,
      [this, &hit](const auto& key){ hit = false; return uid_stepper++; }
    );

    if ( hit ) inlet.Put( uitsl::CachePacket<value_type>{ uid } );
    else inlet.Put( uitsl::CachePacket<value_type>{ uid, val } );
  }

  bool DoProcTryPut(const value_type& val) {
    bool hit{ true };

    const size_t uid = cache.Get(
      val,
      [this, &hit](const auto& key){ hit = false; return uid_stepper++; }
    );

    if ( hit ) return inlet.TryPut( uitsl::CachePacket<value_type>{ uid } );
    else {
      const bool res{
        inlet.TryPut( uitsl::CachePacket<value_type>{ uid, val } )
      };
      if ( !res ) cache.Delete( val );
      return res;
    }
  }

  template<typename P>
  bool DoProcTryPut(P&& val) {
    bool hit{ true };

    const size_t uid = cache.Get(
      val,
      [this, &hit](const auto& key){ hit = false; return uid_stepper++; }
    );

    if ( hit ) return inlet.TryPut( uitsl::CachePacket<value_type>{ uid } );
    else {
      const bool res{ inlet.TryPut(
        uitsl::CachePacket<value_type>{ uid, std::forward<P>(val) }
      ) };
      if ( !res ) cache.Delete( val );
      return res;
    }
  }

public:

  CachingInletWrapper(CachingInletWrapper& other) = default;

  CachingInletWrapper(const CachingInletWrapper& other) = default;

  CachingInletWrapper(CachingInletWrapper&& other) = default;

  template <typename... Args>
  CachingInletWrapper(Args&&... args)
  : inlet(std::forward<Args>(args)...)
  { ; }

  void Put(const value_type& val) {
    if ( HoldsProcImpl().value_or(true) ) DoProcPut( val );
    else inlet.Put( uitsl::CachePacket<value_type>{ 0, val } );
  }

  bool TryPut(const value_type& val) {
    if ( HoldsProcImpl().value_or(true) ) return DoProcTryPut( val );
    else return inlet.TryPut( uitsl::CachePacket<value_type>{ 0, val } );
  }

  template<typename P>
  bool TryPut(P&& val) {
    if ( HoldsProcImpl().value_or(true) ) return DoProcTryPut(
      std::forward<P>(val)
    );
    else return inlet.TryPut(
      uitsl::CachePacket<value_type>{ 0, std::forward<P>(val) }
    );

  }

  bool TryFlush() { return inlet.TryFlush(); }

  void Flush() { inlet.Flush(); }

  size_t GetSuccessfulPutCount() const { return inlet.GetSuccessfulPutCount(); }

  size_t GetBlockedPutCount() const { return inlet.GetBlockedPutCount(); }

  size_t GetDroppedPutCount() const { return inlet.GetDroppedPutCount(); }

  template<typename WhichDuct, typename... Args>
  void EmplaceDuct(Args&&... args) {
    inlet.template EmplaceDuct<WhichDuct>( std::forward<Args>(args)... );
  }

  template<typename WhichDuct, typename... Args>
  void SplitDuct(Args&&... args) {
    inlet.template SplitDuct<WhichDuct>( std::forward<Args>(args)... );
  }

  auto GetDuctUID() const { return inlet.GetUID(); }

  emp::optional<bool> HoldsIntraImpl() const { return inlet.HoldsIntraImpl(); }

  emp::optional<bool> HoldsThreadImpl() const {
    return inlet.HoldsThreadImpl();
  }

  emp::optional<bool> HoldsProcImpl() const { return inlet.HoldsProcImpl(); }

};

} // namespace internal
} // namesapce uit

#endif // #ifndef UIT_SPOUTS_WRAPPERS_INLET_CACHINGINLETWRAPPER_HPP_INCLUDE