Program Listing for File completion_table.cpp
↰ Return to documentation for file (completion_table.cpp
)
#include "completion_table.hpp"
#include "log.hpp"
#include <algorithm>
typedef enum
{
CT_OK,
CT_EMPTY,
CT_ERR,
} ct_return;
CompletionTable::CompletionTable() : m_rd(UINT32_MAX),
m_last_pushed_addr(0x0),
m_last_provided_addr(0x0),
m_current_table(&m_table_a),
m_wrap_table(&m_table_b)
{}
// When a chunk has been decoded
void CompletionTable::push(uint32_t addr)
{
if (addr >= m_rd || m_rd == UINT32_MAX)
{
(*m_current_table)[addr]++;
}
else
{
(*m_wrap_table)[addr]++;
}
m_last_pushed_addr = addr;
// swap tables if current is empty
if (m_current_table->empty() && !m_wrap_table->empty())
{
m_rd = m_wrap_table->begin()->first;
std::swap(m_current_table, m_wrap_table);
}
}
// When a completion object is read
int CompletionTable::update(uint32_t addr)
{
if (m_current_table->empty() && m_wrap_table->empty())
{
return CT_EMPTY;
}
m_last_provided_addr = m_rd;
if (m_rd <= addr || m_rd == UINT32_MAX)
{
auto it = m_current_table->find(addr);
if (it == m_current_table->end())
{
LOG_WARN("Completion object provided block addr 0x%x not in current table", addr);
return CT_ERR;
}
--(it->second);
if (it->second == 0)
{
if (it == m_current_table->begin())
{
m_rd = m_current_table->size() > 1 ? std::next(it, 1)->first : it->first;
}
m_current_table->erase(it);
}
}
else
{
auto it = m_wrap_table->find(addr);
if (it == m_wrap_table->end())
{
return CT_ERR;
}
--(it->second);
if (it->second == 0)
{
m_wrap_table->erase(it);
}
}
return CT_OK;
}
uint32_t CompletionTable::get_count(uint32_t addr) const
{
uint32_t count = 0;
if (m_rd <= addr || m_rd == UINT32_MAX)
{
if (m_current_table->count(addr) == 1)
{
count = m_current_table->at(addr);
}
}
else
{
if (m_wrap_table->count(addr) == 1)
{
count = m_wrap_table->at(addr);
}
}
return count;
}
uint32_t CompletionTable::get_rd() const
{
return m_rd;
}
size_t CompletionTable::get_entries() const
{
return (m_current_table->size() + m_wrap_table->size());
}
bool CompletionTable::is_empty() const
{
return (m_current_table->empty() and m_wrap_table->empty());
}
void CompletionTable::inspect() const
{
LOG_INFO("Completion table contains %lu entries", (m_current_table->size() + m_wrap_table->size()));
int printed{0}, max_printout{100};
for (auto &c : *m_current_table)
{
LOG_INFO("CT Block 0x%08x count %u", c.first, c.second);
++printed;
if (printed == max_printout)
{
break;
}
}
for (auto &w : *m_wrap_table)
{
LOG_INFO("WT Block 0x%08x count %u", w.first, w.second);
++printed;
if (printed == max_printout)
{
break;
}
}
}
uint32_t CompletionTable::get_previous_rd() const
{
return m_last_provided_addr;
}