158 lines
3.6 KiB
C++
158 lines
3.6 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()
|
|
{
|
|
AuTryReserve(this->logBuffer_, this->maxCount_);
|
|
return true;
|
|
}
|
|
|
|
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::PreviewRingBuffer(AuConsumer<AuPair<const AuList<ConsoleMessage> &, AuUInt32>> callback)
|
|
{
|
|
if (!callback)
|
|
{
|
|
return;
|
|
}
|
|
|
|
AU_LOCK_GUARD(this->logMutex_);
|
|
callback(AuMakePair(AuConstReference(this->logBuffer_), this->index_));
|
|
}
|
|
|
|
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);
|
|
}
|
|
} |