Ditch boost.circular_buffer

It drags in a ton of crap, is kinda slow at runtime due to using
std::deque, and doesn't actually make the code much simpler than just
using a manual ring buffer.
This commit is contained in:
Thomas Goyne 2014-05-25 18:41:16 -07:00
parent 1f7c47239b
commit 6c685daf98
5 changed files with 71 additions and 72 deletions

View File

@ -44,9 +44,15 @@ LogSink::~LogSink() {
}
void LogSink::Log(SinkMessage const& sm) {
queue->Async([=]{
messages.push_back(sm);
for (auto& em : emitters) em->log(&messages.back());
queue->Async([=] {
if (messages.size() < 250)
messages.push_back(sm);
else {
messages[next_idx] = sm;
if (++next_idx == 250)
next_idx = 0;
}
for (auto& em : emitters) em->log(sm);
});
}
@ -67,7 +73,11 @@ void LogSink::Unsubscribe(Emitter *em) {
decltype(LogSink::messages) LogSink::GetMessages() const {
decltype(messages) ret;
queue->Sync([&] { ret = messages; });
queue->Sync([&] {
ret.reserve(messages.size());
ret.insert(ret.end(), messages.begin() + next_idx, messages.end());
ret.insert(ret.end(), messages.begin(), messages.begin() + next_idx);
});
return ret;
}
@ -93,16 +103,16 @@ JsonEmitter::JsonEmitter(fs::path const& directory)
{
}
void JsonEmitter::log(SinkMessage *sm) {
void JsonEmitter::log(SinkMessage const& sm) {
json::Object entry;
entry["sec"] = sm->time / 1000000000;
entry["usec"] = sm->time % 1000000000;
entry["severity"] = sm->severity;
entry["section"] = sm->section;
entry["file"] = sm->file;
entry["func"] = sm->func;
entry["line"] = sm->line;
entry["message"] = sm->message;
entry["sec"] = sm.time / 1000000000;
entry["usec"] = sm.time % 1000000000;
entry["severity"] = sm.severity;
entry["section"] = sm.section;
entry["file"] = sm.file;
entry["func"] = sm.func;
entry["line"] = sm.line;
entry["message"] = sm.message;
json::Writer::Write(entry, *fp);
fp->flush();
}

View File

@ -14,7 +14,6 @@
#include <libaegisub/fs_fwd.h>
#include <boost/circular_buffer.hpp>
#include <boost/interprocess/streams/bufferstream.hpp>
#include <cstdint>
#include <memory>
@ -70,7 +69,8 @@ class Emitter;
/// Log sink, single destination for all messages
class LogSink {
boost::circular_buffer<SinkMessage> messages{250};
std::vector<SinkMessage> messages;
size_t next_idx = 0;
std::unique_ptr<dispatch::Queue> queue;
/// List of pointers to emitters
@ -93,7 +93,7 @@ public:
/// @brief @get the complete (current) log.
/// @return Const pointer to internal sink.
decltype(messages) GetMessages() const;
std::vector<SinkMessage> GetMessages() const;
};
/// An emitter to produce human readable output for a log sink.
@ -103,7 +103,7 @@ public:
virtual ~Emitter() { }
/// Accept a single log entry
virtual void log(SinkMessage *sm)=0;
virtual void log(SinkMessage const& sm)=0;
};
/// A simple emitter which writes the log to a file in json format
@ -115,7 +115,7 @@ public:
/// @param directory Directory to write the log file in
JsonEmitter(fs::path const& directory);
void log(SinkMessage *) override;
void log(SinkMessage const&) override;
};
/// Generates a message and submits it to the log sink.
@ -133,7 +133,7 @@ public:
/// Emit log entries to stdout.
class EmitSTDOUT: public Emitter {
public:
void log(SinkMessage *sm) override;
void log(SinkMessage const& sm) override;
};
} // namespace log

View File

@ -19,23 +19,23 @@
#include <unistd.h>
namespace agi { namespace log {
void EmitSTDOUT::log(SinkMessage *sm) {
time_t time = sm->time / 1000000000;
void EmitSTDOUT::log(SinkMessage const& sm) {
time_t time = sm.time / 1000000000;
tm tmtime;
localtime_r(&time, &tmtime);
printf("%c %02d:%02d:%02d %-6ld <%-25s> [%s:%s:%d] %.*s\n",
Severity_ID[sm->severity],
printf("%c %02d:%02d:%02d %-9ld <%-25s> [%s:%s:%d] %.*s\n",
Severity_ID[sm.severity],
tmtime.tm_hour,
tmtime.tm_min,
tmtime.tm_sec,
(long)(sm->time % 1000000000),
sm->section,
sm->file,
sm->func,
sm->line,
(int)sm->message.size(),
sm->message.c_str());
(long)(sm.time % 1000000000),
sm.section,
sm.file,
sm.func,
sm.line,
(int)sm.message.size(),
sm.message.c_str());
if (!isatty(fileno(stdout)))
fflush(stdout);

View File

@ -12,14 +12,6 @@
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
/// @file log.cpp
/// @brief Windows logging
/// @ingroup libaegisub
#include <stdio.h>
#include <time.h>
#include <string.h>
#include "libaegisub/log.h"
#include "libaegisub/charset_conv_win.h"
@ -28,28 +20,25 @@
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
namespace agi {
namespace log {
void EmitSTDOUT::log(SinkMessage *sm) {
namespace agi { namespace log {
void EmitSTDOUT::log(SinkMessage const& sm) {
tm tmtime;
time_t time = sm->tv.tv_sec;
time_t time = sm.time / 1000000000;
localtime_s(&tmtime, &time);
char buff[65536];
_snprintf_s(buff, _TRUNCATE, "%s (%d): %c %02d:%02d:%02d %-6ld <%-25s> [%s] %.*s\n",
sm->file,
sm->line,
Severity_ID[sm->severity],
_snprintf_s(buff, _TRUNCATE, "%s (%d): %c %02d:%02d:%02d.%-3ld <%-25s> [%s] %.*s\n",
sm.file,
sm.line,
Severity_ID[sm.severity],
tmtime.tm_hour,
tmtime.tm_min,
tmtime.tm_sec,
sm->tv.tv_usec,
sm->section,
sm->func,
sm->message.size(),
sm->message.c_str());
(long)(sm.time % 1000000000 / 1000000),
sm.section,
sm.func,
(int)sm.message.size(),
sm.message.c_str());
OutputDebugStringW(charset::ConvertW(buff).c_str());
}
} // namespace log
} // namespace agi
} }

View File

@ -48,35 +48,35 @@ public:
EmitLog(wxTextCtrl *t)
: text_ctrl(t)
{
for (auto sm : agi::log::log->GetMessages())
log(&sm);
for (auto const& sm : agi::log::log->GetMessages())
log(sm);
}
void log(agi::log::SinkMessage *sm) override {
time_t time = sm->time / 1000000000;
void log(agi::log::SinkMessage const& sm) override {
time_t time = sm.time / 1000000000;
#ifndef _WIN32
tm tmtime;
localtime_r(&time, &tmtime);
auto log = wxString::Format("%c %02d:%02d:%02d %-6ld <%-25s> [%s:%s:%d] %s\n",
agi::log::Severity_ID[sm->severity],
agi::log::Severity_ID[sm.severity],
(int)tmtime.tm_hour,
(int)tmtime.tm_min,
(int)tmtime.tm_sec,
(long)(sm->time % 1000000000),
sm->section,
sm->file,
sm->func,
sm->line,
to_wx(sm->message));
(long)(sm.time % 1000000000),
sm.section,
sm.file,
sm.func,
sm.line,
to_wx(sm.message));
#else
auto log = wxString::Format("%c %-6ld <%-25s> [%s:%s:%d] %s\n",
agi::log::Severity_ID[sm->severity],
(long)(sm->time % 1000000000),
sm->section,
sm->file,
sm->func,
sm->line,
to_wx(sm->message));
agi::log::Severity_ID[sm.severity],
(long)(sm.time % 1000000000),
sm.section,
sm.file,
sm.func,
sm.line,
to_wx(sm.message));
#endif
if (wxIsMainThread())