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