Устранена гонка за данными при инициализации очереди логгера

This commit is contained in:
selim 2014-08-28 22:20:38 +04:00
parent 966e729bf8
commit 86d129e335
6 changed files with 51 additions and 15 deletions

View File

@ -10,8 +10,8 @@ OS = linux
# C++ compier # C++ compier
CXX = g++ CXX = g++
CXXFLAGS = -MMD -c -g -Og -Wall -Werror -std=c++11 -Iinclude -Isrc/asm/include CXXFLAGS = -MMD -c -g -Og -Wall -Werror -std=c++11 -Iinclude -Isrc/asm/include #-fsanitize=thread -fPIE
LDFLAGS = -lgtest LDFLAGS = -lgtest #-ltsan -pie
# Archiver # Archiver
AR = ar AR = ar

View File

@ -6,14 +6,16 @@
#include <mutex> #include <mutex>
#include <condition_variable> #include <condition_variable>
#include <functional> #include <functional>
#include <atomic>
class log_queue class log_queue
{ {
private: private:
std::thread _worker;
std::mutex _mutex; std::mutex _mutex;
std::condition_variable _cond; std::condition_variable _cond;
std::queue<std::function<void()>> _queue; std::queue<std::function<void()>> _queue;
std::atomic<bool> _working;
std::thread _worker;
private: private:
void worker_func(); void worker_func();

View File

@ -19,16 +19,16 @@ private:
public: public:
logger(); logger();
void set_enabled(bool enabled) void set_enabled(bool enabled);
{
_enabled = enabled;
}
template<typename... Args> void log(const char* s, const Args&... args) template<typename... Args> void log(const char* s, const Args&... args)
{ {
std::cout << "step 1" << std::endl;
if(_enabled) if(_enabled)
{ {
_queue.add_log([this, s, &args...] { std::cout << "step 2" << std::endl;
_queue.add_log([this, s, args...] {
std::cout << "step 3" << std::endl;
_logLine.str(""); _logLine.str("");
log_internal(s, args...); log_internal(s, args...);
}); });

View File

@ -1,12 +1,17 @@
#include "log_queue.h" #include "log_queue.h"
#include <iostream> #include <iostream>
log_queue::log_queue(): _worker(&log_queue::worker_func, this) log_queue::log_queue(): _working(true), _worker(&log_queue::worker_func, this)
{ {
} }
log_queue::~log_queue() log_queue::~log_queue()
{ {
std::unique_lock<std::mutex> lock(_mutex);
_queue.push([]{});
_working = false;
_cond.notify_one();
lock.unlock();
_worker.join(); _worker.join();
} }
@ -18,6 +23,10 @@ void log_queue::worker_func()
_cond.wait(lock, [this] { return !_queue.empty(); }); _cond.wait(lock, [this] { return !_queue.empty(); });
std::function<void()> func = _queue.front(); std::function<void()> func = _queue.front();
_queue.pop(); _queue.pop();
if(_queue.empty() && !_working)
return;
lock.unlock(); lock.unlock();
func(); func();

View File

@ -8,6 +8,11 @@ logger::logger(): _enabled(true)
{ {
} }
void logger::set_enabled(bool enabled)
{
_enabled = enabled;
}
void logger::log_internal(const char *s) void logger::log_internal(const char *s)
{ {
while (*s) while (*s)

View File

@ -561,18 +561,38 @@ TEST(Ustring, replace_string)
EXPECT_TRUE(str2 == "33 hello 33 world 33 more 33 and 33 more 33"); EXPECT_TRUE(str2 == "33 hello 33 world 33 more 33 and 33 more 33");
} }
void func(std::size_t n)
{
for(std::size_t j = 0; j < 100; ++j)
{
ulog.log("thread %, line %", n, j);
}
std::cout << "end of thread " << n << std::endl;
}
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
//::testing::InitGoogleTest(&argc, argv); //::testing::InitGoogleTest(&argc, argv);
//return RUN_ALL_TESTS(); //return RUN_ALL_TESTS();
int one = 1; const std::size_t threadsCount = 2;
double two = 2.5; //int one = 1;
ulog.log("one: %, two: %", one, two); //double two = 2.5;
ulog.log("Hello world!"); //ulog.log("one: %, two: %", one, two);
//ulog.log("Hello world!");
//ulog.log("some string: %", "qwe!");
int i = 0; std::thread threads[threadsCount];
std::cin >> i; for(std::size_t i = 0; i < threadsCount; ++i)
{
threads[i] = std::thread(func, i);
}
std::cout << "the end" << std::endl;
for(std::size_t i = 0; i < threadsCount; ++i)
threads[i].join();
return 0; return 0;
} }