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) { void LogSink::Log(SinkMessage const& sm) {
queue->Async([=]{ queue->Async([=] {
messages.push_back(sm); if (messages.size() < 250)
for (auto& em : emitters) em->log(&messages.back()); 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(LogSink::messages) LogSink::GetMessages() const {
decltype(messages) ret; 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; 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; json::Object entry;
entry["sec"] = sm->time / 1000000000; entry["sec"] = sm.time / 1000000000;
entry["usec"] = sm->time % 1000000000; entry["usec"] = sm.time % 1000000000;
entry["severity"] = sm->severity; entry["severity"] = sm.severity;
entry["section"] = sm->section; entry["section"] = sm.section;
entry["file"] = sm->file; entry["file"] = sm.file;
entry["func"] = sm->func; entry["func"] = sm.func;
entry["line"] = sm->line; entry["line"] = sm.line;
entry["message"] = sm->message; entry["message"] = sm.message;
json::Writer::Write(entry, *fp); json::Writer::Write(entry, *fp);
fp->flush(); fp->flush();
} }

View File

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

View File

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

View File

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

View File

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