Even faster. Using internal MoveOnCopy struct-wrapper.

This commit is contained in:
KjellKod 2013-11-15 02:02:30 -07:00
parent 889145453d
commit c28593e87e
12 changed files with 314 additions and 316 deletions

View File

@ -27,6 +27,7 @@ namespace g2 {
}
LogMessageBuilder::~LogMessageBuilder() {
_message.get()->write().append(stream().str());
if (_message.get()->wasFatal()) {
FatalMessageBuilder trigger(_message, SIGABRT);
return; // FatalMessageBuilder will send to worker at scope exit
@ -41,7 +42,7 @@ namespace g2 {
}
std::ostringstream& LogMessageBuilder::stream() {
return _message.get()->stream();
return _stream;
}
void LogMessageBuilder::messageSave(const char *printf_like_message, ...) {
@ -72,7 +73,6 @@ namespace g2 {
FatalMessageBuilder:: FatalMessageBuilder(LogMessagePtr details, int signal_id)
//: _fatal_message(details), _fatal_signal(signal_id)
: _fatal_message(std2::make_unique<FatalMessage>(*(details._move_only.get()), signal_id))
{}

View File

@ -44,5 +44,6 @@ namespace g2 {
private:
LogMessagePtr _message;
std::ostringstream _stream;
};
} // g2

View File

@ -42,9 +42,9 @@ FileSink::~FileSink() {
exit_msg.append({"\nLog file at: ["}).append(_log_file_with_path).append({"]\n\n"});
std::cerr << exit_msg << std::flush;
}
void FileSink::fileWrite(std::shared_ptr<LogMessage> message) {
void FileSink::fileWrite(LogMessageMover message) {
std::ofstream& out(filestream());
out << message->toString() << std::flush;
out << message.get().toString() << std::flush;
}
std::string FileSink::changeLogFile(const std::string& directory) {

View File

@ -20,7 +20,7 @@ public:
FileSink(const std::string& log_prefix, const std::string& log_directory);
virtual ~FileSink();
void fileWrite(std::shared_ptr<LogMessage> message);
void fileWrite(LogMessageMover message);
std::string changeLogFile(const std::string& directory);
std::string fileName();

View File

@ -100,9 +100,10 @@ namespace g2 {
g_first_unintialized_msg = incoming.release();
std::string err = {"LOGGER NOT INITIALIZED:\n\t\t"};
err.append(g_first_unintialized_msg->message());
auto& stream = g_first_unintialized_msg->stream();
stream.str(err);
std::cerr << stream.str() << std::endl;
std::string& str = g_first_unintialized_msg->write();
str.clear();
str.append(err);
std::cerr << str << std::endl;
});
return;
}

View File

@ -79,7 +79,7 @@ namespace g2 {
std::string LogMessage::toString() const {
std::string LogMessage::toString() {
std::string out;
out.append("\n").append(timestamp()).append(".")
.append(microseconds()).append("\t")
@ -121,12 +121,12 @@ namespace g2 {
: _timestamp(g2::systemtime_now())
, _microseconds(microsecondsCounter())
, _file(splitFileName(file)), _line(line), _function(function), _level(level)
, _stream(std2::make_unique<std::ostringstream>()){}
{}
LogMessage::LogMessage(const std::string& fatalOsSignalCrashMessage)
: LogMessage({""}, 0, {""}, internal::FATAL_SIGNAL) {
stream() << fatalOsSignalCrashMessage;
_message.append(fatalOsSignalCrashMessage);
}
LogMessage::LogMessage(const LogMessage& other)
@ -137,8 +137,8 @@ namespace g2 {
, _function(other._function)
, _level(other._level)
, _expression(other._expression)
, _message(other._message)
{
stream().str(other.stream().str());
}
@ -150,7 +150,7 @@ namespace g2 {
, _function(std::move(other._function))
, _level(other._level)
, _expression(std::move(other._expression))
, _stream(std::move(other._stream)) {
, _message(std::move(other._message)) {
}
@ -176,10 +176,11 @@ namespace g2 {
// _level = other._level;
// _expression = std::move(other._expression);
// std::move(_stream, other._stream);
// return *this;
// }
//
//
//
FatalMessage::FatalMessage(const LogMessage& details, int signal_id)

View File

@ -30,16 +30,17 @@ namespace g2 {
std::string timestamp(const std::string& time_format = {internal::date_formatted + " " + internal::time_formatted}) const;
std::string microseconds() const { return std::to_string(_microseconds); }
std::string message() const { return stream().str(); }
std::string expression() const { return _expression; }
bool wasFatal() const { return internal::wasFatal(_level); }
std::string toString() const;
std::string message() const { return _message; }
std::string& write() const { return _message; }
std::string expression() { return _expression; }
bool wasFatal() { return internal::wasFatal(_level); }
std::ostringstream& stream() const { return *(_stream.get()); }
std::string toString();
void setExpression(const std::string expression) { _expression = expression; }
LogMessage(const std::string &file, const int line, const std::string& function, const LEVELS& level);
explicit LogMessage(const std::string& fatalOsSignalCrashMessage);
@ -60,7 +61,8 @@ namespace g2 {
std::string _function;
LEVELS _level;
std::string _expression; // only with content for CHECK(...) calls
std::unique_ptr<std::ostringstream> _stream;
//std::unique_ptr<std::ostringstream> _stream;
mutable std::string _message;
};
@ -83,4 +85,5 @@ namespace g2 {
typedef MoveOnCopy<std::unique_ptr<FatalMessage>> FatalMessagePtr;
typedef MoveOnCopy<std::unique_ptr<LogMessage>> LogMessagePtr;
typedef MoveOnCopy<LogMessage> LogMessageMover;
} // g2

View File

@ -35,37 +35,37 @@ struct LogWorkerImpl {
}
void bgSave(g2::LogMessagePtr msgPtr) {
std::shared_ptr<LogMessage> msg(msgPtr.get().release());
if (msg == nullptr) {
std::cerr << "ERROR NULLPTR" << std::endl;
return;
std::unique_ptr<LogMessage> uniqueMsg(std::move(msgPtr.get()));
}
for (auto& sink : _sinks) {
sink->send(msg);
LogMessage msg(*(uniqueMsg));
sink->send(LogMessageMover(std::move(msg)));
}
if (_sinks.empty()) {
std::string err_msg{"g2logworker has no sinks. Message: ["};
err_msg.append(msg->toString()).append({"]\n"});
err_msg.append(uniqueMsg.get()->toString()).append({"]\n"});
std::cerr << err_msg;
}
}
void bgFatal(FatalMessagePtr msgPtr) {
std::string signal = msgPtr.get()->signal();
std::shared_ptr<LogMessage> message(msgPtr.release()); // = msgPtr.get()->copyToLogMessage();
message->stream() << "\nExiting after fatal event (" << message->level()
<< "). Exiting with signal: " << signal
<< "\nLog content flushed flushed sucessfully to sink\n\n";
auto fatal_signal_id = msgPtr.get()->_signal_id;
std::cerr << message->message() << std::flush;
std::unique_ptr<LogMessage> uniqueMsg(std::move(msgPtr.get()));
uniqueMsg->write().append("\nExiting after fatal event (").append(uniqueMsg->level());
uniqueMsg->write().append("). Exiting with signal: ").append(signal)
.append("\nLog content flushed flushed sucessfully to sink\n\n");
std::cerr << uniqueMsg->message() << std::flush;
for (auto& sink : _sinks) {
sink->send(message);
LogMessage msg(*(uniqueMsg));
sink->send(LogMessageMover(std::move(msg)));
}
_sinks.clear(); // flush all queues
internal::exitWithDefaultSignalHandler(msgPtr.get()->_signal_id);
internal::exitWithDefaultSignalHandler(fatal_signal_id);
// should never reach this point
perror("g2log exited after receiving FATAL trigger. Flush message status: ");
}

View File

@ -18,7 +18,7 @@
namespace g2 {
namespace internal {
typedef std::function<void(std::shared_ptr<LogMessage>) > AsyncMessageCall;
typedef std::function<void(LogMessageMover) > AsyncMessageCall;
/// The asynchronous Sink has an active object, incoming requests for actions
// will be processed in the background by the specific object the Sink represents.
@ -51,14 +51,14 @@ struct Sink : public SinkWrapper {
_real_sink {sink},
_bg(kjellkod::Active::createActive()) {
auto adapter = std::bind(Call, _real_sink.get(), std::placeholders::_1);
_default_log_call = [ = ](std::shared_ptr<LogMessage> m){adapter(m->toString());};
_default_log_call = [ = ](LogMessageMover m){adapter(m.get().toString());};
}
virtual ~Sink() {
_bg.reset(); // TODO: to remove
}
void send(std::shared_ptr<LogMessage> msg) override {
void send(LogMessageMover msg) override {
_bg->send([this, msg] {
_default_log_call(msg);
});

View File

@ -15,7 +15,7 @@ namespace g2 {
struct SinkWrapper {
virtual ~SinkWrapper() { }
virtual void send(std::shared_ptr<LogMessage> msg) = 0;
virtual void send(LogMessageMover msg) = 0;
};
}
}

View File

@ -1,265 +1,259 @@
//#include <gtest/gtest.h>
//
//#include <memory>
//#include <string>
//#include <vector>
//#include <thread>
//#include <chrono>
//#include <atomic>
//
//#include "testing_helpers.h"
//#include "std2_make_unique.hpp"
//#include "g2sink.h"
//#include "g2sinkwrapper.h"
//#include "g2sinkhandle.h"
//#include "g2logmessage.hpp"
//
//
//using namespace std;
//using namespace std2;
//using namespace testing_helpers;
//
//class CoutSink {
// stringstream buffer;
// unique_ptr<ScopedOut> scope_ptr;
//
// CoutSink() : scope_ptr(std2::make_unique<ScopedOut>(std::cout, &buffer)) { }
//public:
//
// void clear() { buffer.str(""); }
// std::string string() { return buffer.str(); }
// void save(g2::LogMessage msg) {std::cout << msg.message();}
// virtual ~CoutSink() final { }
//
// static std::unique_ptr<CoutSink> createSink() {
// return std::unique_ptr<CoutSink>(new CoutSink);
// }
//};
//
//
//namespace {
// typedef std::shared_ptr<g2::internal::SinkWrapper> SinkWrapperPtr;
// typedef std::string LogEntry;
//}
//
//namespace g2 {
//
// class Worker {
// std::vector<SinkWrapperPtr> _container; // should be hidden in a pimple with a bg active object
// std::unique_ptr<kjellkod::Active> _bg;
//
// void bgSave(LogEntry msg) {
//// for (auto& sink : _container) {
//// g2::LogMessage message("test", 0, "test", DEBUG);
//// message.stream() << msg;
//// sink->send(message);
//// }
// }
//
// public:
//
// Worker() : _bg { kjellkod::Active::createActive() }
// {}
//
// ~Worker() {
// _bg->send([this] { _container.clear(); });
// }
//
// void save(LogEntry msg) {
// _bg->send([this, msg] {
// bgSave(msg); });
// } // will this be copied?
// //this is guaranteed to work std::bind(&Worker::bgSave, this, msg)); }
//
// template<typename T, typename DefaultLogCall>
// std::unique_ptr< SinkHandle<T> > addSink(std::unique_ptr<T> unique, DefaultLogCall call) {
//// auto shared = std::shared_ptr<T>(unique.release());
//// auto sink = std::make_shared < internal::Sink<T> > (shared, call);
//// auto add_sink_call = [this, sink] {
//// _container.push_back(sink);
//
// }
//// auto wait_result = g2::spawn_task(add_sink_call, _bg.get());
//// wait_result.wait();
//
// auto handle = std2::make_unique< SinkHandle<T> >(sink);
// return handle;
// }
// };
//
//} // g2
//
//
//
//using namespace g2;
//using namespace g2::internal;
//
//TEST(ConceptSink, CreateHandle) {
// Worker worker;
// auto handle = worker.addSink(CoutSink::createSink(), &CoutSink::save);
// ASSERT_NE(nullptr, handle.get());
//}
//
//TEST(ConceptSink, OneSink__VerifyMsgIn) {
// Worker worker;
// auto handle = worker.addSink(CoutSink::createSink(), &CoutSink::save);
// worker.save("Hello World!");
// std::this_thread::sleep_for(std::chrono::milliseconds(100));
// auto output = handle->call(&CoutSink::string);
// auto content = output.get();
// auto pos = content.find("Hello World!");
// ASSERT_NE(pos, std::string::npos);
//}
//
//struct StringSink {
// std::string raw;
//
// void append(g2::LogMessage entry) {
// raw.append(entry.message());
// }
//
// std::string string() {
// return raw;
// }
//};
//
//TEST(ConceptSink, DualSink__VerifyMsgIn) {
// Worker worker;
// auto h1 = worker.addSink(CoutSink::createSink(), &CoutSink::save);
// auto h2 = worker.addSink(std2::make_unique<StringSink>(), &StringSink::append);
// worker.save("Hello World!");
//
//
// std::this_thread::sleep_for(std::chrono::milliseconds(100));
// auto first = h1->call(&CoutSink::string);
// auto second = h2->call(&StringSink::string);
//
//
// ASSERT_EQ("Hello World!", first.get());
// ASSERT_EQ("Hello World!", second.get());
//}
//
//TEST(ConceptSink, DeletedSink__Exptect_badweak_ptr___exception) {
// auto worker = std2::make_unique<Worker>();
// auto h1 = worker->addSink(CoutSink::createSink(), &CoutSink::save);
// worker->save("Hello World!");
// worker.reset();
//
// auto first = h1->call(&CoutSink::string);
// EXPECT_THROW(first.get(), std::bad_weak_ptr);
//}
//
//namespace {
// typedef std::shared_ptr<std::atomic<bool>> AtomicBoolPtr;
// typedef std::shared_ptr<std::atomic<int>> AtomicIntPtr;
// typedef vector<AtomicBoolPtr> BoolList;
// typedef vector<AtomicIntPtr> IntVector;
//}
//TEST(ConceptSink, OneHundredSinks) {
// BoolList flags;
// IntVector counts;
//
// size_t NumberOfItems = 100;
// for(size_t index = 0; index < NumberOfItems; ++index) {
// flags.push_back(make_shared<atomic<bool>>(false));
// counts.push_back(make_shared<atomic<int>>(0));
// }
//
// {
// auto worker = std::unique_ptr<Worker>(new Worker);
// size_t index = 0;
// for(auto& flag: flags) {
// auto& count = counts[index++];
// // ignore the handle
// worker->addSink(std2::make_unique<ScopedSetTrue>(flag, count), &ScopedSetTrue::ReceiveMsg);
// }
// worker->save("Hello to 100 receivers :)");
// worker->save("Hello to 100 receivers :)");
// }
// // at the curly brace above the ScopedLogger will go out of scope and all the
// // 100 logging receivers will get their message to exit after all messages are
// // are processed
// size_t index = 0;
// for(auto& flag: flags) {
// auto& count = counts[index++];
// ASSERT_TRUE(flag->load()) << ", count : " << (index-1);
// ASSERT_TRUE(2 == count->load()) << ", count : " << (index-1);
// }
//
// cout << "test one hundred sinks is finished finished\n";
//}
//
//
///*
//TEST(Sink, OneSink) {
// AtomicBoolPtr flag = make_shared<atomic<bool>>(false);
// AtomicIntPtr count = make_shared<atomic<int>>(0);
// {
// auto worker = std::make_shared<g2LogWorker>();
// worker->addSink(std2::make_unique<ScopedSetTrue>(flag, count), &ScopedSetTrue::ReceiveMsg);
// worker->save("this message should trigger an atomic increment at the sink");
//
// EXPECT_FALSE(flag->load());
// EXPECT_TRUE(0 == count->load());
// }
// EXPECT_TRUE(flag->load());
// EXPECT_TRUE(1 == count->load());
//}
//
//TEST(Sink, OneSinkWithHandleOutOfScope) {
// AtomicBoolPtr flag = make_shared<atomic<bool>>(false);
// AtomicIntPtr count = make_shared<atomic<int>>(0);
// {
// auto worker = std::make_shared<g2LogWorker>();
// {
// auto handle = worker->addSink(std2::make_unique<ScopedSetTrue>(flag, count), &ScopedSetTrue::ReceiveMsg);
// }
// EXPECT_FALSE(flag->load());
// EXPECT_TRUE(0 == count->load());
// worker->save("this message should trigger an atomic increment at the sink");
// }
// EXPECT_TRUE(flag->load());
// EXPECT_TRUE(1 == count->load());
//}
//
////Perfect det här testet triggar felet
//
//typedef vector<AtomicBoolPtr> BoolPtrVector;
//typedef vector<AtomicIntPtr> IntPtrVector;
//TEST(Sink, OneHundredSinks) {
// BoolPtrVector flags;
// IntPtrVector counts;
//
// size_t NumberOfItems = 100;
// for (size_t index = 0; index < NumberOfItems; ++index) {
// flags.push_back(make_shared < atomic<bool >> (false));
// counts.push_back(make_shared < atomic<int >> (0));
// }
//
// {
// auto worker = std::make_shared<g2LogWorker>();
// size_t index = 0;
// for (auto& flag : flags) {
// auto& count = counts[index++];
// // ignore the handle
// worker->addSink(std2::make_unique<ScopedSetTrue>(flag, count), &ScopedSetTrue::ReceiveMsg);
// }
// worker->save("Hello to 100 receivers :)");
// }
//
// // at the curly brace above the ScopedLogger will go out of scope and all the
// // 100 logging receivers will get their message to exit after all messages are
// // are processed // at the curly brace above the ScopedLogger will go out of scope and all the
// // 100 logging receivers will get their message to exit after all messages are
// // are processed
// size_t index = 0;
// for (auto& flag : flags) {
// auto& count = counts[index++];
// EXPECT_TRUE(flag->load());
// EXPECT_EQ(100, count->load());
// cout << "test one hundred sinks is finished finished\n";
// }
//}
//
//*/
//
#include <gtest/gtest.h>
#include <memory>
#include <string>
#include <vector>
#include <thread>
#include <chrono>
#include <atomic>
#include "testing_helpers.h"
#include "std2_make_unique.hpp"
#include "g2sink.h"
#include "g2sinkwrapper.h"
#include "g2sinkhandle.h"
#include "g2logmessage.hpp"
using namespace std;
using namespace std2;
using namespace testing_helpers;
class CoutSink {
stringstream buffer;
unique_ptr<ScopedOut> scope_ptr;
CoutSink() : scope_ptr(std2::make_unique<ScopedOut>(std::cout, &buffer)) {}
public:
void clear() { buffer.str(""); }
std::string string() { return buffer.str(); }
void save(g2::LogMessageMover msg) { std::cout << msg.get().message(); }
virtual ~CoutSink() final {}
static std::unique_ptr<CoutSink> createSink() { return std::unique_ptr<CoutSink>(new CoutSink);}
};
struct StringSink {
std::string raw;
void append(g2::LogMessageMover entry) { raw.append(entry.get().message());}
std::string string() {
return raw;
}
};
namespace {
typedef std::shared_ptr<g2::internal::SinkWrapper> SinkWrapperPtr;
}
namespace g2 {
class Worker {
std::vector<SinkWrapperPtr> _container; // should be hidden in a pimple with a bg active object
std::unique_ptr<kjellkod::Active> _bg;
void bgSave(std::string msg) {
for (auto& sink : _container) {
g2::LogMessage message("test", 0, "test", DEBUG);
message.write().append(msg);
sink->send(LogMessageMover(std::move(message)));
}
}
public:
Worker() : _bg {
kjellkod::Active::createActive()
}
{
}
~Worker() {
_bg->send([this] {
_container.clear(); });
}
void save(std::string msg) {
_bg->send([this, msg] { bgSave(msg); });
}
template<typename T, typename DefaultLogCall>
std::unique_ptr< SinkHandle<T> > addSink(std::unique_ptr<T> unique, DefaultLogCall call) {
auto shared = std::shared_ptr<T>(unique.release());
auto sink = std::make_shared < internal::Sink<T> > (shared, call);
auto add_sink_call = [this, sink] { _container.push_back(sink); };
auto wait_result = g2::spawn_task(add_sink_call, _bg.get());
wait_result.wait();
auto handle = std2::make_unique< SinkHandle<T> >(sink);
return handle;
}
};
} // g2
using namespace g2;
using namespace g2::internal;
TEST(ConceptSink, CreateHandle) {
Worker worker;
auto handle = worker.addSink(CoutSink::createSink(), &CoutSink::save);
ASSERT_NE(nullptr, handle.get());
}
TEST(ConceptSink, OneSink__VerifyMsgIn) {
Worker worker;
auto handle = worker.addSink(CoutSink::createSink(), &CoutSink::save);
worker.save("Hello World!");
std::this_thread::sleep_for(std::chrono::milliseconds(100));
auto output = handle->call(&CoutSink::string);
auto content = output.get();
auto pos = content.find("Hello World!");
ASSERT_NE(pos, std::string::npos);
}
TEST(ConceptSink, DualSink__VerifyMsgIn) {
Worker worker;
auto h1 = worker.addSink(CoutSink::createSink(), &CoutSink::save);
auto h2 = worker.addSink(std2::make_unique<StringSink>(), &StringSink::append);
worker.save("Hello World!");
std::this_thread::sleep_for(std::chrono::milliseconds(100));
auto first = h1->call(&CoutSink::string);
auto second = h2->call(&StringSink::string);
ASSERT_EQ("Hello World!", first.get());
ASSERT_EQ("Hello World!", second.get());
}
TEST(ConceptSink, DeletedSink__Exptect_badweak_ptr___exception) {
auto worker = std2::make_unique<Worker>();
auto h1 = worker->addSink(CoutSink::createSink(), &CoutSink::save);
worker->save("Hello World!");
worker.reset();
auto first = h1->call(&CoutSink::string);
EXPECT_THROW(first.get(), std::bad_weak_ptr);
}
namespace {
typedef std::shared_ptr<std::atomic<bool >> AtomicBoolPtr;
typedef std::shared_ptr<std::atomic<int >> AtomicIntPtr;
typedef vector<AtomicBoolPtr> BoolList;
typedef vector<AtomicIntPtr> IntVector;
}
TEST(ConceptSink, OneHundredSinks) {
BoolList flags;
IntVector counts;
size_t NumberOfItems = 100;
for (size_t index = 0; index < NumberOfItems; ++index) {
flags.push_back(make_shared < atomic<bool >> (false));
counts.push_back(make_shared < atomic<int >> (0));
}
{
auto worker = std::unique_ptr<Worker>(new Worker);
size_t index = 0;
for (auto& flag : flags) {
auto& count = counts[index++];
// ignore the handle
worker->addSink(std2::make_unique<ScopedSetTrue>(flag, count), &ScopedSetTrue::ReceiveMsg);
}
worker->save("Hello to 100 receivers :)");
worker->save("Hello to 100 receivers :)");
}
// at the curly brace above the ScopedLogger will go out of scope and all the
// 100 logging receivers will get their message to exit after all messages are
// are processed
size_t index = 0;
for (auto& flag : flags) {
auto& count = counts[index++];
ASSERT_TRUE(flag->load()) << ", count : " << (index - 1);
ASSERT_TRUE(2 == count->load()) << ", count : " << (index - 1);
}
cout << "test one hundred sinks is finished finished\n";
}
/*
TEST(Sink, OneSink) {
AtomicBoolPtr flag = make_shared<atomic<bool>>(false);
AtomicIntPtr count = make_shared<atomic<int>>(0);
{
auto worker = std::make_shared<g2LogWorker>();
worker->addSink(std2::make_unique<ScopedSetTrue>(flag, count), &ScopedSetTrue::ReceiveMsg);
worker->save("this message should trigger an atomic increment at the sink");
EXPECT_FALSE(flag->load());
EXPECT_TRUE(0 == count->load());
}
EXPECT_TRUE(flag->load());
EXPECT_TRUE(1 == count->load());
}
TEST(Sink, OneSinkWithHandleOutOfScope) {
AtomicBoolPtr flag = make_shared<atomic<bool>>(false);
AtomicIntPtr count = make_shared<atomic<int>>(0);
{
auto worker = std::make_shared<g2LogWorker>();
{
auto handle = worker->addSink(std2::make_unique<ScopedSetTrue>(flag, count), &ScopedSetTrue::ReceiveMsg);
}
EXPECT_FALSE(flag->load());
EXPECT_TRUE(0 == count->load());
worker->save("this message should trigger an atomic increment at the sink");
}
EXPECT_TRUE(flag->load());
EXPECT_TRUE(1 == count->load());
}
//Perfect det här testet triggar felet
typedef vector<AtomicBoolPtr> BoolPtrVector;
typedef vector<AtomicIntPtr> IntPtrVector;
TEST(Sink, OneHundredSinks) {
BoolPtrVector flags;
IntPtrVector counts;
size_t NumberOfItems = 100;
for (size_t index = 0; index < NumberOfItems; ++index) {
flags.push_back(make_shared < atomic<bool >> (false));
counts.push_back(make_shared < atomic<int >> (0));
}
{
auto worker = std::make_shared<g2LogWorker>();
size_t index = 0;
for (auto& flag : flags) {
auto& count = counts[index++];
// ignore the handle
worker->addSink(std2::make_unique<ScopedSetTrue>(flag, count), &ScopedSetTrue::ReceiveMsg);
}
worker->save("Hello to 100 receivers :)");
}
// at the curly brace above the ScopedLogger will go out of scope and all the
// 100 logging receivers will get their message to exit after all messages are
// are processed // at the curly brace above the ScopedLogger will go out of scope and all the
// 100 logging receivers will get their message to exit after all messages are
// are processed
size_t index = 0;
for (auto& flag : flags) {
auto& count = counts[index++];
EXPECT_TRUE(flag->load());
EXPECT_EQ(100, count->load());
cout << "test one hundred sinks is finished finished\n";
}
}
*/

View File

@ -23,7 +23,7 @@ using namespace g2;
EXPECT_TRUE(0 == count->load());
//worker->save("this message should trigger an atomic increment at the sink");
LogMessagePtr message{std2::make_unique<LogMessage>("test", 0, "test", DEBUG)};
message.get()->stream() << "this message should trigger an atomic increment at the sink";
message.get()->write().append("this message should trigger an atomic increment at the sink");
worker->save(message);
}
EXPECT_TRUE(flag->load());
@ -61,15 +61,13 @@ TEST(ConceptSink, OneHundredSinks) {
LOG(DEBUG) << "start message";
LogMessagePtr message1{std2::make_unique<LogMessage>("test", 0, "test", DEBUG)};
LogMessagePtr message2{std2::make_unique<LogMessage>("test", 0, "test", DEBUG)};
auto& stream1 = message1.get()->stream();
stream1 << "Hello to 100 receivers :)";
auto& write1 = message1.get()->write();
write1.append("Hello to 100 receivers :)");
worker->save(message1);
auto& stream2 = message2.get()->stream();
stream2 << "Hello to 100 receivers :)";
auto& write2 = message2.get()->write();
write2.append("Hello to 100 receivers :)");
worker->save(message2);
//worker->save("Hello to 100 receivers :)");
//worker->save("Hello to 100 receivers :)");
LOG(INFO) << "end message";
}
// at the curly brace above the ScopedLogger will go out of scope and all the