Program Listing for File Buffer.cpp

Return to documentation for file (BackendAsyncmsg/Buffer.cpp)

#include "Buffer.hpp"

netio3::asyncmsg::BufferManager::BufferManager(const netio3::ConnectionParameters& params) :
  m_buffers{initBuffers(params)}, m_minNumAvailableBuffers{m_buffers.size()}

{
  for (const auto& [key, buffer] : m_buffers) {
    m_availableBuffers.push(key);
  }
}

[[nodiscard]] netio3::NetworkBuffer* netio3::asyncmsg::BufferManager::getBuffer()
{
  if (m_buffers.empty()) {
    throw TcpNoBuffers(ERS_HERE);
    return nullptr;
  }
  if (m_availableBuffers.empty()) {
    return nullptr;
  }
  auto key = decltype(m_availableBuffers)::value_type{};
  const auto success = m_availableBuffers.try_pop(key);
  if (not success) {
    return nullptr;
  }
  m_minNumAvailableBuffers.store(
    std::min(static_cast<std::size_t>(std::max(m_availableBuffers.size(), 0L)),
             m_minNumAvailableBuffers.load(std::memory_order_relaxed)),
    std::memory_order_relaxed);
  auto& buffer = m_buffers.at(key);
  return &buffer;
}

std::map<netio3::asyncmsg::Key, netio3::asyncmsg::Buffer>
netio3::asyncmsg::BufferManager::initBuffers(const ConnectionParameters& params)
{
  if (params.mr_start != nullptr) {
    return {};
  }
  std::map<Key, Buffer> buffers;
  std::generate_n(
    std::inserter(buffers, buffers.end()), params.num_buf, [&params, key = 0]() mutable {
      auto buffer = std::make_pair(key, Buffer(params.buf_size, key));
      ++key;
      return buffer;
    });
  return buffers;
}

void netio3::asyncmsg::BufferManager::returnBuffer(const netio3::NetworkBuffer* buffer)
{
  const auto* buf = dynamic_cast<const Buffer*>(buffer);
  if (buf == nullptr) {
    throw std::invalid_argument("BufferManager::returnBuffer: buffer is not of type Buffer");
  }
  m_availableBuffers.push(buf->getKey());
}

void netio3::asyncmsg::BufferManager::returnBuffer(Key key)
{
  m_availableBuffers.push(key);
}

std::size_t netio3::asyncmsg::BufferManager::getNumAvailableBuffers()
{
  return m_minNumAvailableBuffers.exchange(
    static_cast<std::size_t>(std::max(m_availableBuffers.size(), 0L)), std::memory_order_relaxed);
}