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;
}