AuroraRuntime/Source/Logging/Sinks/RingBuffer.cpp
2022-03-31 04:40:19 +01:00

148 lines
3.4 KiB
C++

/***
Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: RingBuffer.cpp
Date: 2022-1-24
Author: Reece
***/
#include <Source/RuntimeInternal.hpp>
#include "RingBuffer.hpp"
namespace Aurora::Logging::Sinks
{
RingBufferSink::RingBufferSink(AuUInt32 count) : maxCount_(count)
{
}
bool RingBufferSink::Init()
{
this->logMutex_ = AuThreadPrimitives::MutexUnique();
this->logBuffer_.reserve(maxCount_);
return static_cast<bool>(this->logMutex_);
}
void RingBufferSink::OnMessageBlocking(AuUInt8 level, const ConsoleMessage &msg)
{}
bool RingBufferSink::OnMessageNonblocking(AuUInt8 level, const ConsoleMessage &msg)
{
bool drop {};
TryAddMsg(level, msg, drop);
return false;
}
bool RingBufferSink::TryAddMsg(AuUInt8 level, const ConsoleMessage &msg, bool &drop)
{
AU_LOCK_GUARD(this->logMutex_);
try
{
auto nextIndex = this->index_++;
if (this->logBuffer_.size() < this->maxCount_)
{
if (nextIndex >= this->logBuffer_.size())
{
return AuTryInsert(this->logBuffer_, msg);
}
}
this->logBuffer_[nextIndex % this->logBuffer_.size()] = msg;
}
catch (...)
{
return false;
}
return true;
}
void RingBufferSink::SaveToPath(const AuString &path, bool binary)
{
auto file = AuIOFS::OpenWriteUnique(path);
if (!file)
{
return;
}
for (const auto &message : Export())
{
if (binary)
{
AuByteBuffer buffer;
message.Write(buffer);
file->Write(AuMemoryViewRead(buffer));
}
else
{
file->Write(message.ToPersistentString());
file->Write(AuLocale::NewLine());
}
}
}
AuList<ConsoleMessage> RingBufferSink::Export()
{
AU_LOCK_GUARD(this->logMutex_);
AuList<ConsoleMessage> messages;
auto nextIndex = this->index_;
if (nextIndex >= this->logBuffer_.size())
{
auto nextIndex = (this->index_ + 1) % this->logBuffer_.size();
for (AU_ITERATE_N_TO_X(i, nextIndex, this->logBuffer_.size()))
{
messages.push_back(this->logBuffer_[i]);
}
for (AU_ITERATE_N_TO_X(i, 0, nextIndex))
{
messages.push_back(this->logBuffer_[i]);
}
}
else
{
for (AU_ITERATE_N_TO_X(i, 0, this->logBuffer_.size()))
{
messages.push_back(this->logBuffer_[i]);
}
}
return messages;
}
void RingBufferSink::OnFlush()
{
}
IBasicSinkRB *NewRingBufferNew(AuUInt32 maxLogEntries)
{
try
{
auto logger = _new RingBufferSink(maxLogEntries);
if (!logger)
{
return nullptr;
}
if (!logger->Init())
{
return nullptr;
}
return logger;
}
catch (...)
{
return {};
}
}
void NewRingBufferRelease(IBasicSink *logger)
{
AuSafeDelete<RingBufferSink *>(logger);
}
}