astyle
This commit is contained in:
		
							parent
							
								
									2f6a5eabe0
								
							
						
					
					
						commit
						c5a8eb5cdb
					
				
							
								
								
									
										3
									
								
								astyle.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										3
									
								
								astyle.sh
									
									
									
									
									
										Executable file
									
								
							| @ -0,0 +1,3 @@ | ||||
| #!/bin/bash | ||||
| find . -name "*\.h" -o -name "*\.cpp"|xargs astyle --style=stroustrup | ||||
| 
 | ||||
| @ -1,6 +1,6 @@ | ||||
| // test.cpp : Defines the entry point for the console application.
 | ||||
| // example.cpp : Simple logger example
 | ||||
| //
 | ||||
| #include "stdafx.h" | ||||
| #include <string> | ||||
| #include <functional> | ||||
| 
 | ||||
| #include "c11log/logger.h" | ||||
| @ -10,84 +10,63 @@ | ||||
| 
 | ||||
| #include "utils.h" | ||||
| 
 | ||||
| 
 | ||||
| std::atomic<uint64_t> push_count, pop_count; | ||||
| std::atomic<uint64_t> log_count; | ||||
| std::atomic<bool> active; | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| using std::string; | ||||
| using std::chrono::seconds; | ||||
| using Q = c11log::details::blocking_queue<string>; | ||||
| 
 | ||||
| void pusher(Q* ) | ||||
| void logging_thread() | ||||
| { | ||||
| 	auto &logger = c11log::get_logger("async"); | ||||
| 	while(active) | ||||
| 	{ | ||||
| 		logger.info()<<"Hello logger!"; | ||||
| 		++push_count; | ||||
| 	} | ||||
| 
 | ||||
|     auto &logger = c11log::get_logger("async"); | ||||
|     while(active) { | ||||
|         logger.info()<<"Hello logger!"; | ||||
|         ++log_count; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| void testq(int size, int pushers /*int poppers*/) | ||||
| void testlog(int threads) | ||||
| { | ||||
| 
 | ||||
| 	active = true; | ||||
| 	Q q{static_cast<Q::size_type>(size)}; | ||||
|     active = true; | ||||
| 
 | ||||
| 	/*
 | ||||
| 	for(int i = 0; i < poppers; i++) | ||||
| 		testq(qsize, pushers, poppers); | ||||
| 	*/ | ||||
| 	for(int i = 0; i < pushers; i++) | ||||
| 		new std::thread(std::bind(pusher, &q)); | ||||
|     for(int i = 0; i < threads; i++) | ||||
|         new std::thread(std::bind(logging_thread)); | ||||
| 
 | ||||
| 	while(active) | ||||
| 	{ | ||||
| 		using std::endl; | ||||
| 		using std::cout; | ||||
| 		using utils::format; | ||||
|     while(active) { | ||||
|         using std::endl; | ||||
|         using std::cout; | ||||
|         using utils::format; | ||||
| 
 | ||||
| 		push_count = 0; | ||||
| 		pop_count = 0; | ||||
| 		std::this_thread::sleep_for(seconds(1)); | ||||
| 		cout << "Pushes/sec =\t" << format(push_count.load()) << endl; | ||||
| 		//cout << "Pops/sec =\t" << format(pop_count.load()) << endl << endl;
 | ||||
| 		//cout << "Total/sec =\t" << format(push_count+pop_count) << endl;
 | ||||
| 		cout << "Queue size =\t" << format(q.size()) << endl; | ||||
| 		cout << "---------------------------------------------------------------------" << endl; | ||||
| 	} | ||||
|         log_count = 0; | ||||
|         std::this_thread::sleep_for(seconds(1)); | ||||
|         cout << "Logs/sec =\t" << format(log_count.load()) << endl; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| int main(int argc, char* argv[]) | ||||
| { | ||||
|     using namespace std::chrono; | ||||
| 
 | ||||
| 	if(argc !=4) | ||||
| 	{ | ||||
| 		std::cerr << "Usage: " << argv[0] << " qsize, pushers, poppers" << std::endl; | ||||
| 		return 0; | ||||
| 	} | ||||
| 	int qsize = atoi(argv[1]); | ||||
| 	int pushers = atoi(argv[2]); | ||||
|     if(argc !=3) { | ||||
|         std::cerr << "Usage: " << argv[0] << " qsize, threads" << std::endl; | ||||
|         return 0; | ||||
|     } | ||||
|     int qsize = atoi(argv[1]); | ||||
|     int threads = atoi(argv[2]); | ||||
| 
 | ||||
|     using namespace c11log::sinks; | ||||
|     auto null_sink = std::make_shared<null_sink>(); | ||||
|     auto stdout_sink = std::make_shared<stdout_sink>(); | ||||
|     auto async = std::make_shared<async_sink>(qsize); | ||||
|     auto fsink = std::make_shared<rotating_file_sink>("example_log", "txt", 1024*1024*50 , 5); | ||||
| 
 | ||||
| 	using namespace std::chrono; | ||||
|     async->add_sink(fsink); | ||||
| 
 | ||||
|     auto &logger = c11log::get_logger("async"); | ||||
|     logger.add_sink(async); | ||||
| 
 | ||||
|     auto null_sink = std::make_shared<c11log::sinks::null_sink>(); | ||||
|     auto stdout_sink = std::make_shared<c11log::sinks::stdout_sink>(); | ||||
|     auto async = std::make_shared<c11log::sinks::async_sink>(1000); | ||||
|     auto fsink = std::make_shared<c11log::sinks::rotating_file_sink>("log", "txt", 1024*1024*50 , 5); | ||||
|      | ||||
| 
 | ||||
| 	async->add_sink(fsink); | ||||
| 	auto &logger = c11log::get_logger("async"); | ||||
| 	logger.add_sink(async); | ||||
| 
 | ||||
|     testq(qsize, pushers); | ||||
|     testlog(threads); | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -7,8 +7,7 @@ | ||||
| #include <iomanip> | ||||
| #include <locale> | ||||
| 
 | ||||
| namespace utils | ||||
| { | ||||
| namespace utils { | ||||
| 
 | ||||
| template<typename T> | ||||
| std::string format(const T& value) | ||||
| @ -28,15 +27,13 @@ inline void bench(const std::string& fn_name, const std::chrono::milliseconds &d | ||||
|     seconds print_interval(1); | ||||
|     auto start_time = the_clock::now(); | ||||
|     auto lastPrintTime = start_time; | ||||
|     while (true) | ||||
|     { | ||||
|     while (true) { | ||||
|         fn(); | ||||
|         ++counter; | ||||
|         auto now = the_clock::now(); | ||||
|         if (now - start_time >= duration) | ||||
|             break; | ||||
|         if (now - lastPrintTime >= print_interval) | ||||
|         { | ||||
|         if (now - lastPrintTime >= print_interval) { | ||||
|             std::cout << fn_name << ": " << format(counter) << " per sec" << std::endl; | ||||
|             counter = 0; | ||||
|             lastPrintTime = the_clock::now(); | ||||
| @ -10,105 +10,102 @@ | ||||
| #include <mutex> | ||||
| #include <condition_variable> | ||||
| 
 | ||||
| namespace c11log | ||||
| { | ||||
| namespace details | ||||
| { | ||||
| namespace c11log { | ||||
| namespace details { | ||||
| 
 | ||||
| template<typename T> | ||||
| class blocking_queue | ||||
| { | ||||
| class blocking_queue { | ||||
| public: | ||||
| 	using queue_t = std::queue<T>; | ||||
| 	using size_type = typename queue_t::size_type; | ||||
| 	using clock = std::chrono::system_clock; | ||||
|     using queue_t = std::queue<T>; | ||||
|     using size_type = typename queue_t::size_type; | ||||
|     using clock = std::chrono::system_clock; | ||||
| 
 | ||||
| 	explicit blocking_queue(size_type max_size) : | ||||
| 		max_size_(max_size), | ||||
| 		q_(), | ||||
| 		mutex_() | ||||
| 		{} | ||||
| 	blocking_queue(const blocking_queue&) = delete; | ||||
| 	blocking_queue& operator=(const blocking_queue&) = delete; | ||||
| 	~blocking_queue() = default; | ||||
|     explicit blocking_queue(size_type max_size) : | ||||
|         max_size_(max_size), | ||||
|         q_(), | ||||
|         mutex_() { | ||||
|     } | ||||
|     blocking_queue(const blocking_queue&) = delete; | ||||
|     blocking_queue& operator=(const blocking_queue&) = delete; | ||||
|     ~blocking_queue() = default; | ||||
| 
 | ||||
| 	size_type size() { | ||||
| 		std::lock_guard<std::mutex> lock(mutex_); | ||||
| 		return q_.size(); | ||||
| 	} | ||||
|     size_type size() { | ||||
|         std::lock_guard<std::mutex> lock(mutex_); | ||||
|         return q_.size(); | ||||
|     } | ||||
| 
 | ||||
| 	// Push copy of item into the back of the queue.
 | ||||
| 	// If the queue is full, block the calling thread util there is room or timeout have passed.
 | ||||
| 	// Return: false on timeout, true on successful push.
 | ||||
| 	template<typename Duration_Rep, typename Duration_Period, typename TT> | ||||
| 	bool push(TT&& item, const std::chrono::duration<Duration_Rep, Duration_Period>& timeout) { | ||||
| 		std::unique_lock<std::mutex> ul(mutex_); | ||||
| 		if (q_.size() >= max_size_) { | ||||
| 			if (!item_popped_cond_.wait_until(ul, clock::now() + timeout, [this]() { | ||||
| 			return this->q_.size() < this->max_size_; | ||||
| 			})) | ||||
| 			return false; | ||||
| 		} | ||||
| 		q_.push(std::forward<TT>(item)); | ||||
| 		if (q_.size() <= 1) { | ||||
| 			ul.unlock(); //So the notified thread will have better chance to accuire the lock immediatly..
 | ||||
| 			item_pushed_cond_.notify_one(); | ||||
| 		} | ||||
| 		return true; | ||||
| 	} | ||||
|     // Push copy of item into the back of the queue.
 | ||||
|     // If the queue is full, block the calling thread util there is room or timeout have passed.
 | ||||
|     // Return: false on timeout, true on successful push.
 | ||||
|     template<typename Duration_Rep, typename Duration_Period, typename TT> | ||||
|     bool push(TT&& item, const std::chrono::duration<Duration_Rep, Duration_Period>& timeout) { | ||||
|         std::unique_lock<std::mutex> ul(mutex_); | ||||
|         if (q_.size() >= max_size_) { | ||||
|             if (!item_popped_cond_.wait_until(ul, clock::now() + timeout, [this]() { | ||||
|             return this->q_.size() < this->max_size_; | ||||
|             })) | ||||
|             return false; | ||||
|         } | ||||
|         q_.push(std::forward<TT>(item)); | ||||
|         if (q_.size() <= 1) { | ||||
|             ul.unlock(); //So the notified thread will have better chance to accuire the lock immediatly..
 | ||||
|             item_pushed_cond_.notify_one(); | ||||
|         } | ||||
|         return true; | ||||
|     } | ||||
| 
 | ||||
| 	// Push copy of item into the back of the queue.
 | ||||
| 	// If the queue is full, block the calling thread until there is room.
 | ||||
| 	template<typename TT> | ||||
| 	void push(TT&& item) { | ||||
| 		while (!push(std::forward<TT>(item), one_hour)); | ||||
| 	} | ||||
|     // Push copy of item into the back of the queue.
 | ||||
|     // If the queue is full, block the calling thread until there is room.
 | ||||
|     template<typename TT> | ||||
|     void push(TT&& item) { | ||||
|         while (!push(std::forward<TT>(item), one_hour)); | ||||
|     } | ||||
| 
 | ||||
| 	// Pop a copy of the front item in the queue into the given item ref.
 | ||||
| 	// If the queue is empty, block the calling thread util there is item to pop or timeout have passed.
 | ||||
| 	// Return: false on timeout , true on successful pop/
 | ||||
| 	template<class Duration_Rep, class Duration_Period> | ||||
| 	bool pop(T& item, const std::chrono::duration<Duration_Rep, Duration_Period>& timeout) { | ||||
| 		std::unique_lock<std::mutex> ul(mutex_); | ||||
| 		if (q_.empty()) { | ||||
| 			if (!item_pushed_cond_.wait_until(ul, clock::now() + timeout, [this]() { | ||||
| 			return !this->q_.empty(); | ||||
| 			})) | ||||
| 			return false; | ||||
| 		} | ||||
| 		item = std::move(q_.front()); | ||||
| 		q_.pop(); | ||||
| 		if (q_.size() >= max_size_ - 1) { | ||||
| 			ul.unlock(); //So the notified thread will have better chance to accuire the lock immediatly..
 | ||||
| 			item_popped_cond_.notify_one(); | ||||
| 		} | ||||
| 		return true; | ||||
| 	} | ||||
|     // Pop a copy of the front item in the queue into the given item ref.
 | ||||
|     // If the queue is empty, block the calling thread util there is item to pop or timeout have passed.
 | ||||
|     // Return: false on timeout , true on successful pop/
 | ||||
|     template<class Duration_Rep, class Duration_Period> | ||||
|     bool pop(T& item, const std::chrono::duration<Duration_Rep, Duration_Period>& timeout) { | ||||
|         std::unique_lock<std::mutex> ul(mutex_); | ||||
|         if (q_.empty()) { | ||||
|             if (!item_pushed_cond_.wait_until(ul, clock::now() + timeout, [this]() { | ||||
|             return !this->q_.empty(); | ||||
|             })) | ||||
|             return false; | ||||
|         } | ||||
|         item = std::move(q_.front()); | ||||
|         q_.pop(); | ||||
|         if (q_.size() >= max_size_ - 1) { | ||||
|             ul.unlock(); //So the notified thread will have better chance to accuire the lock immediatly..
 | ||||
|             item_popped_cond_.notify_one(); | ||||
|         } | ||||
|         return true; | ||||
|     } | ||||
| 
 | ||||
| 	// Pop a copy of the front item in the queue into the given item ref.
 | ||||
| 	// If the queue is empty, block the calling thread util there is item to pop.
 | ||||
| 	void pop(T& item) { | ||||
| 		while (!pop(item, one_hour)); | ||||
| 	} | ||||
|     // Pop a copy of the front item in the queue into the given item ref.
 | ||||
|     // If the queue is empty, block the calling thread util there is item to pop.
 | ||||
|     void pop(T& item) { | ||||
|         while (!pop(item, one_hour)); | ||||
|     } | ||||
| 
 | ||||
| 	// Clear the queue
 | ||||
| 	void clear() { | ||||
| 		{ | ||||
| 			std::unique_lock<std::mutex> ul(mutex_); | ||||
| 			queue_t().swap(q_); | ||||
| 		} | ||||
| 		item_popped_cond_.notify_all(); | ||||
| 	} | ||||
|     // Clear the queue
 | ||||
|     void clear() { | ||||
|         { | ||||
|             std::unique_lock<std::mutex> ul(mutex_); | ||||
|             queue_t().swap(q_); | ||||
|         } | ||||
|         item_popped_cond_.notify_all(); | ||||
|     } | ||||
| 
 | ||||
| private: | ||||
| 	size_type max_size_; | ||||
| 	std::queue<T> q_; | ||||
| 	std::mutex mutex_; | ||||
| 	std::condition_variable item_pushed_cond_; | ||||
| 	std::condition_variable item_popped_cond_; | ||||
| 	const std::chrono::hours one_hour { | ||||
| 		1 | ||||
| 	}; | ||||
|     size_type max_size_; | ||||
|     std::queue<T> q_; | ||||
|     std::mutex mutex_; | ||||
|     std::condition_variable item_pushed_cond_; | ||||
|     std::condition_variable item_popped_cond_; | ||||
|     const std::chrono::hours one_hour { | ||||
|         1 | ||||
|     }; | ||||
| }; | ||||
| 
 | ||||
| } | ||||
|  | ||||
| @ -24,20 +24,19 @@ private: | ||||
| 
 | ||||
| inline c11log::details::factory::logger_ptr c11log::details::factory::get_logger(const std::string &name) | ||||
| { | ||||
| 	std::lock_guard<std::mutex> lock(_loggers_mutex); | ||||
| 	auto found = _loggers.find(name); | ||||
| 	if (found == _loggers.end()) { | ||||
| 		auto new_logger_ptr = std::make_shared<c11log::logger>(name); | ||||
| 		_loggers.insert(std::make_pair(name, new_logger_ptr)); | ||||
| 		return new_logger_ptr; | ||||
| 	} | ||||
| 	else { | ||||
| 		return found->second; | ||||
| 	} | ||||
|     std::lock_guard<std::mutex> lock(_loggers_mutex); | ||||
|     auto found = _loggers.find(name); | ||||
|     if (found == _loggers.end()) { | ||||
|         auto new_logger_ptr = std::make_shared<c11log::logger>(name); | ||||
|         _loggers.insert(std::make_pair(name, new_logger_ptr)); | ||||
|         return new_logger_ptr; | ||||
|     } else { | ||||
|         return found->second; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| inline c11log::details::factory & c11log::details::factory::instance() | ||||
| { | ||||
| 	static c11log::details::factory instance; | ||||
| 	return instance; | ||||
|     static c11log::details::factory instance; | ||||
|     return instance; | ||||
| } | ||||
|  | ||||
| @ -2,80 +2,71 @@ | ||||
| 
 | ||||
| #include<streambuf> | ||||
| #include<string> | ||||
| namespace c11log | ||||
| { | ||||
| namespace details | ||||
| { | ||||
| namespace c11log { | ||||
| namespace details { | ||||
| 
 | ||||
| class str_devicebuf:public std::streambuf | ||||
| { | ||||
| class str_devicebuf:public std::streambuf { | ||||
| public: | ||||
| 	str_devicebuf() = default; | ||||
| 	~str_devicebuf() = default; | ||||
| 	str_devicebuf(const str_devicebuf& other):std::streambuf(),_str(other._str) {} | ||||
| 	str_devicebuf& operator=(const str_devicebuf other) | ||||
| 	{ | ||||
| 		if(this != &other) | ||||
| 			_str = other._str; | ||||
| 		return *this; | ||||
| 	} | ||||
|     str_devicebuf() = default; | ||||
|     ~str_devicebuf() = default; | ||||
|     str_devicebuf(const str_devicebuf& other):std::streambuf(),_str(other._str) {} | ||||
|     str_devicebuf& operator=(const str_devicebuf other) { | ||||
|         if(this != &other) | ||||
|             _str = other._str; | ||||
|         return *this; | ||||
|     } | ||||
| 
 | ||||
| 	const std::string& str_ref() const { | ||||
| 		return _str; | ||||
| 	} | ||||
|     const std::string& str_ref() const { | ||||
|         return _str; | ||||
|     } | ||||
| 
 | ||||
| 	void clear() { | ||||
| 		_str.clear(); | ||||
| 	} | ||||
|     void clear() { | ||||
|         _str.clear(); | ||||
|     } | ||||
| 
 | ||||
| protected: | ||||
| 	virtual int sync() override { | ||||
| 		return 0; | ||||
| 	} | ||||
|     virtual int sync() override { | ||||
|         return 0; | ||||
|     } | ||||
| 
 | ||||
| 	virtual std::streamsize xsputn(const char_type* s, std::streamsize count) override { | ||||
| 		_str.append(s, static_cast<unsigned int>(count)); | ||||
| 		return count; | ||||
| 	} | ||||
|     virtual std::streamsize xsputn(const char_type* s, std::streamsize count) override { | ||||
|         _str.append(s, static_cast<unsigned int>(count)); | ||||
|         return count; | ||||
|     } | ||||
| 
 | ||||
| 	virtual int_type overflow(int_type ch) override { | ||||
| 		if (ch != traits_type::eof()) | ||||
| 			_str.append((char*)&ch, 1); | ||||
| 		return 1; | ||||
| 	} | ||||
|     virtual int_type overflow(int_type ch) override { | ||||
|         if (ch != traits_type::eof()) | ||||
|             _str.append((char*)&ch, 1); | ||||
|         return 1; | ||||
|     } | ||||
| private: | ||||
| 	std::string _str; | ||||
|     std::string _str; | ||||
| }; | ||||
| 
 | ||||
| class fast_oss:public std::ostream | ||||
| { | ||||
| class fast_oss:public std::ostream { | ||||
| public: | ||||
| 	fast_oss():std::ostream(&_dev) {} | ||||
| 	~fast_oss() = default; | ||||
| 	fast_oss(const fast_oss& other):std::basic_ios<char>(), std::ostream(),_dev(other._dev) {} | ||||
| 	fast_oss& operator=(const fast_oss& other) | ||||
| 	{ | ||||
| 		if(&other != this) | ||||
| 			_dev = other._dev; | ||||
| 		return *this; | ||||
| 	} | ||||
|     fast_oss():std::ostream(&_dev) {} | ||||
|     ~fast_oss() = default; | ||||
|     fast_oss(const fast_oss& other):std::basic_ios<char>(), std::ostream(),_dev(other._dev) {} | ||||
|     fast_oss& operator=(const fast_oss& other) { | ||||
|         if(&other != this) | ||||
|             _dev = other._dev; | ||||
|         return *this; | ||||
|     } | ||||
| 
 | ||||
| 	const std::string& str_ref() const | ||||
| 	{ | ||||
| 		return _dev.str_ref(); | ||||
| 	} | ||||
|     const std::string& str_ref() const { | ||||
|         return _dev.str_ref(); | ||||
|     } | ||||
| 
 | ||||
| 	const std::string str() const | ||||
| 	{ | ||||
| 		return _dev.str_ref(); | ||||
| 	} | ||||
|     const std::string str() const { | ||||
|         return _dev.str_ref(); | ||||
|     } | ||||
| 
 | ||||
| 	void clear() | ||||
| 	{ | ||||
| 		_dev.clear(); | ||||
| 	} | ||||
|     void clear() { | ||||
|         _dev.clear(); | ||||
|     } | ||||
| private: | ||||
| 	str_devicebuf _dev; | ||||
|     str_devicebuf _dev; | ||||
| }; | ||||
| } | ||||
| } | ||||
|  | ||||
| @ -4,50 +4,47 @@ | ||||
| #include "../logger.h" | ||||
| #include "fast_oss.h" | ||||
| 
 | ||||
| namespace c11log | ||||
| { | ||||
| namespace c11log { | ||||
| class logger; | ||||
| namespace details | ||||
| { | ||||
| namespace details { | ||||
| 
 | ||||
| class line_logger | ||||
| { | ||||
| class line_logger { | ||||
| public: | ||||
| 	line_logger(logger* callback_logger, level::level_enum msg_level): | ||||
| 		_callback_logger(callback_logger), | ||||
| 		_oss(), | ||||
| 		_level(msg_level) { | ||||
| 		callback_logger->formatter_->format_header(callback_logger->logger_name_, | ||||
| 		        msg_level, | ||||
| 		        c11log::formatters::clock::now(), | ||||
| 		        _oss); | ||||
| 	} | ||||
| 	line_logger(logger*):_callback_logger(nullptr) {}; | ||||
| 	line_logger(const line_logger& other): | ||||
| 		_callback_logger(other._callback_logger), | ||||
| 		_oss(other._oss), | ||||
| 		_level(other._level) {}; | ||||
|     line_logger(logger* callback_logger, level::level_enum msg_level): | ||||
|         _callback_logger(callback_logger), | ||||
|         _oss(), | ||||
|         _level(msg_level) { | ||||
|         callback_logger->formatter_->format_header(callback_logger->logger_name_, | ||||
|                 msg_level, | ||||
|                 c11log::formatters::clock::now(), | ||||
|                 _oss); | ||||
|     } | ||||
|     line_logger(logger*):_callback_logger(nullptr) {}; | ||||
|     line_logger(const line_logger& other): | ||||
|         _callback_logger(other._callback_logger), | ||||
|         _oss(other._oss), | ||||
|         _level(other._level) {}; | ||||
| 
 | ||||
| 	line_logger& operator=(const line_logger&) = delete; | ||||
|     line_logger& operator=(const line_logger&) = delete; | ||||
| 
 | ||||
| 	~line_logger() { | ||||
| 		if (_callback_logger) { | ||||
| 			_oss << '\n'; | ||||
| 			_callback_logger->log_it_(_oss.str_ref()); | ||||
| 		} | ||||
| 	} | ||||
|     ~line_logger() { | ||||
|         if (_callback_logger) { | ||||
|             _oss << '\n'; | ||||
|             _callback_logger->log_it_(_oss.str_ref()); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| 	template<typename T> | ||||
| 	line_logger& operator<<(const T& msg) { | ||||
| 		if (_callback_logger) | ||||
| 			_oss << msg; | ||||
| 		return *this; | ||||
| 	} | ||||
|     template<typename T> | ||||
|     line_logger& operator<<(const T& msg) { | ||||
|         if (_callback_logger) | ||||
|             _oss << msg; | ||||
|         return *this; | ||||
|     } | ||||
| 
 | ||||
| private: | ||||
| 	logger* _callback_logger; | ||||
| 	details::fast_oss _oss; | ||||
| 	level::level_enum _level; | ||||
|     logger* _callback_logger; | ||||
|     details::fast_oss _oss; | ||||
|     level::level_enum _level; | ||||
| 
 | ||||
| }; | ||||
| } //Namespace details
 | ||||
|  | ||||
| @ -1,17 +1,15 @@ | ||||
| #pragma once | ||||
| 
 | ||||
| namespace c11log{ | ||||
| 	namespace details{ | ||||
| 		struct null_mutex | ||||
| 		{ | ||||
| 			void lock() | ||||
| 			{} | ||||
| 			void unlock() | ||||
| 			{} | ||||
| 			bool try_lock() | ||||
| 			{ | ||||
| 				return true; | ||||
| 			} | ||||
| 		}; | ||||
| 	} | ||||
| namespace c11log { | ||||
| namespace details { | ||||
| struct null_mutex { | ||||
|     void lock() { | ||||
|     } | ||||
|     void unlock() { | ||||
|     } | ||||
|     bool try_lock() { | ||||
|         return true; | ||||
|     } | ||||
| }; | ||||
| } | ||||
| } | ||||
| @ -3,17 +3,14 @@ | ||||
| #include<cstdio> | ||||
| #include<ctime> | ||||
| 
 | ||||
| namespace c11log | ||||
| { | ||||
| 	namespace details | ||||
| 	{ | ||||
| 		namespace os | ||||
| 		{			 | ||||
| 			std::tm localtime(const std::time_t &time_tt); | ||||
| 			std::tm localtime();  | ||||
| namespace c11log { | ||||
| namespace details { | ||||
| namespace os { | ||||
| std::tm localtime(const std::time_t &time_tt); | ||||
| std::tm localtime(); | ||||
| 
 | ||||
| 		}		 | ||||
| 	} | ||||
| } | ||||
| } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| @ -24,7 +21,7 @@ inline std::tm c11log::details::os::localtime(const std::time_t &time_tt) | ||||
| #ifdef _MSC_VER | ||||
|     localtime_s(&tm, &time_tt); | ||||
| #else | ||||
| 	localtime_r(&time_tt, &tm); | ||||
|     localtime_r(&time_tt, &tm); | ||||
| #endif | ||||
|     return tm; | ||||
| } | ||||
|  | ||||
| @ -28,13 +28,12 @@ public: | ||||
| class default_formatter: public formatter { | ||||
| public: | ||||
|     // Format: [2013-12-29 01:04:42.900] [logger_name:Info] Message body
 | ||||
|     void format_header(const std::string& logger_name, level::level_enum level, const time_point& tp, std::ostream& dest) override | ||||
|     { | ||||
|     void format_header(const std::string& logger_name, level::level_enum level, const time_point& tp, std::ostream& dest) override { | ||||
|         _format_time(tp, dest); | ||||
|         dest << " [" <<  logger_name << ":" << c11log::level::to_str(level) << "] "; | ||||
|     } | ||||
| private: | ||||
| 	void _format_time(const time_point& tp, std::ostream &dest); | ||||
|     void _format_time(const time_point& tp, std::ostream &dest); | ||||
| 
 | ||||
| }; | ||||
| } //namespace formatter
 | ||||
| @ -46,20 +45,19 @@ inline void c11log::formatters::default_formatter::_format_time(const time_point | ||||
| { | ||||
|     using namespace std::chrono; | ||||
| 
 | ||||
| 	static thread_local c11log::formatters::time_point last_tp; | ||||
| 	static thread_local char timestamp_cache[64]; | ||||
|     static thread_local c11log::formatters::time_point last_tp; | ||||
|     static thread_local char timestamp_cache[64]; | ||||
| 
 | ||||
| 
 | ||||
| 	if(duration_cast<milliseconds>(tp-last_tp).count() > 950) | ||||
|     { | ||||
|     	auto tm = details::os::localtime(clock::to_time_t(tp)); | ||||
| 		sprintf(timestamp_cache, "[%d-%02d-%02d %02d:%02d:%02d]", tm.tm_year + 1900, | ||||
| 			tm.tm_mon + 1, | ||||
| 			tm.tm_mday, | ||||
| 			tm.tm_hour, | ||||
| 			tm.tm_min, | ||||
| 			tm.tm_sec); | ||||
| 		last_tp = tp; | ||||
|     if(duration_cast<milliseconds>(tp-last_tp).count() > 950) { | ||||
|         auto tm = details::os::localtime(clock::to_time_t(tp)); | ||||
|         sprintf(timestamp_cache, "[%d-%02d-%02d %02d:%02d:%02d]", tm.tm_year + 1900, | ||||
|                 tm.tm_mon + 1, | ||||
|                 tm.tm_mday, | ||||
|                 tm.tm_hour, | ||||
|                 tm.tm_min, | ||||
|                 tm.tm_sec); | ||||
|         last_tp = tp; | ||||
|     } | ||||
| 	dest << timestamp_cache; | ||||
|     dest << timestamp_cache; | ||||
| } | ||||
|  | ||||
| @ -1,24 +1,21 @@ | ||||
| #pragma once | ||||
| 
 | ||||
| namespace c11log | ||||
| { | ||||
| 	namespace level | ||||
| 	{ | ||||
| 		typedef enum | ||||
| 		{ | ||||
| 			DEBUG, | ||||
| 			INFO, | ||||
| 			WARNING, | ||||
| 			ERROR, | ||||
| 			FATAL, | ||||
| 			NONE = 99 | ||||
| 		} level_enum; | ||||
| 		const char* to_str(level_enum l);				 | ||||
| 	} | ||||
| namespace c11log { | ||||
| namespace level { | ||||
| typedef enum { | ||||
|     DEBUG, | ||||
|     INFO, | ||||
|     WARNING, | ||||
|     ERROR, | ||||
|     FATAL, | ||||
|     NONE = 99 | ||||
| } level_enum; | ||||
| const char* to_str(level_enum l); | ||||
| } | ||||
| } | ||||
| 
 | ||||
| static const char* level_names[] { "Debug", "Info", "Warning", "Error", "Fatal" }; | ||||
| inline const char* c11log::level::to_str(c11log::level::level_enum l) | ||||
| { | ||||
| 	return level_names[l]; | ||||
|     return level_names[l]; | ||||
| } | ||||
| @ -2,45 +2,40 @@ | ||||
| #include <sstream> | ||||
| #include <iostream> | ||||
| 
 | ||||
| namespace c11log | ||||
| { | ||||
| 	class log_exception :public std::exception | ||||
| 	{ | ||||
| 	public: | ||||
| 		log_exception() : _oss(), _msg() | ||||
| 		{} | ||||
| namespace c11log { | ||||
| class log_exception :public std::exception { | ||||
| public: | ||||
|     log_exception() : _oss(), _msg() { | ||||
|     } | ||||
| 
 | ||||
| 		virtual ~log_exception() | ||||
| 		{} | ||||
|     virtual ~log_exception() { | ||||
|     } | ||||
| 
 | ||||
| 		explicit log_exception(const std::string& msg) :_oss(msg, std::ostringstream::ate), _msg(msg) | ||||
| 		{} | ||||
|     explicit log_exception(const std::string& msg) :_oss(msg, std::ostringstream::ate), _msg(msg) { | ||||
|     } | ||||
| 
 | ||||
| 		log_exception(const log_exception &other) :_oss(other._oss.str()), _msg(other._msg) | ||||
| 		{} | ||||
|     log_exception(const log_exception &other) :_oss(other._oss.str()), _msg(other._msg) { | ||||
|     } | ||||
| 
 | ||||
| 		log_exception& operator=(const log_exception& other) | ||||
| 		{ | ||||
| 			_oss.str(other._oss.str()); | ||||
| 			_msg = other._msg; | ||||
| 			return *this; | ||||
| 		} | ||||
|     log_exception& operator=(const log_exception& other) { | ||||
|         _oss.str(other._oss.str()); | ||||
|         _msg = other._msg; | ||||
|         return *this; | ||||
|     } | ||||
| 
 | ||||
| 		virtual const char* what() const throw () override | ||||
| 		{ | ||||
| 			return _msg.c_str(); | ||||
| 		} | ||||
|     virtual const char* what() const throw () override { | ||||
|         return _msg.c_str(); | ||||
|     } | ||||
| 
 | ||||
| 		template<typename T> | ||||
| 		log_exception& operator<<(const T& what) | ||||
| 		{ | ||||
| 			_oss << what; | ||||
| 			_msg = _oss.str(); | ||||
| 			return *this; | ||||
| 		} | ||||
|     template<typename T> | ||||
|     log_exception& operator<<(const T& what) { | ||||
|         _oss << what; | ||||
|         _msg = _oss.str(); | ||||
|         return *this; | ||||
|     } | ||||
| 
 | ||||
| 	private: | ||||
| 		std::ostringstream _oss; | ||||
| 		std::string _msg; | ||||
| 	}; | ||||
| private: | ||||
|     std::ostringstream _oss; | ||||
|     std::string _msg; | ||||
| }; | ||||
| } | ||||
| @ -12,156 +12,151 @@ | ||||
| #include "sinks/base_sink.h" | ||||
| #include "details/factory.h" | ||||
| 
 | ||||
| namespace c11log | ||||
| { | ||||
| namespace details | ||||
| { | ||||
| namespace c11log { | ||||
| namespace details { | ||||
| class line_logger; | ||||
| } | ||||
| 
 | ||||
| class logger | ||||
| { | ||||
| class logger { | ||||
| public: | ||||
| 
 | ||||
| 	typedef std::shared_ptr<sinks::base_sink>  sink_ptr_t; | ||||
| 	typedef std::vector<sink_ptr_t> sinks_vector_t; | ||||
|     typedef std::shared_ptr<sinks::base_sink>  sink_ptr_t; | ||||
|     typedef std::vector<sink_ptr_t> sinks_vector_t; | ||||
| 
 | ||||
| 	explicit logger(const std::string& name) : | ||||
| 		logger_name_(name), | ||||
| 		formatter_(std::make_unique<formatters::default_formatter>()), | ||||
| 		sinks_(), | ||||
| 		mutex_(), | ||||
| 		atomic_level_(level::INFO) | ||||
| 		{} | ||||
|     explicit logger(const std::string& name) : | ||||
|         logger_name_(name), | ||||
|         formatter_(new formatters::default_formatter()), | ||||
|         sinks_(), | ||||
|         mutex_(), | ||||
|         atomic_level_(level::INFO) { | ||||
|     } | ||||
| 
 | ||||
| 	~logger() = default; | ||||
|     ~logger() = default; | ||||
| 
 | ||||
| 	logger(const logger&) = delete; | ||||
| 	logger& operator=(const logger&) = delete; | ||||
|     logger(const logger&) = delete; | ||||
|     logger& operator=(const logger&) = delete; | ||||
| 
 | ||||
| 	void set_name(const std::string& name); | ||||
| 	const std::string& get_name(); | ||||
| 	void add_sink(sink_ptr_t sink_ptr); | ||||
| 	void remove_sink(sink_ptr_t sink_ptr); | ||||
| 	void set_formatter(std::unique_ptr<formatters::formatter> formatter); | ||||
| 	void set_level(c11log::level::level_enum level); | ||||
| 	c11log::level::level_enum get_level() const; | ||||
| 	bool should_log(c11log::level::level_enum level) const; | ||||
|     void set_name(const std::string& name); | ||||
|     const std::string& get_name(); | ||||
|     void add_sink(sink_ptr_t sink_ptr); | ||||
|     void remove_sink(sink_ptr_t sink_ptr); | ||||
|     void set_formatter(std::unique_ptr<formatters::formatter> formatter); | ||||
|     void set_level(c11log::level::level_enum level); | ||||
|     c11log::level::level_enum get_level() const; | ||||
|     bool should_log(c11log::level::level_enum level) const; | ||||
| 
 | ||||
| 	details::line_logger log(level::level_enum level); | ||||
| 	details::line_logger debug(); | ||||
| 	details::line_logger info(); | ||||
| 	details::line_logger warn(); | ||||
| 	details::line_logger error(); | ||||
| 	details::line_logger fatal(); | ||||
|     details::line_logger log(level::level_enum level); | ||||
|     details::line_logger debug(); | ||||
|     details::line_logger info(); | ||||
|     details::line_logger warn(); | ||||
|     details::line_logger error(); | ||||
|     details::line_logger fatal(); | ||||
| 
 | ||||
| private: | ||||
| 	friend details::line_logger; | ||||
|     friend details::line_logger; | ||||
| 
 | ||||
| 	std::string logger_name_ = ""; | ||||
| 	std::unique_ptr<c11log::formatters::formatter> formatter_; | ||||
| 	sinks_vector_t sinks_; | ||||
| 	std::mutex mutex_; | ||||
| 	std::atomic_int atomic_level_; | ||||
|     std::string logger_name_ = ""; | ||||
|     std::unique_ptr<c11log::formatters::formatter> formatter_; | ||||
|     sinks_vector_t sinks_; | ||||
|     std::mutex mutex_; | ||||
|     std::atomic_int atomic_level_; | ||||
| 
 | ||||
| 	void log_it_(const std::string& msg); | ||||
|     void log_it_(const std::string& msg); | ||||
| 
 | ||||
| }; | ||||
| 
 | ||||
| logger& get_logger(const std::string& name); | ||||
| } | ||||
| 
 | ||||
| #include "details/line_logger.h" | ||||
| //
 | ||||
| // Logger inline impl
 | ||||
| //
 | ||||
| #include "details/line_logger.h" | ||||
| inline c11log::details::line_logger c11log::logger::log(c11log::level::level_enum msg_level) | ||||
| { | ||||
| 
 | ||||
| 	if (msg_level >= atomic_level_) { | ||||
| 		return details::line_logger(this, msg_level); | ||||
| 	} else { | ||||
| 		return details::line_logger(nullptr); | ||||
| 	} | ||||
| 
 | ||||
|     if (msg_level >= atomic_level_) | ||||
|         return details::line_logger(this, msg_level); | ||||
|     else | ||||
|         return details::line_logger(nullptr); | ||||
| } | ||||
| 
 | ||||
| inline c11log::details::line_logger c11log::logger::debug() | ||||
| { | ||||
| 	return log(c11log::level::DEBUG); | ||||
|     return log(c11log::level::DEBUG); | ||||
| } | ||||
| inline c11log::details::line_logger c11log::logger::info() | ||||
| { | ||||
| 	return log(c11log::level::INFO); | ||||
|     return log(c11log::level::INFO); | ||||
| } | ||||
| inline c11log::details::line_logger c11log::logger::warn() | ||||
| { | ||||
| 	return log(c11log::level::WARNING); | ||||
|     return log(c11log::level::WARNING); | ||||
| } | ||||
| inline c11log::details::line_logger c11log::logger::error() | ||||
| { | ||||
| 	return log(level::ERROR); | ||||
|     return log(level::ERROR); | ||||
| } | ||||
| inline c11log::details::line_logger c11log::logger::fatal() | ||||
| { | ||||
| 	return log(c11log::level::FATAL); | ||||
|     return log(c11log::level::FATAL); | ||||
| } | ||||
| 
 | ||||
| inline void c11log::logger::set_name(const std::string& name) | ||||
| { | ||||
| 	std::lock_guard<std::mutex> lock(mutex_); | ||||
| 	logger_name_ = name; | ||||
|     std::lock_guard<std::mutex> lock(mutex_); | ||||
|     logger_name_ = name; | ||||
| } | ||||
| 
 | ||||
| inline const std::string& c11log::logger::get_name() | ||||
| { | ||||
| 	std::lock_guard<std::mutex> lock(mutex_); | ||||
| 	return logger_name_; | ||||
|     std::lock_guard<std::mutex> lock(mutex_); | ||||
|     return logger_name_; | ||||
| } | ||||
| 
 | ||||
| inline void c11log::logger::add_sink(sink_ptr_t sink_ptr) | ||||
| { | ||||
| 	std::lock_guard<std::mutex> lock(mutex_); | ||||
| 	sinks_.push_back(sink_ptr); | ||||
|     std::lock_guard<std::mutex> lock(mutex_); | ||||
|     sinks_.push_back(sink_ptr); | ||||
| } | ||||
| 
 | ||||
| inline void c11log::logger::remove_sink(sink_ptr_t sink_ptr) | ||||
| { | ||||
| 	std::lock_guard<std::mutex> lock(mutex_); | ||||
| 	sinks_.erase(std::remove(sinks_.begin(), sinks_.end(), sink_ptr), sinks_.end()); | ||||
|     std::lock_guard<std::mutex> lock(mutex_); | ||||
|     sinks_.erase(std::remove(sinks_.begin(), sinks_.end(), sink_ptr), sinks_.end()); | ||||
| } | ||||
| 
 | ||||
| inline void c11log::logger::set_formatter(std::unique_ptr<formatters::formatter> formatter) | ||||
| { | ||||
| 	std::lock_guard<std::mutex> lock(mutex_); | ||||
| 	formatter_ = std::move(formatter); | ||||
|     std::lock_guard<std::mutex> lock(mutex_); | ||||
|     formatter_ = std::move(formatter); | ||||
| } | ||||
| 
 | ||||
| inline void c11log::logger::set_level(c11log::level::level_enum level) | ||||
| { | ||||
| 	atomic_level_.store(level); | ||||
|     atomic_level_.store(level); | ||||
| } | ||||
| 
 | ||||
| inline c11log::level::level_enum c11log::logger::get_level() const | ||||
| { | ||||
| 	return static_cast<c11log::level::level_enum>(atomic_level_.load()); | ||||
|     return static_cast<c11log::level::level_enum>(atomic_level_.load()); | ||||
| } | ||||
| 
 | ||||
| inline bool c11log::logger::should_log(c11log::level::level_enum level) const | ||||
| { | ||||
| 	return level >= atomic_level_.load(); | ||||
|     return level >= atomic_level_.load(); | ||||
| } | ||||
| inline void c11log::logger::log_it_(const std::string& msg) | ||||
| { | ||||
| 	level::level_enum level = static_cast<level::level_enum>(atomic_level_.load()); | ||||
| 	std::lock_guard<std::mutex> lock(mutex_); | ||||
| 	for (auto &sink : sinks_) | ||||
| 		sink->log(msg, level); | ||||
|     level::level_enum level = static_cast<level::level_enum>(atomic_level_.load()); | ||||
|     std::lock_guard<std::mutex> lock(mutex_); | ||||
|     for (auto &sink : sinks_) | ||||
|         sink->log(msg, level); | ||||
| } | ||||
| 
 | ||||
| // Static factory function
 | ||||
| inline c11log::logger& c11log::get_logger(const std::string& name) | ||||
| { | ||||
| 	return *(c11log::details::factory::instance().get_logger(name)); | ||||
|     return *(c11log::details::factory::instance().get_logger(name)); | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -11,8 +11,7 @@ | ||||
| namespace c11log { | ||||
| namespace sinks { | ||||
| 
 | ||||
| class async_sink : public base_sink | ||||
| { | ||||
| class async_sink : public base_sink { | ||||
| public: | ||||
|     using size_type = c11log::details::blocking_queue<std::string>::size_type; | ||||
| 
 | ||||
| @ -45,9 +44,9 @@ private: | ||||
| ///////////////////////////////////////////////////////////////////////////////
 | ||||
| 
 | ||||
| inline c11log::sinks::async_sink::async_sink(const std::size_t max_queue_size) | ||||
| 	:sinks_(), | ||||
| 	active_(true), | ||||
|     q_(max_queue_size), | ||||
|     :sinks_(), | ||||
|      active_(true), | ||||
|      q_(max_queue_size), | ||||
|      back_thread_(&async_sink::thread_loop_, this) | ||||
| {} | ||||
| 
 | ||||
| @ -62,15 +61,12 @@ inline void c11log::sinks::async_sink::sink_it_(const std::string& msg) | ||||
| 
 | ||||
| inline void c11log::sinks::async_sink::thread_loop_() | ||||
| { | ||||
| 	constexpr auto pop_timeout = std::chrono::seconds(1); | ||||
|     constexpr auto pop_timeout = std::chrono::seconds(1); | ||||
|     std::string msg; | ||||
| 
 | ||||
|     while (active_) | ||||
|     { | ||||
|         if (q_.pop(msg, pop_timeout)) | ||||
|         { | ||||
|             for (auto &sink : sinks_) | ||||
|             { | ||||
|     while (active_) { | ||||
|         if (q_.pop(msg, pop_timeout)) { | ||||
|             for (auto &sink : sinks_) { | ||||
|                 sink->log(msg, static_cast<level::level_enum>(_level.load())); | ||||
|                 if (!active_) | ||||
|                     return; | ||||
| @ -93,8 +89,7 @@ inline void c11log::sinks::async_sink::remove_sink(logger::sink_ptr_t sink_ptr) | ||||
| inline void c11log::sinks::async_sink::shutdown(const std::chrono::seconds &timeout) | ||||
| { | ||||
|     auto until = std::chrono::system_clock::now() + timeout; | ||||
|     while (q_.size() > 0 && std::chrono::system_clock::now() < until) | ||||
|     { | ||||
|     while (q_.size() > 0 && std::chrono::system_clock::now() < until) { | ||||
|         std::this_thread::sleep_for(std::chrono::milliseconds(200)); | ||||
|     } | ||||
|     shutdown_(); | ||||
| @ -102,8 +97,7 @@ inline void c11log::sinks::async_sink::shutdown(const std::chrono::seconds &time | ||||
| 
 | ||||
| inline void c11log::sinks::async_sink::shutdown_() | ||||
| { | ||||
|     if(active_) | ||||
|     { | ||||
|     if(active_) { | ||||
|         active_ = false; | ||||
|         if (back_thread_.joinable()) | ||||
|             back_thread_.join(); | ||||
|  | ||||
| @ -11,34 +11,32 @@ namespace sinks { | ||||
| class base_sink { | ||||
| public: | ||||
|     base_sink() = default; | ||||
|     base_sink(level::level_enum l):_level(l) | ||||
|     {}; | ||||
|     base_sink(level::level_enum l):_level(l) { | ||||
|     }; | ||||
|     virtual ~base_sink() = default; | ||||
| 
 | ||||
|     base_sink(const base_sink&) = delete; | ||||
|     base_sink& operator=(const base_sink&) = delete; | ||||
| 
 | ||||
|     void log(const std::string &msg, level::level_enum level) | ||||
|     { | ||||
|     void log(const std::string &msg, level::level_enum level) { | ||||
|         if (level >= _level) { | ||||
|             sink_it_(msg); | ||||
|         } | ||||
|     }; | ||||
| 
 | ||||
|     void set_level(level::level_enum level) | ||||
|     { | ||||
|     void set_level(level::level_enum level) { | ||||
|         _level = level; | ||||
|     } | ||||
| 
 | ||||
| protected: | ||||
|     virtual void sink_it_(const std::string& msg) = 0; | ||||
|     std::atomic<int> _level{level::INFO}; | ||||
|     std::atomic<int> _level {level::INFO}; | ||||
| }; | ||||
| 
 | ||||
| class null_sink:public base_sink { | ||||
| protected: | ||||
|     void sink_it_(const std::string& ) override | ||||
|     {} | ||||
|     void sink_it_(const std::string& ) override { | ||||
|     } | ||||
| }; | ||||
| } | ||||
| } | ||||
|  | ||||
| @ -6,29 +6,26 @@ | ||||
| 
 | ||||
| #include "base_sink.h" | ||||
| 
 | ||||
| namespace c11log | ||||
| { | ||||
| namespace sinks | ||||
| { | ||||
| namespace c11log { | ||||
| namespace sinks { | ||||
| /*
 | ||||
| * Trivial file sink with single file as target | ||||
| */ | ||||
| class simple_file_sink : public base_sink | ||||
| { | ||||
| class simple_file_sink : public base_sink { | ||||
| public: | ||||
| 	explicit simple_file_sink(const std::string &filename, const std::string& extension = "txt") | ||||
| 		: mutex_(), | ||||
| 		  _ofstream(filename + "." + extension, std::ofstream::app) | ||||
| 	{} | ||||
|     explicit simple_file_sink(const std::string &filename, const std::string& extension = "txt") | ||||
|         : mutex_(), | ||||
|           _ofstream(filename + "." + extension, std::ofstream::app) { | ||||
|     } | ||||
| protected: | ||||
| 	void sink_it_(const std::string& msg) override { | ||||
| 		std::lock_guard<std::mutex> lock(mutex_); | ||||
| 		_ofstream << msg; | ||||
| 		_ofstream.flush(); | ||||
| 	} | ||||
|     void sink_it_(const std::string& msg) override { | ||||
|         std::lock_guard<std::mutex> lock(mutex_); | ||||
|         _ofstream << msg; | ||||
|         _ofstream.flush(); | ||||
|     } | ||||
| private: | ||||
| 	std::mutex mutex_; | ||||
| 	std::ofstream _ofstream; | ||||
|     std::mutex mutex_; | ||||
|     std::ofstream _ofstream; | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| @ -36,119 +33,117 @@ private: | ||||
| /*
 | ||||
|  * Thread safe, size limited file sink | ||||
| */ | ||||
| class rotating_file_sink : public base_sink | ||||
| { | ||||
| class rotating_file_sink : public base_sink { | ||||
| public: | ||||
| 	rotating_file_sink(const std::string &base_filename, const std::string &extension, size_t max_size, size_t max_files): | ||||
| 		_base_filename(base_filename), | ||||
| 		_extension(extension), | ||||
| 		_max_size(max_size), | ||||
| 		_max_files(max_files), | ||||
| 		_current_size(0), | ||||
| 		mutex_(), | ||||
| 		_ofstream(_calc_filename(_base_filename, 0, _extension)) | ||||
| 	{} | ||||
|     rotating_file_sink(const std::string &base_filename, const std::string &extension, size_t max_size, size_t max_files): | ||||
|         _base_filename(base_filename), | ||||
|         _extension(extension), | ||||
|         _max_size(max_size), | ||||
|         _max_files(max_files), | ||||
|         _current_size(0), | ||||
|         mutex_(), | ||||
|         _ofstream(_calc_filename(_base_filename, 0, _extension)) { | ||||
|     } | ||||
| 
 | ||||
| protected: | ||||
| 	void sink_it_(const std::string& msg) override { | ||||
| 		std::lock_guard<std::mutex> lock(mutex_); | ||||
| 		_current_size += msg.length(); | ||||
| 		if (_current_size  > _max_size) { | ||||
| 			_rotate(); | ||||
| 			_current_size = msg.length(); | ||||
| 		} | ||||
| 		_ofstream << msg; | ||||
| 		_ofstream.flush(); | ||||
| 	} | ||||
|     void sink_it_(const std::string& msg) override { | ||||
|         std::lock_guard<std::mutex> lock(mutex_); | ||||
|         _current_size += msg.length(); | ||||
|         if (_current_size  > _max_size) { | ||||
|             _rotate(); | ||||
|             _current_size = msg.length(); | ||||
|         } | ||||
|         _ofstream << msg; | ||||
|         _ofstream.flush(); | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
| private: | ||||
| 	static std::string _calc_filename(const std::string& filename, std::size_t index, const std::string& extension) { | ||||
| 		std::ostringstream oss; | ||||
| 		if (index) | ||||
| 			oss << filename << "." << index << "." << extension; | ||||
| 		else | ||||
| 			oss << filename << "." << extension; | ||||
| 		return oss.str(); | ||||
| 	} | ||||
|     static std::string _calc_filename(const std::string& filename, std::size_t index, const std::string& extension) { | ||||
|         std::ostringstream oss; | ||||
|         if (index) | ||||
|             oss << filename << "." << index << "." << extension; | ||||
|         else | ||||
|             oss << filename << "." << extension; | ||||
|         return oss.str(); | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
| 	// Rotate old files:
 | ||||
| 	// log.n-1.txt -> log.n.txt
 | ||||
| 	// log n-2.txt -> log.n-1.txt
 | ||||
| 	// ...
 | ||||
| 	// log.txt -> log.1.txt
 | ||||
| 	void _rotate() { | ||||
| 		_ofstream.close(); | ||||
| 		//Remove oldest file
 | ||||
| 		for (auto i = _max_files; i > 0; --i) { | ||||
| 			auto src = _calc_filename(_base_filename, i - 1, _extension); | ||||
| 			auto target = _calc_filename(_base_filename, i, _extension); | ||||
| 			if (i == _max_files) | ||||
| 				std::remove(target.c_str()); | ||||
| 			std::rename(src.c_str(), target.c_str()); | ||||
| 		} | ||||
| 		_ofstream.open(_calc_filename(_base_filename, 0, _extension)); | ||||
| 	} | ||||
| 	std::string _base_filename; | ||||
| 	std::string _extension; | ||||
| 	std::size_t _max_size; | ||||
| 	std::size_t _max_files; | ||||
| 	std::size_t _current_size; | ||||
| 	std::mutex mutex_; | ||||
| 	std::ofstream _ofstream; | ||||
|     // Rotate old files:
 | ||||
|     // log.n-1.txt -> log.n.txt
 | ||||
|     // log n-2.txt -> log.n-1.txt
 | ||||
|     // ...
 | ||||
|     // log.txt -> log.1.txt
 | ||||
|     void _rotate() { | ||||
|         _ofstream.close(); | ||||
|         //Remove oldest file
 | ||||
|         for (auto i = _max_files; i > 0; --i) { | ||||
|             auto src = _calc_filename(_base_filename, i - 1, _extension); | ||||
|             auto target = _calc_filename(_base_filename, i, _extension); | ||||
|             if (i == _max_files) | ||||
|                 std::remove(target.c_str()); | ||||
|             std::rename(src.c_str(), target.c_str()); | ||||
|         } | ||||
|         _ofstream.open(_calc_filename(_base_filename, 0, _extension)); | ||||
|     } | ||||
|     std::string _base_filename; | ||||
|     std::string _extension; | ||||
|     std::size_t _max_size; | ||||
|     std::size_t _max_files; | ||||
|     std::size_t _current_size; | ||||
|     std::mutex mutex_; | ||||
|     std::ofstream _ofstream; | ||||
| }; | ||||
| 
 | ||||
| /*
 | ||||
|  * Thread safe file sink that closes the log file at midnight and opens new one | ||||
|  */ | ||||
| class daily_file_sink:public base_sink | ||||
| { | ||||
| class daily_file_sink:public base_sink { | ||||
| public: | ||||
| 	explicit daily_file_sink(const std::string& base_filename, const std::string& extension = "txt"): | ||||
| 		_base_filename(base_filename), | ||||
| 		_extension(extension), | ||||
| 		_midnight_tp (_calc_midnight_tp() ), | ||||
| 		mutex_(), | ||||
| 		_ofstream(_calc_filename(_base_filename, _extension), std::ofstream::app) | ||||
| 	{} | ||||
|     explicit daily_file_sink(const std::string& base_filename, const std::string& extension = "txt"): | ||||
|         _base_filename(base_filename), | ||||
|         _extension(extension), | ||||
|         _midnight_tp (_calc_midnight_tp() ), | ||||
|         mutex_(), | ||||
|         _ofstream(_calc_filename(_base_filename, _extension), std::ofstream::app) { | ||||
|     } | ||||
| 
 | ||||
| protected: | ||||
| 	void sink_it_(const std::string& msg) override { | ||||
| 		std::lock_guard<std::mutex> lock(mutex_); | ||||
| 		if (std::chrono::system_clock::now() >= _midnight_tp) { | ||||
| 			_ofstream.close(); | ||||
| 			_ofstream.open(_calc_filename(_base_filename, _extension)); | ||||
| 			_midnight_tp = _calc_midnight_tp(); | ||||
| 		} | ||||
| 		_ofstream << msg; | ||||
| 		_ofstream.flush(); | ||||
| 	} | ||||
|     void sink_it_(const std::string& msg) override { | ||||
|         std::lock_guard<std::mutex> lock(mutex_); | ||||
|         if (std::chrono::system_clock::now() >= _midnight_tp) { | ||||
|             _ofstream.close(); | ||||
|             _ofstream.open(_calc_filename(_base_filename, _extension)); | ||||
|             _midnight_tp = _calc_midnight_tp(); | ||||
|         } | ||||
|         _ofstream << msg; | ||||
|         _ofstream.flush(); | ||||
|     } | ||||
| 
 | ||||
| private: | ||||
| 	// Return next midnight's time_point
 | ||||
| 	static std::chrono::system_clock::time_point _calc_midnight_tp() { | ||||
| 		using namespace std::chrono; | ||||
| 		auto now = system_clock::now(); | ||||
| 		time_t tnow = std::chrono::system_clock::to_time_t(now); | ||||
| 		tm date = c11log::details::os::localtime(tnow); | ||||
| 		date.tm_hour = date.tm_min = date.tm_sec = 0; | ||||
| 		auto midnight = std::chrono::system_clock::from_time_t(std::mktime(&date)); | ||||
| 		return system_clock::time_point(midnight + hours(24)); | ||||
| 	} | ||||
|     // Return next midnight's time_point
 | ||||
|     static std::chrono::system_clock::time_point _calc_midnight_tp() { | ||||
|         using namespace std::chrono; | ||||
|         auto now = system_clock::now(); | ||||
|         time_t tnow = std::chrono::system_clock::to_time_t(now); | ||||
|         tm date = c11log::details::os::localtime(tnow); | ||||
|         date.tm_hour = date.tm_min = date.tm_sec = 0; | ||||
|         auto midnight = std::chrono::system_clock::from_time_t(std::mktime(&date)); | ||||
|         return system_clock::time_point(midnight + hours(24)); | ||||
|     } | ||||
| 
 | ||||
| 	static std::string _calc_filename(const std::string& basename, const std::string& extension) { | ||||
| 		std::tm tm = c11log::details::os::localtime(); | ||||
| 		char buf[32]; | ||||
| 		sprintf(buf, ".%d-%02d-%02d.", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday); | ||||
| 		return basename+buf+extension; | ||||
| 	} | ||||
|     static std::string _calc_filename(const std::string& basename, const std::string& extension) { | ||||
|         std::tm tm = c11log::details::os::localtime(); | ||||
|         char buf[32]; | ||||
|         sprintf(buf, ".%d-%02d-%02d.", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday); | ||||
|         return basename+buf+extension; | ||||
|     } | ||||
| 
 | ||||
| 	std::string _base_filename; | ||||
| 	std::string _extension; | ||||
| 	std::chrono::system_clock::time_point _midnight_tp; | ||||
| 	std::mutex mutex_; | ||||
| 	std::ofstream _ofstream; | ||||
|     std::string _base_filename; | ||||
|     std::string _extension; | ||||
|     std::chrono::system_clock::time_point _midnight_tp; | ||||
|     std::mutex mutex_; | ||||
|     std::ofstream _ofstream; | ||||
| 
 | ||||
| }; | ||||
| } | ||||
|  | ||||
| @ -3,33 +3,27 @@ | ||||
| #include <iostream> | ||||
| #include "base_sink.h" | ||||
| 
 | ||||
| namespace c11log | ||||
| { | ||||
| namespace sinks | ||||
| { | ||||
| class ostream_sink: public base_sink | ||||
| { | ||||
| namespace c11log { | ||||
| namespace sinks { | ||||
| class ostream_sink: public base_sink { | ||||
| public: | ||||
| 	ostream_sink(std::ostream& os):_ostream(os) {} | ||||
|     ostream_sink(std::ostream& os):_ostream(os) {} | ||||
|     virtual ~ostream_sink() = default; | ||||
| 
 | ||||
| protected: | ||||
| 	virtual void sink_it_(const std::string& msg) override | ||||
| 	{ | ||||
| 		_ostream << msg; | ||||
| 	} | ||||
|     virtual void sink_it_(const std::string& msg) override { | ||||
|         _ostream << msg; | ||||
|     } | ||||
| 
 | ||||
| 	std::ostream& _ostream; | ||||
|     std::ostream& _ostream; | ||||
| }; | ||||
| 
 | ||||
| class stdout_sink:public ostream_sink | ||||
| { | ||||
| class stdout_sink:public ostream_sink { | ||||
| public: | ||||
|     stdout_sink():ostream_sink(std::cout) {} | ||||
| }; | ||||
| 
 | ||||
| class stderr_sink:public ostream_sink | ||||
| { | ||||
| class stderr_sink:public ostream_sink { | ||||
| public: | ||||
|     stderr_sink():ostream_sink(std::cerr) {} | ||||
| 
 | ||||
|  | ||||
| @ -1,28 +0,0 @@ | ||||
| // stdafx.h : include file for standard system include files,
 | ||||
| // or project specific include files that are used frequently, but
 | ||||
| // are changed infrequently
 | ||||
| //
 | ||||
| #pragma once | ||||
| 
 | ||||
| #ifdef _MSC_VER | ||||
| #include "targetver.h" | ||||
| #define WIN32_LEAN_AND_MEAN             // Exclude rarely-used stuff from Windows headers
 | ||||
| #endif | ||||
| 
 | ||||
| #include <string> | ||||
| #include <chrono> | ||||
| #include <ctime> | ||||
| #include <memory> | ||||
| #include <iostream> | ||||
| 
 | ||||
| 
 | ||||
| #ifndef _MSC_VER | ||||
| namespace std | ||||
| { | ||||
| template<typename T, typename ...Args> | ||||
| std::unique_ptr<T> make_unique( Args&& ...args ) | ||||
| { | ||||
|     return std::unique_ptr<T>( new T( std::forward<Args>(args)... ) ); | ||||
| } | ||||
| } | ||||
| #endif | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user