Program Listing for File poisson_queue.hpp
↰ Return to documentation for file (rcppsw/ds/poisson_queue.hpp
)
#pragma once
/*******************************************************************************
* Includes
******************************************************************************/
#include <boost/optional.hpp>
#include <deque>
#include "rcsw/common/fpc.h"
#include "rcppsw/math/rng.hpp"
#include "rcppsw/rcppsw.hpp"
#include "rcppsw/types/timestep.hpp"
/*******************************************************************************
* Namespaces/Decls
******************************************************************************/
namespace rcppsw::ds {
/*******************************************************************************
* Class Definitions
******************************************************************************/
template <typename T>
class poisson_queue {
public:
struct op_metadata {
size_t count{ 0 };
size_t total_count{ 0 };
types::timestep interval_accum{ 0 };
types::timestep total_interval_accum{ 0 };
};
poisson_queue(double lambda, double mu, math::rng* rng)
: mc_lambda(lambda), mc_mu(mu), m_rng(rng) {}
/* not assignable or copy-constructible by default */
poisson_queue(const poisson_queue&) = delete;
const poisson_queue& operator=(const poisson_queue&) = delete;
op_metadata enqueue_data(void) const { return m_enqueue.md; }
op_metadata dequeue_data(void) const { return m_dequeue.md; }
double lambda(void) const { return mc_lambda; }
double mu(void) const { return mc_mu; }
bool enqueue_check(const types::timestep& t) {
RCSW_FPC_NV(false, mc_lambda > 0.0);
if (!m_enqueue.op_set) {
double val = m_rng->exponential(mc_lambda);
m_enqueue.next_op_time = m_enqueue.last_op_time + static_cast<uint>(val);
m_enqueue.op_set = true;
}
return t >= m_enqueue.next_op_time;
}
bool dequeue_check(const types::timestep& t) {
RCSW_FPC_NV(false, mc_mu > 0.0);
if (!m_dequeue.op_set) {
double val = m_rng->exponential(mc_mu);
m_dequeue.next_op_time = m_dequeue.last_op_time + static_cast<uint>(val);
m_dequeue.op_set = true;
}
return t >= m_dequeue.next_op_time;
}
void enqueue(const T& item, const types::timestep& t) {
++m_enqueue.md.total_count;
++m_enqueue.md.count;
m_enqueue.md.interval_accum += types::timestep(t - m_enqueue.last_op_time);
m_enqueue.md.total_interval_accum +=
types::timestep(t - m_enqueue.last_op_time);
m_enqueue.last_op_time = t;
m_enqueue.op_set = false;
m_queue.push_back(item);
}
boost::optional<T> dequeue(const types::timestep& t, bool fake) {
++m_dequeue.md.count;
++m_dequeue.md.total_count;
m_dequeue.md.interval_accum += types::timestep(t - m_dequeue.last_op_time);
m_dequeue.md.total_interval_accum +=
types::timestep(t - m_dequeue.last_op_time);
m_dequeue.last_op_time = t;
m_dequeue.op_set = false;
if (fake || m_queue.empty()) {
return boost::none;
}
auto val = m_queue.front();
m_queue.pop_front();
return boost::make_optional(val);
}
void reset_metrics(void) {
m_enqueue.md.count = 0;
m_enqueue.md.interval_accum = types::timestep(0);
m_dequeue.md.count = 0;
m_dequeue.md.interval_accum = types::timestep(0);
}
bool contains(const T& key) const {
return m_queue.end() != std::find_if(m_queue.begin(),
m_queue.end(),
[&](const auto& a) { return a == key; });
}
private:
struct op_data {
struct op_metadata md;
bool op_set{ false };
types::timestep last_op_time{ 0 };
types::timestep next_op_time{ 0 };
};
/* clang-format off */
const double mc_lambda;
const double mc_mu;
math::rng* m_rng;
struct op_data m_enqueue{};
struct op_data m_dequeue{};
std::deque<T> m_queue{};
/* clang-format on */
public:
RCPPSW_WRAP_DECLDEF(size, m_queue, const);
RCPPSW_WRAP_DECLDEF(size, m_queue);
};
} /* namespace rcppsw::ds */