Commit a2653d40 authored by gabime's avatar gabime

clang-format

parent 461b5ef2
...@@ -3,18 +3,18 @@ ...@@ -3,18 +3,18 @@
// Distributed under the MIT License (http://opensource.org/licenses/MIT) // Distributed under the MIT License (http://opensource.org/licenses/MIT)
// //
#include <atomic>
#include <thread> #include <thread>
#include <vector> #include <vector>
#include <atomic>
#include <boost/log/core.hpp> #include <boost/log/core.hpp>
#include <boost/log/trivial.hpp>
#include <boost/log/expressions.hpp> #include <boost/log/expressions.hpp>
#include <boost/log/sinks/text_file_backend.hpp> #include <boost/log/sinks/text_file_backend.hpp>
#include <boost/log/utility/setup/file.hpp>
#include <boost/log/utility/setup/common_attributes.hpp>
#include <boost/log/sources/severity_logger.hpp>
#include <boost/log/sources/record_ostream.hpp> #include <boost/log/sources/record_ostream.hpp>
#include <boost/log/sources/severity_logger.hpp>
#include <boost/log/trivial.hpp>
#include <boost/log/utility/setup/common_attributes.hpp>
#include <boost/log/utility/setup/file.hpp>
namespace logging = boost::log; namespace logging = boost::log;
namespace src = boost::log::sources; namespace src = boost::log::sources;
...@@ -23,62 +23,49 @@ namespace keywords = boost::log::keywords; ...@@ -23,62 +23,49 @@ namespace keywords = boost::log::keywords;
void init() void init()
{ {
logging::add_file_log logging::add_file_log(keywords::file_name = "logs/boost-sample_%N.log", /*< file name pattern >*/
( keywords::auto_flush = false, keywords::format = "[%TimeStamp%]: %Message%");
keywords::file_name = "logs/boost-sample_%N.log", /*< file name pattern >*/
keywords::auto_flush = false,
keywords::format = "[%TimeStamp%]: %Message%"
);
logging::core::get()->set_filter logging::core::get()->set_filter(logging::trivial::severity >= logging::trivial::info);
(
logging::trivial::severity >= logging::trivial::info
);
} }
using namespace std; using namespace std;
int main(int argc, char* argv[]) int main(int argc, char *argv[])
{ {
int thread_count = 10; int thread_count = 10;
if(argc > 1) if (argc > 1)
thread_count = atoi(argv[1]); thread_count = atoi(argv[1]);
int howmany = 1000000; int howmany = 1000000;
init(); init();
logging::add_common_attributes(); logging::add_common_attributes();
using namespace logging::trivial; using namespace logging::trivial;
src::severity_logger_mt< severity_level > lg; src::severity_logger_mt<severity_level> lg;
std::atomic<int > msg_counter {0}; std::atomic<int> msg_counter{0};
vector<thread> threads; vector<thread> threads;
for (int t = 0; t < thread_count; ++t) for (int t = 0; t < thread_count; ++t)
{ {
threads.push_back(std::thread([&]() threads.push_back(std::thread([&]() {
{
while (true) while (true)
{ {
int counter = ++msg_counter; int counter = ++msg_counter;
if (counter > howmany) break; if (counter > howmany)
break;
BOOST_LOG_SEV(lg, info) << "boost message #" << counter << ": This is some text for your pleasure"; BOOST_LOG_SEV(lg, info) << "boost message #" << counter << ": This is some text for your pleasure";
} }
})); }));
} }
for (auto &t : threads)
for(auto &t:threads)
{ {
t.join(); t.join();
}; };
return 0; return 0;
} }
...@@ -3,13 +3,13 @@ ...@@ -3,13 +3,13 @@
// Distributed under the MIT License (http://opensource.org/licenses/MIT) // Distributed under the MIT License (http://opensource.org/licenses/MIT)
// //
#include <boost/log/core.hpp> #include <boost/log/core.hpp>
#include <boost/log/trivial.hpp>
#include <boost/log/expressions.hpp> #include <boost/log/expressions.hpp>
#include <boost/log/sinks/text_file_backend.hpp> #include <boost/log/sinks/text_file_backend.hpp>
#include <boost/log/utility/setup/file.hpp>
#include <boost/log/utility/setup/common_attributes.hpp>
#include <boost/log/sources/severity_logger.hpp>
#include <boost/log/sources/record_ostream.hpp> #include <boost/log/sources/record_ostream.hpp>
#include <boost/log/sources/severity_logger.hpp>
#include <boost/log/trivial.hpp>
#include <boost/log/utility/setup/common_attributes.hpp>
#include <boost/log/utility/setup/file.hpp>
namespace logging = boost::log; namespace logging = boost::log;
namespace src = boost::log::sources; namespace src = boost::log::sources;
...@@ -18,29 +18,21 @@ namespace keywords = boost::log::keywords; ...@@ -18,29 +18,21 @@ namespace keywords = boost::log::keywords;
void init() void init()
{ {
logging::add_file_log logging::add_file_log(keywords::file_name = "logs/boost-sample_%N.log", /*< file name pattern >*/
( keywords::auto_flush = false, keywords::format = "[%TimeStamp%]: %Message%");
keywords::file_name = "logs/boost-sample_%N.log", /*< file name pattern >*/
keywords::auto_flush = false,
keywords::format = "[%TimeStamp%]: %Message%"
);
logging::core::get()->set_filter logging::core::get()->set_filter(logging::trivial::severity >= logging::trivial::info);
(
logging::trivial::severity >= logging::trivial::info
);
} }
int main(int argc, char *[])
int main(int argc, char* [])
{ {
int howmany = 1000000; int howmany = 1000000;
init(); init();
logging::add_common_attributes(); logging::add_common_attributes();
using namespace logging::trivial; using namespace logging::trivial;
src::severity_logger_mt< severity_level > lg; src::severity_logger_mt<severity_level> lg;
for(int i = 0 ; i < howmany; ++i) for (int i = 0; i < howmany; ++i)
BOOST_LOG_SEV(lg, info) << "boost message #" << i << ": This is some text for your pleasure"; BOOST_LOG_SEV(lg, info) << "boost message #" << i << ": This is some text for your pleasure";
return 0; return 0;
......
...@@ -3,9 +3,9 @@ ...@@ -3,9 +3,9 @@
// Distributed under the MIT License (http://opensource.org/licenses/MIT) // Distributed under the MIT License (http://opensource.org/licenses/MIT)
// //
#include <atomic>
#include <thread> #include <thread>
#include <vector> #include <vector>
#include <atomic>
#define _ELPP_THREAD_SAFE #define _ELPP_THREAD_SAFE
#include "easylogging++.h" #include "easylogging++.h"
...@@ -13,11 +13,11 @@ _INITIALIZE_EASYLOGGINGPP ...@@ -13,11 +13,11 @@ _INITIALIZE_EASYLOGGINGPP
using namespace std; using namespace std;
int main(int argc, char* argv[]) int main(int argc, char *argv[])
{ {
int thread_count = 10; int thread_count = 10;
if(argc > 1) if (argc > 1)
thread_count = atoi(argv[1]); thread_count = atoi(argv[1]);
int howmany = 1000000; int howmany = 1000000;
...@@ -26,24 +26,23 @@ int main(int argc, char* argv[]) ...@@ -26,24 +26,23 @@ int main(int argc, char* argv[])
el::Configurations conf("easyl.conf"); el::Configurations conf("easyl.conf");
el::Loggers::reconfigureLogger("default", conf); el::Loggers::reconfigureLogger("default", conf);
std::atomic<int > msg_counter {0}; std::atomic<int> msg_counter{0};
vector<thread> threads; vector<thread> threads;
for (int t = 0; t < thread_count; ++t) for (int t = 0; t < thread_count; ++t)
{ {
threads.push_back(std::thread([&]() threads.push_back(std::thread([&]() {
{
while (true) while (true)
{ {
int counter = ++msg_counter; int counter = ++msg_counter;
if (counter > howmany) break; if (counter > howmany)
break;
LOG(INFO) << "easylog message #" << counter << ": This is some text for your pleasure"; LOG(INFO) << "easylog message #" << counter << ": This is some text for your pleasure";
} }
})); }));
} }
for (auto &t : threads)
for(auto &t:threads)
{ {
t.join(); t.join();
}; };
......
...@@ -3,12 +3,11 @@ ...@@ -3,12 +3,11 @@
// Distributed under the MIT License (http://opensource.org/licenses/MIT) // Distributed under the MIT License (http://opensource.org/licenses/MIT)
// //
#include "easylogging++.h" #include "easylogging++.h"
_INITIALIZE_EASYLOGGINGPP _INITIALIZE_EASYLOGGINGPP
int main(int, char* []) int main(int, char *[])
{ {
int howmany = 1000000; int howmany = 1000000;
...@@ -16,7 +15,7 @@ int main(int, char* []) ...@@ -16,7 +15,7 @@ int main(int, char* [])
el::Configurations conf("easyl.conf"); el::Configurations conf("easyl.conf");
el::Loggers::reconfigureLogger("default", conf); el::Loggers::reconfigureLogger("default", conf);
for(int i = 0 ; i < howmany; ++i) for (int i = 0; i < howmany; ++i)
LOG(INFO) << "easylog message #" << i << ": This is some text for your pleasure"; LOG(INFO) << "easylog message #" << i << ": This is some text for your pleasure";
return 0; return 0;
} }
...@@ -3,57 +3,55 @@ ...@@ -3,57 +3,55 @@
// Distributed under the MIT License (http://opensource.org/licenses/MIT) // Distributed under the MIT License (http://opensource.org/licenses/MIT)
// //
#include <thread>
#include <vector>
#include <atomic> #include <atomic>
#include <iostream>
#include <chrono> #include <chrono>
#include <iostream>
#include <thread>
#include <vector>
#include "g2logworker.h"
#include "g2log.h" #include "g2log.h"
#include "g2logworker.h"
using namespace std; using namespace std;
template<typename T> std::string format(const T& value); template <typename T> std::string format(const T &value);
int main(int argc, char* argv[]) int main(int argc, char *argv[])
{ {
using namespace std::chrono; using namespace std::chrono;
using clock=steady_clock; using clock = steady_clock;
int thread_count = 10; int thread_count = 10;
if(argc > 1) if (argc > 1)
thread_count = atoi(argv[1]); thread_count = atoi(argv[1]);
int howmany = 1000000; int howmany = 1000000;
g2LogWorker g2log(argv[0], "logs"); g2LogWorker g2log(argv[0], "logs");
g2::initializeLogging(&g2log); g2::initializeLogging(&g2log);
std::atomic<int> msg_counter{0};
std::atomic<int > msg_counter {0};
vector<thread> threads; vector<thread> threads;
auto start = clock::now(); auto start = clock::now();
for (int t = 0; t < thread_count; ++t) for (int t = 0; t < thread_count; ++t)
{ {
threads.push_back(std::thread([&]() threads.push_back(std::thread([&]() {
{
while (true) while (true)
{ {
int counter = ++msg_counter; int counter = ++msg_counter;
if (counter > howmany) break; if (counter > howmany)
break;
LOG(INFO) << "g2log message #" << counter << ": This is some text for your pleasure"; LOG(INFO) << "g2log message #" << counter << ": This is some text for your pleasure";
} }
})); }));
} }
for (auto &t : threads)
for(auto &t:threads)
{ {
t.join(); t.join();
}; };
duration<float> delta = clock::now() - start; duration<float> delta = clock::now() - start;
float deltaf = delta.count(); float deltaf = delta.count();
auto rate = howmany/deltaf; auto rate = howmany / deltaf;
cout << "Total: " << howmany << std::endl; cout << "Total: " << howmany << std::endl;
cout << "Threads: " << thread_count << std::endl; cout << "Threads: " << thread_count << std::endl;
......
...@@ -3,19 +3,19 @@ ...@@ -3,19 +3,19 @@
// Distributed under the MIT License (http://opensource.org/licenses/MIT) // Distributed under the MIT License (http://opensource.org/licenses/MIT)
// //
#include <atomic>
#include <thread> #include <thread>
#include <vector> #include <vector>
#include <atomic>
#include "glog/logging.h" #include "glog/logging.h"
using namespace std; using namespace std;
int main(int argc, char* argv[]) int main(int argc, char *argv[])
{ {
int thread_count = 10; int thread_count = 10;
if(argc > 1) if (argc > 1)
thread_count = atoi(argv[1]); thread_count = atoi(argv[1]);
int howmany = 1000000; int howmany = 1000000;
...@@ -24,24 +24,23 @@ int main(int argc, char* argv[]) ...@@ -24,24 +24,23 @@ int main(int argc, char* argv[])
FLAGS_log_dir = "logs"; FLAGS_log_dir = "logs";
google::InitGoogleLogging(argv[0]); google::InitGoogleLogging(argv[0]);
std::atomic<int > msg_counter {0}; std::atomic<int> msg_counter{0};
vector<thread> threads; vector<thread> threads;
for (int t = 0; t < thread_count; ++t) for (int t = 0; t < thread_count; ++t)
{ {
threads.push_back(std::thread([&]() threads.push_back(std::thread([&]() {
{
while (true) while (true)
{ {
int counter = ++msg_counter; int counter = ++msg_counter;
if (counter > howmany) break; if (counter > howmany)
break;
LOG(INFO) << "glog message #" << counter << ": This is some text for your pleasure"; LOG(INFO) << "glog message #" << counter << ": This is some text for your pleasure";
} }
})); }));
} }
for (auto &t : threads)
for(auto &t:threads)
{ {
t.join(); t.join();
}; };
......
...@@ -5,16 +5,14 @@ ...@@ -5,16 +5,14 @@
#include "glog/logging.h" #include "glog/logging.h"
int main(int, char *argv[])
int main(int, char* argv[])
{ {
int howmany = 1000000; int howmany = 1000000;
FLAGS_logtostderr = 0; FLAGS_logtostderr = 0;
FLAGS_log_dir = "logs"; FLAGS_log_dir = "logs";
google::InitGoogleLogging(argv[0]); google::InitGoogleLogging(argv[0]);
for(int i = 0 ; i < howmany; ++i) for (int i = 0; i < howmany; ++i)
LOG(INFO) << "glog message # " << i << ": This is some text for your pleasure"; LOG(INFO) << "glog message # " << i << ": This is some text for your pleasure";
return 0; return 0;
......
...@@ -9,29 +9,26 @@ void CrusherLoop() ...@@ -9,29 +9,26 @@ void CrusherLoop()
while (true) while (true)
{ {
LOGF(INFO, "Some text to crush you machine. thread:"); LOGF(INFO, "Some text to crush you machine. thread:");
if(++counter % 1000000 == 0) if (++counter % 1000000 == 0)
{ {
std::cout << "Wrote " << counter << " entries" << std::endl; std::cout << "Wrote " << counter << " entries" << std::endl;
} }
} }
} }
int main(int argc, char **argv)
int main(int argc, char** argv)
{ {
std::cout << "WARNING: This test will exaust all your machine memory and will crush it!" << std::endl; std::cout << "WARNING: This test will exaust all your machine memory and will crush it!" << std::endl;
std::cout << "Are you sure you want to continue ? " << std::endl; std::cout << "Are you sure you want to continue ? " << std::endl;
char c; char c;
std::cin >> c; std::cin >> c;
if (toupper( c ) != 'Y') if (toupper(c) != 'Y')
return 0; return 0;
auto worker = g3::LogWorker::createLogWorker(); auto worker = g3::LogWorker::createLogWorker();
auto handle= worker->addDefaultLogger(argv[0], "g3log.txt"); auto handle = worker->addDefaultLogger(argv[0], "g3log.txt");
g3::initializeLogging(worker.get()); g3::initializeLogging(worker.get());
CrusherLoop(); CrusherLoop();
return 0; return 0;
} }
#include <thread> #include "utils.h"
#include <vector> #include <algorithm>
#include <atomic> #include <atomic>
#include <iostream>
#include <chrono> #include <chrono>
#include <algorithm> #include <cstdio>
#include <fstream>
#include <functional>
#include <g3log/g3log.hpp>
#include <g3log/logworker.hpp>
#include <iomanip> #include <iomanip>
#include <iostream> #include <iostream>
#include <sstream>
#include <fstream>
#include <cstdio>
#include <map> #include <map>
#include <numeric> #include <numeric>
#include <functional> #include <sstream>
#include <thread> #include <thread>
#include "utils.h" #include <vector>
#include <g3log/g3log.hpp>
#include <g3log/logworker.hpp>
namespace namespace {
{
const uint64_t g_iterations = 1000000; const uint64_t g_iterations = 1000000;
std::atomic<size_t> g_counter = {0}; std::atomic<size_t> g_counter = {0};
void MeasurePeakDuringLogWrites(const size_t id, std::vector<uint64_t> &result)
void MeasurePeakDuringLogWrites(const size_t id, std::vector<uint64_t>& result)
{ {
while (true) while (true)
...@@ -45,14 +39,12 @@ void MeasurePeakDuringLogWrites(const size_t id, std::vector<uint64_t>& result) ...@@ -45,14 +39,12 @@ void MeasurePeakDuringLogWrites(const size_t id, std::vector<uint64_t>& result)
} }
} }
void PrintResults(const std::map<size_t, std::vector<uint64_t>> &threads_result, size_t total_us)
void PrintResults(const std::map<size_t, std::vector<uint64_t>>& threads_result, size_t total_us)
{ {
std::vector<uint64_t> all_measurements; std::vector<uint64_t> all_measurements;
all_measurements.reserve(g_iterations); all_measurements.reserve(g_iterations);
for (auto& t_result : threads_result) for (auto &t_result : threads_result)
{ {
all_measurements.insert(all_measurements.end(), t_result.second.begin(), t_result.second.end()); all_measurements.insert(all_measurements.end(), t_result.second.begin(), t_result.second.end());
} }
...@@ -62,13 +54,12 @@ void PrintResults(const std::map<size_t, std::vector<uint64_t>>& threads_result, ...@@ -62,13 +54,12 @@ void PrintResults(const std::map<size_t, std::vector<uint64_t>>& threads_result,
// calc avg // calc avg
auto total = accumulate(begin(all_measurements), end(all_measurements), 0, std::plus<uint64_t>()); auto total = accumulate(begin(all_measurements), end(all_measurements), 0, std::plus<uint64_t>());
auto avg = double(total)/all_measurements.size(); auto avg = double(total) / all_measurements.size();
std::cout << "[g3log] worst: " << std::setw(10) << std::right << worst << "\tAvg: " << avg << "\tTotal: " << utils::format(total_us) << " us" << std::endl;
std::cout << "[g3log] worst: " << std::setw(10) << std::right << worst << "\tAvg: " << avg << "\tTotal: " << utils::format(total_us)
<< " us" << std::endl;
} }
}// anonymous } // namespace
// The purpose of this test is NOT to see how fast // The purpose of this test is NOT to see how fast
// each thread can possibly write. It is to see what // each thread can possibly write. It is to see what
...@@ -78,9 +69,9 @@ void PrintResults(const std::map<size_t, std::vector<uint64_t>>& threads_result, ...@@ -78,9 +69,9 @@ void PrintResults(const std::map<size_t, std::vector<uint64_t>>& threads_result,
// an atomic counter is used to give each thread what // an atomic counter is used to give each thread what
// it is to write next. The overhead of atomic // it is to write next. The overhead of atomic
// synchronization between the threads are not counted in the worst case latency // synchronization between the threads are not counted in the worst case latency
int main(int argc, char** argv) int main(int argc, char **argv)
{ {
size_t number_of_threads {0}; size_t number_of_threads{0};
if (argc == 2) if (argc == 2)
{ {
number_of_threads = atoi(argv[1]); number_of_threads = atoi(argv[1]);
...@@ -91,7 +82,6 @@ int main(int argc, char** argv) ...@@ -91,7 +82,6 @@ int main(int argc, char** argv)
return 1; return 1;
} }
std::vector<std::thread> threads(number_of_threads); std::vector<std::thread> threads(number_of_threads);
std::map<size_t, std::vector<uint64_t>> threads_result; std::map<size_t, std::vector<uint64_t>> threads_result;
...@@ -102,12 +92,12 @@ int main(int argc, char** argv) ...@@ -102,12 +92,12 @@ int main(int argc, char** argv)
threads_result[idx].reserve(g_iterations); threads_result[idx].reserve(g_iterations);
} }
const std::string g_path = "./" ; const std::string g_path = "./";
const std::string g_prefix_log_name = "g3log-performance-"; const std::string g_prefix_log_name = "g3log-performance-";
const std::string g_measurement_dump = g_path + g_prefix_log_name + "_RESULT.txt"; const std::string g_measurement_dump = g_path + g_prefix_log_name + "_RESULT.txt";
auto worker = g3::LogWorker::createLogWorker(); auto worker = g3::LogWorker::createLogWorker();
auto handle= worker->addDefaultLogger(argv[0], "g3log.txt"); auto handle = worker->addDefaultLogger(argv[0], "g3log.txt");
g3::initializeLogging(worker.get()); g3::initializeLogging(worker.get());
auto start_time_application_total = std::chrono::high_resolution_clock::now(); auto start_time_application_total = std::chrono::high_resolution_clock::now();
...@@ -121,9 +111,8 @@ int main(int argc, char** argv) ...@@ -121,9 +111,8 @@ int main(int argc, char** argv)
} }
auto stop_time_application_total = std::chrono::high_resolution_clock::now(); auto stop_time_application_total = std::chrono::high_resolution_clock::now();
uint64_t total_time_in_us = std::chrono::duration_cast<std::chrono::microseconds>(stop_time_application_total - start_time_application_total).count(); uint64_t total_time_in_us =
std::chrono::duration_cast<std::chrono::microseconds>(stop_time_application_total - start_time_application_total).count();
PrintResults(threads_result, total_time_in_us); PrintResults(threads_result, total_time_in_us);
return 0; return 0;
} }
#include <thread> #include "utils.h"
#include <vector> #include <algorithm>
#include <atomic> #include <atomic>
#include <iostream>
#include <chrono> #include <chrono>
#include <algorithm>
#include <iostream>
#include <cstdio> #include <cstdio>
#include <functional>
#include <iostream>
#include <map> #include <map>
#include <numeric> #include <numeric>
#include <functional>
#include "utils.h"
#include <thread> #include <thread>
#include <vector>
#include "spdlog/spdlog.h" #include "spdlog/spdlog.h"
namespace spd = spdlog; namespace spd = spdlog;
namespace namespace {
{
const uint64_t g_iterations = 1000000; const uint64_t g_iterations = 1000000;
std::atomic<size_t> g_counter = {0}; std::atomic<size_t> g_counter = {0};
void MeasurePeakDuringLogWrites(const size_t id, std::vector<uint64_t> &result)
void MeasurePeakDuringLogWrites(const size_t id, std::vector<uint64_t>& result)
{ {
auto logger = spd::get("file_logger"); auto logger = spd::get("file_logger");
while (true) while (true)
...@@ -44,13 +39,12 @@ void MeasurePeakDuringLogWrites(const size_t id, std::vector<uint64_t>& result) ...@@ -44,13 +39,12 @@ void MeasurePeakDuringLogWrites(const size_t id, std::vector<uint64_t>& result)
} }
} }
void PrintResults(const std::map<size_t, std::vector<uint64_t>> &threads_result, size_t total_us)
void PrintResults(const std::map<size_t, std::vector<uint64_t>>& threads_result, size_t total_us)
{ {
std::vector<uint64_t> all_measurements; std::vector<uint64_t> all_measurements;
all_measurements.reserve(g_iterations); all_measurements.reserve(g_iterations);
for (auto& t_result : threads_result) for (auto &t_result : threads_result)
{ {
all_measurements.insert(all_measurements.end(), t_result.second.begin(), t_result.second.end()); all_measurements.insert(all_measurements.end(), t_result.second.begin(), t_result.second.end());
} }
...@@ -60,13 +54,12 @@ void PrintResults(const std::map<size_t, std::vector<uint64_t>>& threads_result, ...@@ -60,13 +54,12 @@ void PrintResults(const std::map<size_t, std::vector<uint64_t>>& threads_result,
// calc avg // calc avg
auto total = accumulate(begin(all_measurements), end(all_measurements), 0, std::plus<uint64_t>()); auto total = accumulate(begin(all_measurements), end(all_measurements), 0, std::plus<uint64_t>());
auto avg = double(total)/all_measurements.size(); auto avg = double(total) / all_measurements.size();
std::cout << "[spdlog] worst: " << std::setw(10) << std::right << worst << "\tAvg: " << avg << "\tTotal: " << utils::format(total_us) << " us" << std::endl;
std::cout << "[spdlog] worst: " << std::setw(10) << std::right << worst << "\tAvg: " << avg << "\tTotal: " << utils::format(total_us)
<< " us" << std::endl;
} }
}// anonymous } // namespace
// The purpose of this test is NOT to see how fast // The purpose of this test is NOT to see how fast
// each thread can possibly write. It is to see what // each thread can possibly write. It is to see what
...@@ -76,9 +69,9 @@ void PrintResults(const std::map<size_t, std::vector<uint64_t>>& threads_result, ...@@ -76,9 +69,9 @@ void PrintResults(const std::map<size_t, std::vector<uint64_t>>& threads_result,
// an atomic counter is used to give each thread what // an atomic counter is used to give each thread what
// it is to write next. The overhead of atomic // it is to write next. The overhead of atomic
// synchronization between the threads are not counted in the worst case latency // synchronization between the threads are not counted in the worst case latency
int main(int argc, char** argv) int main(int argc, char **argv)
{ {
size_t number_of_threads {0}; size_t number_of_threads{0};
if (argc == 2) if (argc == 2)
{ {
number_of_threads = atoi(argv[1]); number_of_threads = atoi(argv[1]);
...@@ -89,7 +82,6 @@ int main(int argc, char** argv) ...@@ -89,7 +82,6 @@ int main(int argc, char** argv)
return 1; return 1;
} }
std::vector<std::thread> threads(number_of_threads); std::vector<std::thread> threads(number_of_threads);
std::map<size_t, std::vector<uint64_t>> threads_result; std::map<size_t, std::vector<uint64_t>> threads_result;
...@@ -104,8 +96,8 @@ int main(int argc, char** argv) ...@@ -104,8 +96,8 @@ int main(int argc, char** argv)
spdlog::set_async_mode(queue_size); spdlog::set_async_mode(queue_size);
auto logger = spdlog::create<spd::sinks::simple_file_sink_mt>("file_logger", "spdlog.log", true); auto logger = spdlog::create<spd::sinks::simple_file_sink_mt>("file_logger", "spdlog.log", true);
//force flush on every call to compare with g3log // force flush on every call to compare with g3log
auto s = (spd::sinks::simple_file_sink_mt*)logger->sinks()[0].get(); auto s = (spd::sinks::simple_file_sink_mt *)logger->sinks()[0].get();
s->set_force_flush(true); s->set_force_flush(true);
auto start_time_application_total = std::chrono::high_resolution_clock::now(); auto start_time_application_total = std::chrono::high_resolution_clock::now();
...@@ -119,10 +111,9 @@ int main(int argc, char** argv) ...@@ -119,10 +111,9 @@ int main(int argc, char** argv)
} }
auto stop_time_application_total = std::chrono::high_resolution_clock::now(); auto stop_time_application_total = std::chrono::high_resolution_clock::now();
uint64_t total_time_in_us = std::chrono::duration_cast<std::chrono::microseconds>(stop_time_application_total - start_time_application_total).count(); uint64_t total_time_in_us =
std::chrono::duration_cast<std::chrono::microseconds>(stop_time_application_total - start_time_application_total).count();
PrintResults(threads_result, total_time_in_us); PrintResults(threads_result, total_time_in_us);
return 0; return 0;
} }
...@@ -5,15 +5,13 @@ ...@@ -5,15 +5,13 @@
#pragma once #pragma once
#include <sstream>
#include <iomanip> #include <iomanip>
#include <locale> #include <locale>
#include <sstream>
namespace utils namespace utils {
{
template<typename T> template <typename T> inline std::string format(const T &value)
inline std::string format(const T& value)
{ {
static std::locale loc(""); static std::locale loc("");
std::stringstream ss; std::stringstream ss;
...@@ -22,8 +20,7 @@ inline std::string format(const T& value) ...@@ -22,8 +20,7 @@ inline std::string format(const T& value)
return ss.str(); return ss.str();
} }
template<> template <> inline std::string format(const double &value)
inline std::string format(const double & value)
{ {
static std::locale loc(""); static std::locale loc("");
std::stringstream ss; std::stringstream ss;
...@@ -32,4 +29,4 @@ inline std::string format(const double & value) ...@@ -32,4 +29,4 @@ inline std::string format(const double & value)
return ss.str(); return ss.str();
} }
} } // namespace utils
...@@ -3,25 +3,25 @@ ...@@ -3,25 +3,25 @@
// Distributed under the MIT License (http://opensource.org/licenses/MIT) // Distributed under the MIT License (http://opensource.org/licenses/MIT)
// //
#include <thread> #include "spdlog/spdlog.h"
#include <vector>
#include <atomic> #include <atomic>
#include <iostream>
#include <chrono> #include <chrono>
#include <cstdlib> #include <cstdlib>
#include "spdlog/spdlog.h" #include <iostream>
#include <thread>
#include <vector>
using namespace std; using namespace std;
int main(int argc, char* argv[]) int main(int argc, char *argv[])
{ {
using namespace std::chrono; using namespace std::chrono;
using clock=steady_clock; using clock = steady_clock;
namespace spd = spdlog; namespace spd = spdlog;
int thread_count = 10; int thread_count = 10;
if(argc > 1) if (argc > 1)
thread_count = ::atoi(argv[1]); thread_count = ::atoi(argv[1]);
int howmany = 1000000; int howmany = 1000000;
...@@ -29,31 +29,30 @@ int main(int argc, char* argv[]) ...@@ -29,31 +29,30 @@ int main(int argc, char* argv[])
auto logger = spdlog::create<spd::sinks::simple_file_sink_mt>("file_logger", "logs/spd-bench-async.txt", false); auto logger = spdlog::create<spd::sinks::simple_file_sink_mt>("file_logger", "logs/spd-bench-async.txt", false);
logger->set_pattern("[%Y-%b-%d %T.%e]: %v"); logger->set_pattern("[%Y-%b-%d %T.%e]: %v");
std::atomic<int> msg_counter{0};
std::atomic<int > msg_counter {0};
vector<thread> threads; vector<thread> threads;
auto start = clock::now(); auto start = clock::now();
for (int t = 0; t < thread_count; ++t) for (int t = 0; t < thread_count; ++t)
{ {
threads.push_back(std::thread([&]() threads.push_back(std::thread([&]() {
{
while (true) while (true)
{ {
int counter = ++msg_counter; int counter = ++msg_counter;
if (counter > howmany) break; if (counter > howmany)
break;
logger->info("spdlog message #{}: This is some text for your pleasure", counter); logger->info("spdlog message #{}: This is some text for your pleasure", counter);
} }
})); }));
} }
for(auto &t:threads) for (auto &t : threads)
{ {
t.join(); t.join();
}; };
duration<float> delta = clock::now() - start; duration<float> delta = clock::now() - start;
float deltaf = delta.count(); float deltaf = delta.count();
auto rate = howmany/deltaf; auto rate = howmany / deltaf;
cout << "Total: " << howmany << std::endl; cout << "Total: " << howmany << std::endl;
cout << "Threads: " << thread_count << std::endl; cout << "Threads: " << thread_count << std::endl;
......
...@@ -3,20 +3,19 @@ ...@@ -3,20 +3,19 @@
// Distributed under the MIT License (http://opensource.org/licenses/MIT) // Distributed under the MIT License (http://opensource.org/licenses/MIT)
// //
#include <thread> #include "spdlog/spdlog.h"
#include <vector>
#include <atomic> #include <atomic>
#include <cstdlib> #include <cstdlib>
#include "spdlog/spdlog.h" #include <thread>
#include <vector>
using namespace std; using namespace std;
int main(int argc, char* argv[]) int main(int argc, char *argv[])
{ {
int thread_count = 10; int thread_count = 10;
if(argc > 1) if (argc > 1)
thread_count = std::atoi(argv[1]); thread_count = std::atoi(argv[1]);
int howmany = 1000000; int howmany = 1000000;
...@@ -27,29 +26,26 @@ int main(int argc, char* argv[]) ...@@ -27,29 +26,26 @@ int main(int argc, char* argv[])
logger->set_pattern("[%Y-%b-%d %T.%e]: %v"); logger->set_pattern("[%Y-%b-%d %T.%e]: %v");
std::atomic<int > msg_counter {0}; std::atomic<int> msg_counter{0};
std::vector<thread> threads; std::vector<thread> threads;
for (int t = 0; t < thread_count; ++t) for (int t = 0; t < thread_count; ++t)
{ {
threads.push_back(std::thread([&]() threads.push_back(std::thread([&]() {
{
while (true) while (true)
{ {
int counter = ++msg_counter; int counter = ++msg_counter;
if (counter > howmany) break; if (counter > howmany)
break;
logger->info("spdlog message #{}: This is some text for your pleasure", counter); logger->info("spdlog message #{}: This is some text for your pleasure", counter);
} }
})); }));
} }
for (auto &t : threads)
for(auto &t:threads)
{ {
t.join(); t.join();
}; };
return 0; return 0;
} }
...@@ -5,16 +5,15 @@ ...@@ -5,16 +5,15 @@
#include "spdlog/spdlog.h" #include "spdlog/spdlog.h"
int main(int, char *[])
int main(int, char* [])
{ {
int howmany = 1000000; int howmany = 1000000;
namespace spd = spdlog; namespace spd = spdlog;
///Create a file rotating logger with 5mb size max and 3 rotated files /// Create a file rotating logger with 5mb size max and 3 rotated files
auto logger = spdlog::create<spd::sinks::simple_file_sink_st>("file_logger", "logs/spd-bench-st.txt", false); auto logger = spdlog::create<spd::sinks::simple_file_sink_st>("file_logger", "logs/spd-bench-st.txt", false);
logger->set_pattern("[%Y-%b-%d %T.%e]: %v"); logger->set_pattern("[%Y-%b-%d %T.%e]: %v");
for(int i = 0 ; i < howmany; ++i) for (int i = 0; i < howmany; ++i)
logger->info("spdlog message #{} : This is some text for your pleasure", i); logger->info("spdlog message #{} : This is some text for your pleasure", i);
return 0; return 0;
} }
...@@ -6,17 +6,16 @@ ...@@ -6,17 +6,16 @@
// //
// bench.cpp : spdlog benchmarks // bench.cpp : spdlog benchmarks
// //
#include "spdlog/async_logger.h"
#include "spdlog/sinks/null_sink.h"
#include "spdlog/spdlog.h"
#include "utils.h"
#include <atomic> #include <atomic>
#include <cstdlib> // EXIT_FAILURE #include <cstdlib> // EXIT_FAILURE
#include <iostream> #include <iostream>
#include <memory> #include <memory>
#include <string> #include <string>
#include <thread> #include <thread>
#include "spdlog/spdlog.h"
#include "spdlog/async_logger.h"
#include "spdlog/sinks/null_sink.h"
#include "utils.h"
using namespace std; using namespace std;
using namespace std::chrono; using namespace std::chrono;
...@@ -24,11 +23,9 @@ using namespace spdlog; ...@@ -24,11 +23,9 @@ using namespace spdlog;
using namespace spdlog::sinks; using namespace spdlog::sinks;
using namespace utils; using namespace utils;
size_t bench_as(int howmany, std::shared_ptr<spdlog::logger> log, int thread_count); size_t bench_as(int howmany, std::shared_ptr<spdlog::logger> log, int thread_count);
int main(int argc, char* argv[]) int main(int argc, char *argv[])
{ {
int queue_size = 1048576; int queue_size = 1048576;
...@@ -39,14 +36,13 @@ int main(int argc, char* argv[]) ...@@ -39,14 +36,13 @@ int main(int argc, char* argv[])
try try
{ {
if(argc > 1) if (argc > 1)
howmany = atoi(argv[1]); howmany = atoi(argv[1]);
if (argc > 2) if (argc > 2)
threads = atoi(argv[2]); threads = atoi(argv[2]);
if (argc > 3) if (argc > 3)
queue_size = atoi(argv[3]); queue_size = atoi(argv[3]);
cout << "\n*******************************************************************************\n"; cout << "\n*******************************************************************************\n";
cout << "async logging.. " << threads << " threads sharing same logger, " << format(howmany) << " messages " << endl; cout << "async logging.. " << threads << " threads sharing same logger, " << format(howmany) << " messages " << endl;
cout << "*******************************************************************************\n"; cout << "*******************************************************************************\n";
...@@ -55,16 +51,15 @@ int main(int argc, char* argv[]) ...@@ -55,16 +51,15 @@ int main(int argc, char* argv[])
size_t total_rate = 0; size_t total_rate = 0;
for(int i = 0; i < iters; ++i) for (int i = 0; i < iters; ++i)
{ {
//auto as = spdlog::daily_logger_st("as", "logs/daily_async"); // auto as = spdlog::daily_logger_st("as", "logs/daily_async");
auto as = spdlog::create<null_sink_st>("async(null-sink)"); auto as = spdlog::create<null_sink_st>("async(null-sink)");
total_rate+= bench_as(howmany, as, threads); total_rate += bench_as(howmany, as, threads);
spdlog::drop("async(null-sink)"); spdlog::drop("async(null-sink)");
} }
std::cout << endl; std::cout << endl;
std::cout << "Avg rate: " << format(total_rate/iters) << "/sec" <<std::endl; std::cout << "Avg rate: " << format(total_rate / iters) << "/sec" << std::endl;
} }
catch (std::exception &ex) catch (std::exception &ex)
{ {
...@@ -75,37 +70,33 @@ int main(int argc, char* argv[]) ...@@ -75,37 +70,33 @@ int main(int argc, char* argv[])
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }
// return rate/sec
//return rate/sec
size_t bench_as(int howmany, std::shared_ptr<spdlog::logger> log, int thread_count) size_t bench_as(int howmany, std::shared_ptr<spdlog::logger> log, int thread_count)
{ {
cout << log->name() << "...\t\t" << flush; cout << log->name() << "...\t\t" << flush;
std::atomic<int > msg_counter {0}; std::atomic<int> msg_counter{0};
vector<thread> threads; vector<thread> threads;
auto start = system_clock::now(); auto start = system_clock::now();
for (int t = 0; t < thread_count; ++t) for (int t = 0; t < thread_count; ++t)
{ {
threads.push_back(std::thread([&]() threads.push_back(std::thread([&]() {
{ for (;;)
for(;;)
{ {
int counter = ++msg_counter; int counter = ++msg_counter;
if (counter > howmany) break; if (counter > howmany)
break;
log->info("Hello logger: msg number {}", counter); log->info("Hello logger: msg number {}", counter);
} }
})); }));
} }
for (auto &t : threads)
for(auto &t:threads)
{ {
t.join(); t.join();
}; };
auto delta = system_clock::now() - start; auto delta = system_clock::now() - start;
auto delta_d = duration_cast<duration<double>> (delta).count(); auto delta_d = duration_cast<duration<double>>(delta).count();
auto per_sec = size_t(howmany / delta_d); auto per_sec = size_t(howmany / delta_d);
cout << format(per_sec) << "/sec" << endl; cout << format(per_sec) << "/sec" << endl;
return per_sec; return per_sec;
......
...@@ -5,15 +5,13 @@ ...@@ -5,15 +5,13 @@
#pragma once #pragma once
#include <sstream>
#include <iomanip> #include <iomanip>
#include <locale> #include <locale>
#include <sstream>
namespace utils namespace utils {
{
template<typename T> template <typename T> inline std::string format(const T &value)
inline std::string format(const T& value)
{ {
static std::locale loc(""); static std::locale loc("");
std::stringstream ss; std::stringstream ss;
...@@ -22,8 +20,7 @@ inline std::string format(const T& value) ...@@ -22,8 +20,7 @@ inline std::string format(const T& value)
return ss.str(); return ss.str();
} }
template<> template <> inline std::string format(const double &value)
inline std::string format(const double & value)
{ {
static std::locale loc(""); static std::locale loc("");
std::stringstream ss; std::stringstream ss;
...@@ -32,4 +29,4 @@ inline std::string format(const double & value) ...@@ -32,4 +29,4 @@ inline std::string format(const double & value)
return ss.str(); return ss.str();
} }
} } // namespace utils
...@@ -6,18 +6,17 @@ ...@@ -6,18 +6,17 @@
// //
// bench.cpp : spdlog benchmarks // bench.cpp : spdlog benchmarks
// //
#include "spdlog/async_logger.h"
#include "spdlog/sinks/file_sinks.h"
#include "spdlog/sinks/null_sink.h"
#include "spdlog/spdlog.h"
#include "utils.h"
#include <atomic> #include <atomic>
#include <cstdlib> // EXIT_FAILURE #include <cstdlib> // EXIT_FAILURE
#include <iostream> #include <iostream>
#include <memory> #include <memory>
#include <string> #include <string>
#include <thread> #include <thread>
#include "spdlog/spdlog.h"
#include "spdlog/async_logger.h"
#include "spdlog/sinks/file_sinks.h"
#include "spdlog/sinks/null_sink.h"
#include "utils.h"
using namespace std; using namespace std;
using namespace std::chrono; using namespace std::chrono;
...@@ -25,11 +24,10 @@ using namespace spdlog; ...@@ -25,11 +24,10 @@ using namespace spdlog;
using namespace spdlog::sinks; using namespace spdlog::sinks;
using namespace utils; using namespace utils;
void bench(int howmany, std::shared_ptr<spdlog::logger> log); void bench(int howmany, std::shared_ptr<spdlog::logger> log);
void bench_mt(int howmany, std::shared_ptr<spdlog::logger> log, int thread_count); void bench_mt(int howmany, std::shared_ptr<spdlog::logger> log, int thread_count);
int main(int argc, char* argv[]) int main(int argc, char *argv[])
{ {
int queue_size = 1048576; int queue_size = 1048576;
...@@ -41,14 +39,13 @@ int main(int argc, char* argv[]) ...@@ -41,14 +39,13 @@ int main(int argc, char* argv[])
try try
{ {
if(argc > 1) if (argc > 1)
howmany = atoi(argv[1]); howmany = atoi(argv[1]);
if (argc > 2) if (argc > 2)
threads = atoi(argv[2]); threads = atoi(argv[2]);
if (argc > 3) if (argc > 3)
queue_size = atoi(argv[3]); queue_size = atoi(argv[3]);
cout << "*******************************************************************************\n"; cout << "*******************************************************************************\n";
cout << "Single thread, " << format(howmany) << " iterations" << endl; cout << "Single thread, " << format(howmany) << " iterations" << endl;
cout << "*******************************************************************************\n"; cout << "*******************************************************************************\n";
...@@ -66,7 +63,6 @@ int main(int argc, char* argv[]) ...@@ -66,7 +63,6 @@ int main(int argc, char* argv[])
auto rotating_mt = spdlog::rotating_logger_mt("rotating_mt", "logs/rotating_mt.log", file_size, rotating_files); auto rotating_mt = spdlog::rotating_logger_mt("rotating_mt", "logs/rotating_mt.log", file_size, rotating_files);
bench_mt(howmany, rotating_mt, threads); bench_mt(howmany, rotating_mt, threads);
auto daily_mt = spdlog::daily_logger_mt("daily_mt", "logs/daily_mt.log"); auto daily_mt = spdlog::daily_logger_mt("daily_mt", "logs/daily_mt.log");
bench_mt(howmany, daily_mt, threads); bench_mt(howmany, daily_mt, threads);
bench(howmany, spdlog::create<null_sink_st>("null_mt")); bench(howmany, spdlog::create<null_sink_st>("null_mt"));
...@@ -75,10 +71,9 @@ int main(int argc, char* argv[]) ...@@ -75,10 +71,9 @@ int main(int argc, char* argv[])
cout << "async logging.. " << threads << " threads sharing same logger, " << format(howmany) << " iterations " << endl; cout << "async logging.. " << threads << " threads sharing same logger, " << format(howmany) << " iterations " << endl;
cout << "*******************************************************************************\n"; cout << "*******************************************************************************\n";
spdlog::set_async_mode(queue_size); spdlog::set_async_mode(queue_size);
for(int i = 0; i < 3; ++i) for (int i = 0; i < 3; ++i)
{ {
auto as = spdlog::daily_logger_st("as", "logs/daily_async.log"); auto as = spdlog::daily_logger_st("as", "logs/daily_async.log");
bench_mt(howmany, as, threads); bench_mt(howmany, as, threads);
...@@ -94,7 +89,6 @@ int main(int argc, char* argv[]) ...@@ -94,7 +89,6 @@ int main(int argc, char* argv[])
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }
void bench(int howmany, std::shared_ptr<spdlog::logger> log) void bench(int howmany, std::shared_ptr<spdlog::logger> log)
{ {
cout << log->name() << "...\t\t" << flush; cout << log->name() << "...\t\t" << flush;
...@@ -104,41 +98,37 @@ void bench(int howmany, std::shared_ptr<spdlog::logger> log) ...@@ -104,41 +98,37 @@ void bench(int howmany, std::shared_ptr<spdlog::logger> log)
log->info("Hello logger: msg number {}", i); log->info("Hello logger: msg number {}", i);
} }
auto delta = system_clock::now() - start; auto delta = system_clock::now() - start;
auto delta_d = duration_cast<duration<double>> (delta).count(); auto delta_d = duration_cast<duration<double>>(delta).count();
cout << format(int(howmany / delta_d)) << "/sec" << endl; cout << format(int(howmany / delta_d)) << "/sec" << endl;
} }
void bench_mt(int howmany, std::shared_ptr<spdlog::logger> log, int thread_count) void bench_mt(int howmany, std::shared_ptr<spdlog::logger> log, int thread_count)
{ {
cout << log->name() << "...\t\t" << flush; cout << log->name() << "...\t\t" << flush;
std::atomic<int > msg_counter {0}; std::atomic<int> msg_counter{0};
vector<thread> threads; vector<thread> threads;
auto start = system_clock::now(); auto start = system_clock::now();
for (int t = 0; t < thread_count; ++t) for (int t = 0; t < thread_count; ++t)
{ {
threads.push_back(std::thread([&]() threads.push_back(std::thread([&]() {
{ for (;;)
for(;;)
{ {
int counter = ++msg_counter; int counter = ++msg_counter;
if (counter > howmany) break; if (counter > howmany)
break;
log->info("Hello logger: msg number {}", counter); log->info("Hello logger: msg number {}", counter);
} }
})); }));
} }
for (auto &t : threads)
for(auto &t:threads)
{ {
t.join(); t.join();
}; };
auto delta = system_clock::now() - start; auto delta = system_clock::now() - start;
auto delta_d = duration_cast<duration<double>> (delta).count(); auto delta_d = duration_cast<duration<double>>(delta).count();
cout << format(int(howmany / delta_d)) << "/sec" << endl; cout << format(int(howmany / delta_d)) << "/sec" << endl;
} }
...@@ -22,7 +22,7 @@ void user_defined_example(); ...@@ -22,7 +22,7 @@ void user_defined_example();
void err_handler_example(); void err_handler_example();
namespace spd = spdlog; namespace spd = spdlog;
int main(int, char*[]) int main(int, char *[])
{ {
try try
{ {
...@@ -31,7 +31,6 @@ int main(int, char*[]) ...@@ -31,7 +31,6 @@ int main(int, char*[])
console->info("Welcome to spdlog!"); console->info("Welcome to spdlog!");
console->error("Some error message with arg{}..", 1); console->error("Some error message with arg{}..", 1);
// Formatting examples // Formatting examples
console->warn("Easy padding in numbers like {:08d}", 12); console->warn("Easy padding in numbers like {:08d}", 12);
console->critical("Support for int: {0:d}; hex: {0:x}; oct: {0:o}; bin: {0:b}", 42); console->critical("Support for int: {0:d}; hex: {0:x}; oct: {0:o}; bin: {0:b}", 42);
...@@ -41,7 +40,6 @@ int main(int, char*[]) ...@@ -41,7 +40,6 @@ int main(int, char*[])
spd::get("console")->info("loggers can be retrieved from a global registry using the spdlog::get(logger_name) function"); spd::get("console")->info("loggers can be retrieved from a global registry using the spdlog::get(logger_name) function");
// Create basic file logger (not rotated) // Create basic file logger (not rotated)
auto my_logger = spd::basic_logger_mt("basic_logger", "logs/basic-log.txt"); auto my_logger = spd::basic_logger_mt("basic_logger", "logs/basic-log.txt");
my_logger->info("Some log message"); my_logger->info("Some log message");
...@@ -49,7 +47,7 @@ int main(int, char*[]) ...@@ -49,7 +47,7 @@ int main(int, char*[])
// Create a file rotating logger with 5mb size max and 3 rotated files // Create a file rotating logger with 5mb size max and 3 rotated files
auto rotating_logger = spd::rotating_logger_mt("some_logger_name", "logs/rotating.txt", 1048576 * 5, 3); auto rotating_logger = spd::rotating_logger_mt("some_logger_name", "logs/rotating.txt", 1048576 * 5, 3);
for (int i = 0; i < 10; ++i) for (int i = 0; i < 10; ++i)
rotating_logger->info("{} * {} equals {:>10}", i, i, i*i); rotating_logger->info("{} * {} equals {:>10}", i, i, i * i);
// Create a daily logger - a new file is created every day on 2:30am // Create a daily logger - a new file is created every day on 2:30am
auto daily_logger = spd::daily_logger_mt("daily_logger", "logs/daily.txt", 2, 30); auto daily_logger = spd::daily_logger_mt("daily_logger", "logs/daily.txt", 2, 30);
...@@ -61,9 +59,8 @@ int main(int, char*[]) ...@@ -61,9 +59,8 @@ int main(int, char*[])
spd::set_pattern("*** [%H:%M:%S %z] [thread %t] %v ***"); spd::set_pattern("*** [%H:%M:%S %z] [thread %t] %v ***");
rotating_logger->info("This is another message with custom format"); rotating_logger->info("This is another message with custom format");
// Runtime log levels // Runtime log levels
spd::set_level(spd::level::info); //Set global log level to info spd::set_level(spd::level::info); // Set global log level to info
console->debug("This message should not be displayed!"); console->debug("This message should not be displayed!");
console->set_level(spd::level::debug); // Set specific logger's log level console->set_level(spd::level::debug); // Set specific logger's log level
console->debug("This message should be displayed.."); console->debug("This message should be displayed..");
...@@ -73,7 +70,6 @@ int main(int, char*[]) ...@@ -73,7 +70,6 @@ int main(int, char*[])
SPDLOG_TRACE(console, "Enabled only #ifdef SPDLOG_TRACE_ON..{} ,{}", 1, 3.23); SPDLOG_TRACE(console, "Enabled only #ifdef SPDLOG_TRACE_ON..{} ,{}", 1, 3.23);
SPDLOG_DEBUG(console, "Enabled only #ifdef SPDLOG_DEBUG_ON.. {} ,{}", 1, 3.23); SPDLOG_DEBUG(console, "Enabled only #ifdef SPDLOG_DEBUG_ON.. {} ,{}", 1, 3.23);
// Asynchronous logging is very fast.. // Asynchronous logging is very fast..
// Just call spdlog::set_async_mode(q_size) and all created loggers from now on will be asynchronous.. // Just call spdlog::set_async_mode(q_size) and all created loggers from now on will be asynchronous..
async_example(); async_example();
...@@ -91,16 +87,13 @@ int main(int, char*[]) ...@@ -91,16 +87,13 @@ int main(int, char*[])
err_handler_example(); err_handler_example();
// Apply a function on all registered loggers // Apply a function on all registered loggers
spd::apply_all([&](std::shared_ptr<spdlog::logger> l) spd::apply_all([&](std::shared_ptr<spdlog::logger> l) { l->info("End of example."); });
{
l->info("End of example.");
});
// Release and close all loggers // Release and close all loggers
spdlog::drop_all(); spdlog::drop_all();
} }
// Exceptions will only be thrown upon failed logger or sink construction (not during logging) // Exceptions will only be thrown upon failed logger or sink construction (not during logging)
catch (const spd::spdlog_ex& ex) catch (const spd::spdlog_ex &ex)
{ {
std::cout << "Log init failed: " << ex.what() << std::endl; std::cout << "Log init failed: " << ex.what() << std::endl;
return 1; return 1;
...@@ -109,14 +102,14 @@ int main(int, char*[]) ...@@ -109,14 +102,14 @@ int main(int, char*[])
void async_example() void async_example()
{ {
size_t q_size = 4096; //queue size must be power of 2 size_t q_size = 4096; // queue size must be power of 2
spdlog::set_async_mode(q_size); spdlog::set_async_mode(q_size);
auto async_file = spd::daily_logger_st("async_file_logger", "logs/async_log.txt"); auto async_file = spd::daily_logger_st("async_file_logger", "logs/async_log.txt");
for (int i = 0; i < 100; ++i) for (int i = 0; i < 100; ++i)
async_file->info("Async message #{}", i); async_file->info("Async message #{}", i);
} }
//syslog example (linux/osx/freebsd) // syslog example (linux/osx/freebsd)
void syslog_example() void syslog_example()
{ {
#ifdef SPDLOG_ENABLE_SYSLOG #ifdef SPDLOG_ENABLE_SYSLOG
...@@ -140,28 +133,24 @@ void android_example() ...@@ -140,28 +133,24 @@ void android_example()
struct my_type struct my_type
{ {
int i; int i;
template<typename OStream> template <typename OStream> friend OStream &operator<<(OStream &os, const my_type &c)
friend OStream& operator<<(OStream& os, const my_type &c)
{ {
return os << "[my_type i="<<c.i << "]"; return os << "[my_type i=" << c.i << "]";
} }
}; };
#include "spdlog/fmt/ostr.h" // must be included #include "spdlog/fmt/ostr.h" // must be included
void user_defined_example() void user_defined_example()
{ {
spd::get("console")->info("user defined type: {}", my_type { 14 }); spd::get("console")->info("user defined type: {}", my_type{14});
} }
// //
//custom error handler // custom error handler
// //
void err_handler_example() void err_handler_example()
{ {
//can be set globaly or per logger(logger->set_error_handler(..)) // can be set globaly or per logger(logger->set_error_handler(..))
spdlog::set_error_handler([](const std::string& msg) spdlog::set_error_handler([](const std::string &msg) { std::cerr << "my err handler: " << msg << std::endl; });
{
std::cerr << "my err handler: " << msg << std::endl;
});
spd::get("console")->info("some invalid message to trigger an error {}{}{}{}", 3); spd::get("console")->info("some invalid message to trigger an error {}{}{}{}", 3);
} }
../example.cpp
\ No newline at end of file
//
// Copyright(c) 2015 Gabi Melman.
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
//
//
// spdlog usage example
//
//
#define SPDLOG_TRACE_ON
#define SPDLOG_DEBUG_ON
#include "spdlog/spdlog.h"
#include <iostream>
#include <memory>
void async_example();
void syslog_example();
void android_example();
void user_defined_example();
void err_handler_example();
namespace spd = spdlog;
int main(int, char *[])
{
try
{
// Console logger with color
auto console = spd::stdout_color_mt("console");
console->info("Welcome to spdlog!");
console->error("Some error message with arg{}..", 1);
// Formatting examples
console->warn("Easy padding in numbers like {:08d}", 12);
console->critical("Support for int: {0:d}; hex: {0:x}; oct: {0:o}; bin: {0:b}", 42);
console->info("Support for floats {:03.2f}", 1.23456);
console->info("Positional args are {1} {0}..", "too", "supported");
console->info("{:<30}", "left aligned");
spd::get("console")->info("loggers can be retrieved from a global registry using the spdlog::get(logger_name) function");
// Create basic file logger (not rotated)
auto my_logger = spd::basic_logger_mt("basic_logger", "logs/basic-log.txt");
my_logger->info("Some log message");
// Create a file rotating logger with 5mb size max and 3 rotated files
auto rotating_logger = spd::rotating_logger_mt("some_logger_name", "logs/rotating.txt", 1048576 * 5, 3);
for (int i = 0; i < 10; ++i)
rotating_logger->info("{} * {} equals {:>10}", i, i, i * i);
// Create a daily logger - a new file is created every day on 2:30am
auto daily_logger = spd::daily_logger_mt("daily_logger", "logs/daily.txt", 2, 30);
// trigger flush if the log severity is error or higher
daily_logger->flush_on(spd::level::err);
daily_logger->info(123.44);
// Customize msg format for all messages
spd::set_pattern("*** [%H:%M:%S %z] [thread %t] %v ***");
rotating_logger->info("This is another message with custom format");
// Runtime log levels
spd::set_level(spd::level::info); // Set global log level to info
console->debug("This message should not be displayed!");
console->set_level(spd::level::debug); // Set specific logger's log level
console->debug("This message should be displayed..");
// Compile time log levels
// define SPDLOG_DEBUG_ON or SPDLOG_TRACE_ON
SPDLOG_TRACE(console, "Enabled only #ifdef SPDLOG_TRACE_ON..{} ,{}", 1, 3.23);
SPDLOG_DEBUG(console, "Enabled only #ifdef SPDLOG_DEBUG_ON.. {} ,{}", 1, 3.23);
// Asynchronous logging is very fast..
// Just call spdlog::set_async_mode(q_size) and all created loggers from now on will be asynchronous..
async_example();
// syslog example. linux/osx only
syslog_example();
// android example. compile with NDK
android_example();
// Log user-defined types example
user_defined_example();
// Change default log error handler
err_handler_example();
// Apply a function on all registered loggers
spd::apply_all([&](std::shared_ptr<spdlog::logger> l) { l->info("End of example."); });
// Release and close all loggers
spdlog::drop_all();
}
// Exceptions will only be thrown upon failed logger or sink construction (not during logging)
catch (const spd::spdlog_ex &ex)
{
std::cout << "Log init failed: " << ex.what() << std::endl;
return 1;
}
}
void async_example()
{
size_t q_size = 4096; // queue size must be power of 2
spdlog::set_async_mode(q_size);
auto async_file = spd::daily_logger_st("async_file_logger", "logs/async_log.txt");
for (int i = 0; i < 100; ++i)
async_file->info("Async message #{}", i);
}
// syslog example (linux/osx/freebsd)
void syslog_example()
{
#ifdef SPDLOG_ENABLE_SYSLOG
std::string ident = "spdlog-example";
auto syslog_logger = spd::syslog_logger("syslog", ident, LOG_PID);
syslog_logger->warn("This is warning that will end up in syslog.");
#endif
}
// Android example
void android_example()
{
#if defined(__ANDROID__)
std::string tag = "spdlog-android";
auto android_logger = spd::android_logger("android", tag);
android_logger->critical("Use \"adb shell logcat\" to view this message.");
#endif
}
// user defined types logging by implementing operator<<
struct my_type
{
int i;
template <typename OStream> friend OStream &operator<<(OStream &os, const my_type &c)
{
return os << "[my_type i=" << c.i << "]";
}
};
#include "spdlog/fmt/ostr.h" // must be included
void user_defined_example()
{
spd::get("console")->info("user defined type: {}", my_type{14});
}
//
// custom error handler
//
void err_handler_example()
{
// can be set globaly or per logger(logger->set_error_handler(..))
spdlog::set_error_handler([](const std::string &msg) { std::cerr << "my err handler: " << msg << std::endl; });
spd::get("console")->info("some invalid message to trigger an error {}{}{}{}", 3);
}
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
#include <memory> #include <memory>
namespace spd = spdlog; namespace spd = spdlog;
int main(int, char*[]) int main(int, char *[])
{ {
bool enable_debug = true; bool enable_debug = true;
try try
...@@ -13,24 +13,24 @@ int main(int, char*[]) ...@@ -13,24 +13,24 @@ int main(int, char*[])
// This means that the same log_msg is forwarded to multiple sinks; // This means that the same log_msg is forwarded to multiple sinks;
// Each sink can have it's own log level and a message will be logged. // Each sink can have it's own log level and a message will be logged.
std::vector<spdlog::sink_ptr> sinks; std::vector<spdlog::sink_ptr> sinks;
sinks.push_back( std::make_shared<spdlog::sinks::stdout_sink_mt>() ); sinks.push_back(std::make_shared<spdlog::sinks::stdout_sink_mt>());
sinks.push_back( std::make_shared<spdlog::sinks::simple_file_sink_mt>("./log_regular_file.txt") ); sinks.push_back(std::make_shared<spdlog::sinks::simple_file_sink_mt>("./log_regular_file.txt"));
sinks.push_back( std::make_shared<spdlog::sinks::simple_file_sink_mt>("./log_debug_file.txt") ); sinks.push_back(std::make_shared<spdlog::sinks::simple_file_sink_mt>("./log_debug_file.txt"));
spdlog::logger console_multisink("multisink", sinks.begin(), sinks.end() ); spdlog::logger console_multisink("multisink", sinks.begin(), sinks.end());
console_multisink.set_level( spdlog::level::warn); console_multisink.set_level(spdlog::level::warn);
sinks[0]->set_level( spdlog::level::trace); // console. Allow everything. Default value sinks[0]->set_level(spdlog::level::trace); // console. Allow everything. Default value
sinks[1]->set_level( spdlog::level::trace); // regular file. Allow everything. Default value sinks[1]->set_level(spdlog::level::trace); // regular file. Allow everything. Default value
sinks[2]->set_level( spdlog::level::off); // regular file. Ignore everything. sinks[2]->set_level(spdlog::level::off); // regular file. Ignore everything.
console_multisink.warn("warn: will print only on console and regular file"); console_multisink.warn("warn: will print only on console and regular file");
if( enable_debug ) if (enable_debug)
{ {
console_multisink.set_level( spdlog::level::debug); // level of the logger console_multisink.set_level(spdlog::level::debug); // level of the logger
sinks[1]->set_level( spdlog::level::debug); // regular file sinks[1]->set_level(spdlog::level::debug); // regular file
sinks[2]->set_level( spdlog::level::debug); // debug file sinks[2]->set_level(spdlog::level::debug); // debug file
} }
console_multisink.debug("Debug: you should see this on console and both files"); console_multisink.debug("Debug: you should see this on console and both files");
...@@ -38,10 +38,9 @@ int main(int, char*[]) ...@@ -38,10 +38,9 @@ int main(int, char*[])
spdlog::drop_all(); spdlog::drop_all();
} }
// Exceptions will only be thrown upon failed logger or sink construction (not during logging) // Exceptions will only be thrown upon failed logger or sink construction (not during logging)
catch (const spd::spdlog_ex& ex) catch (const spd::spdlog_ex &ex)
{ {
std::cout << "Log init failed: " << ex.what() << std::endl; std::cout << "Log init failed: " << ex.what() << std::endl;
return 1; return 1;
} }
} }
...@@ -5,15 +5,13 @@ ...@@ -5,15 +5,13 @@
#pragma once #pragma once
#include <sstream>
#include <iomanip> #include <iomanip>
#include <locale> #include <locale>
#include <sstream>
namespace utils namespace utils {
{
template<typename T> template <typename T> inline std::string format(const T &value)
inline std::string format(const T& value)
{ {
static std::locale loc(""); static std::locale loc("");
std::stringstream ss; std::stringstream ss;
...@@ -22,8 +20,7 @@ inline std::string format(const T& value) ...@@ -22,8 +20,7 @@ inline std::string format(const T& value)
return ss.str(); return ss.str();
} }
template<> template <> inline std::string format(const double &value)
inline std::string format(const double & value)
{ {
static std::locale loc(""); static std::locale loc("");
std::stringstream ss; std::stringstream ss;
...@@ -32,4 +29,4 @@ inline std::string format(const double & value) ...@@ -32,4 +29,4 @@ inline std::string format(const double & value)
return ss.str(); return ss.str();
} }
} } // namespace utils
...@@ -20,48 +20,39 @@ ...@@ -20,48 +20,39 @@
#include <chrono> #include <chrono>
#include <functional> #include <functional>
#include <string>
#include <memory> #include <memory>
#include <string>
namespace spdlog namespace spdlog {
{
namespace details namespace details {
{
class async_log_helper; class async_log_helper;
} }
class async_logger SPDLOG_FINAL : public logger class async_logger SPDLOG_FINAL : public logger
{ {
public: public:
template<class It> template <class It>
async_logger(const std::string& logger_name, async_logger(const std::string &logger_name, const It &begin, const It &end, size_t queue_size,
const It& begin,
const It& end,
size_t queue_size,
const async_overflow_policy overflow_policy = async_overflow_policy::block_retry, const async_overflow_policy overflow_policy = async_overflow_policy::block_retry,
const std::function<void()>& worker_warmup_cb = nullptr, const std::function<void()> &worker_warmup_cb = nullptr,
const std::chrono::milliseconds& flush_interval_ms = std::chrono::milliseconds::zero(), const std::chrono::milliseconds &flush_interval_ms = std::chrono::milliseconds::zero(),
const std::function<void()>& worker_teardown_cb = nullptr); const std::function<void()> &worker_teardown_cb = nullptr);
async_logger(const std::string& logger_name, async_logger(const std::string &logger_name, sinks_init_list sinks, size_t queue_size,
sinks_init_list sinks,
size_t queue_size,
const async_overflow_policy overflow_policy = async_overflow_policy::block_retry, const async_overflow_policy overflow_policy = async_overflow_policy::block_retry,
const std::function<void()>& worker_warmup_cb = nullptr, const std::function<void()> &worker_warmup_cb = nullptr,
const std::chrono::milliseconds& flush_interval_ms = std::chrono::milliseconds::zero(), const std::chrono::milliseconds &flush_interval_ms = std::chrono::milliseconds::zero(),
const std::function<void()>& worker_teardown_cb = nullptr); const std::function<void()> &worker_teardown_cb = nullptr);
async_logger(const std::string& logger_name, async_logger(const std::string &logger_name, sink_ptr single_sink, size_t queue_size,
sink_ptr single_sink,
size_t queue_size,
const async_overflow_policy overflow_policy = async_overflow_policy::block_retry, const async_overflow_policy overflow_policy = async_overflow_policy::block_retry,
const std::function<void()>& worker_warmup_cb = nullptr, const std::function<void()> &worker_warmup_cb = nullptr,
const std::chrono::milliseconds& flush_interval_ms = std::chrono::milliseconds::zero(), const std::chrono::milliseconds &flush_interval_ms = std::chrono::milliseconds::zero(),
const std::function<void()>& worker_teardown_cb = nullptr); const std::function<void()> &worker_teardown_cb = nullptr);
//Wait for the queue to be empty, and flush synchronously // Wait for the queue to be empty, and flush synchronously
//Warning: this can potentially last forever as we wait it to complete // Warning: this can potentially last forever as we wait it to complete
void flush() override; void flush() override;
// Error handler // Error handler
...@@ -69,13 +60,13 @@ public: ...@@ -69,13 +60,13 @@ public:
log_err_handler error_handler() override; log_err_handler error_handler() override;
protected: protected:
void _sink_it(details::log_msg& msg) override; void _sink_it(details::log_msg &msg) override;
void _set_formatter(spdlog::formatter_ptr msg_formatter) override; void _set_formatter(spdlog::formatter_ptr msg_formatter) override;
void _set_pattern(const std::string& pattern, pattern_time_type pattern_time) override; void _set_pattern(const std::string &pattern, pattern_time_type pattern_time) override;
private: private:
std::unique_ptr<details::async_log_helper> _async_log_helper; std::unique_ptr<details::async_log_helper> _async_log_helper;
}; };
} } // namespace spdlog
#include "details/async_logger_impl.h" #include "details/async_logger_impl.h"
This diff is collapsed.
...@@ -8,49 +8,39 @@ ...@@ -8,49 +8,39 @@
// Async Logger implementation // Async Logger implementation
// Use an async_sink (queue per logger) to perform the logging in a worker thread // Use an async_sink (queue per logger) to perform the logging in a worker thread
#include "../details/async_log_helper.h"
#include "../async_logger.h" #include "../async_logger.h"
#include "../details/async_log_helper.h"
#include <string>
#include <functional>
#include <chrono> #include <chrono>
#include <functional>
#include <memory> #include <memory>
#include <string>
template<class It> template <class It>
inline spdlog::async_logger::async_logger(const std::string& logger_name, inline spdlog::async_logger::async_logger(const std::string &logger_name, const It &begin, const It &end, size_t queue_size,
const It& begin, const async_overflow_policy overflow_policy, const std::function<void()> &worker_warmup_cb,
const It& end, const std::chrono::milliseconds &flush_interval_ms, const std::function<void()> &worker_teardown_cb)
size_t queue_size, : logger(logger_name, begin, end)
const async_overflow_policy overflow_policy, , _async_log_helper(new details::async_log_helper(
const std::function<void()>& worker_warmup_cb, _formatter, _sinks, queue_size, _err_handler, overflow_policy, worker_warmup_cb, flush_interval_ms, worker_teardown_cb))
const std::chrono::milliseconds& flush_interval_ms,
const std::function<void()>& worker_teardown_cb) :
logger(logger_name, begin, end),
_async_log_helper(new details::async_log_helper(_formatter, _sinks, queue_size, _err_handler, overflow_policy, worker_warmup_cb, flush_interval_ms, worker_teardown_cb))
{ {
} }
inline spdlog::async_logger::async_logger(const std::string& logger_name, inline spdlog::async_logger::async_logger(const std::string &logger_name, sinks_init_list sinks_list, size_t queue_size,
sinks_init_list sinks_list, const async_overflow_policy overflow_policy, const std::function<void()> &worker_warmup_cb,
size_t queue_size, const std::chrono::milliseconds &flush_interval_ms, const std::function<void()> &worker_teardown_cb)
const async_overflow_policy overflow_policy, : async_logger(logger_name, sinks_list.begin(), sinks_list.end(), queue_size, overflow_policy, worker_warmup_cb, flush_interval_ms,
const std::function<void()>& worker_warmup_cb, worker_teardown_cb)
const std::chrono::milliseconds& flush_interval_ms,
const std::function<void()>& worker_teardown_cb) :
async_logger(logger_name, sinks_list.begin(), sinks_list.end(), queue_size, overflow_policy, worker_warmup_cb, flush_interval_ms, worker_teardown_cb) {}
inline spdlog::async_logger::async_logger(const std::string& logger_name,
sink_ptr single_sink,
size_t queue_size,
const async_overflow_policy overflow_policy,
const std::function<void()>& worker_warmup_cb,
const std::chrono::milliseconds& flush_interval_ms,
const std::function<void()>& worker_teardown_cb) :
async_logger(logger_name,
{ {
std::move(single_sink) }
}, queue_size, overflow_policy, worker_warmup_cb, flush_interval_ms, worker_teardown_cb) {}
inline spdlog::async_logger::async_logger(const std::string &logger_name, sink_ptr single_sink, size_t queue_size,
const async_overflow_policy overflow_policy, const std::function<void()> &worker_warmup_cb,
const std::chrono::milliseconds &flush_interval_ms, const std::function<void()> &worker_teardown_cb)
: async_logger(
logger_name, {std::move(single_sink)}, queue_size, overflow_policy, worker_warmup_cb, flush_interval_ms, worker_teardown_cb)
{
}
inline void spdlog::async_logger::flush() inline void spdlog::async_logger::flush()
{ {
...@@ -62,28 +52,25 @@ inline void spdlog::async_logger::set_error_handler(spdlog::log_err_handler err_ ...@@ -62,28 +52,25 @@ inline void spdlog::async_logger::set_error_handler(spdlog::log_err_handler err_
{ {
_err_handler = err_handler; _err_handler = err_handler;
_async_log_helper->set_error_handler(err_handler); _async_log_helper->set_error_handler(err_handler);
} }
inline spdlog::log_err_handler spdlog::async_logger::error_handler() inline spdlog::log_err_handler spdlog::async_logger::error_handler()
{ {
return _err_handler; return _err_handler;
} }
inline void spdlog::async_logger::_set_formatter(spdlog::formatter_ptr msg_formatter) inline void spdlog::async_logger::_set_formatter(spdlog::formatter_ptr msg_formatter)
{ {
_formatter = msg_formatter; _formatter = msg_formatter;
_async_log_helper->set_formatter(_formatter); _async_log_helper->set_formatter(_formatter);
} }
inline void spdlog::async_logger::_set_pattern(const std::string& pattern, pattern_time_type pattern_time) inline void spdlog::async_logger::_set_pattern(const std::string &pattern, pattern_time_type pattern_time)
{ {
_formatter = std::make_shared<pattern_formatter>(pattern, pattern_time); _formatter = std::make_shared<pattern_formatter>(pattern, pattern_time);
_async_log_helper->set_formatter(_formatter); _async_log_helper->set_formatter(_formatter);
} }
inline void spdlog::async_logger::_sink_it(details::log_msg &msg)
inline void spdlog::async_logger::_sink_it(details::log_msg& msg)
{ {
try try
{ {
...@@ -98,10 +85,9 @@ inline void spdlog::async_logger::_sink_it(details::log_msg& msg) ...@@ -98,10 +85,9 @@ inline void spdlog::async_logger::_sink_it(details::log_msg& msg)
{ {
_err_handler(ex.what()); _err_handler(ex.what());
} }
catch(...) catch (...)
{ {
_err_handler("Unknown exception in logger " + _name); _err_handler("Unknown exception in logger " + _name);
throw; throw;
} }
} }
...@@ -9,20 +9,17 @@ ...@@ -9,20 +9,17 @@
// When failing to open a file, retry several times(5) with small delay between the tries(10 ms) // When failing to open a file, retry several times(5) with small delay between the tries(10 ms)
// Throw spdlog_ex exception on errors // Throw spdlog_ex exception on errors
#include "../details/os.h"
#include "../details/log_msg.h" #include "../details/log_msg.h"
#include "../details/os.h"
#include <cerrno>
#include <chrono> #include <chrono>
#include <cstdio> #include <cstdio>
#include <string> #include <string>
#include <thread> #include <thread>
#include <tuple> #include <tuple>
#include <cerrno>
namespace spdlog namespace spdlog { namespace details {
{
namespace details
{
class file_helper class file_helper
{ {
...@@ -33,16 +30,15 @@ public: ...@@ -33,16 +30,15 @@ public:
explicit file_helper() = default; explicit file_helper() = default;
file_helper(const file_helper&) = delete; file_helper(const file_helper &) = delete;
file_helper& operator=(const file_helper&) = delete; file_helper &operator=(const file_helper &) = delete;
~file_helper() ~file_helper()
{ {
close(); close();
} }
void open(const filename_t &fname, bool truncate = false)
void open(const filename_t& fname, bool truncate = false)
{ {
close(); close();
auto *mode = truncate ? SPDLOG_FILENAME_T("wb") : SPDLOG_FILENAME_T("ab"); auto *mode = truncate ? SPDLOG_FILENAME_T("wb") : SPDLOG_FILENAME_T("ab");
...@@ -63,7 +59,6 @@ public: ...@@ -63,7 +59,6 @@ public:
if (_filename.empty()) if (_filename.empty())
throw spdlog_ex("Failed re opening file - was not opened before"); throw spdlog_ex("Failed re opening file - was not opened before");
open(_filename, truncate); open(_filename, truncate);
} }
void flush() void flush()
...@@ -80,7 +75,7 @@ public: ...@@ -80,7 +75,7 @@ public:
} }
} }
void write(const log_msg& msg) void write(const log_msg &msg)
{ {
size_t msg_size = msg.formatted.size(); size_t msg_size = msg.formatted.size();
auto data = msg.formatted.data(); auto data = msg.formatted.data();
...@@ -97,12 +92,12 @@ public: ...@@ -97,12 +92,12 @@ public:
return os::filesize(_fd); return os::filesize(_fd);
} }
const filename_t& filename() const const filename_t &filename() const
{ {
return _filename; return _filename;
} }
static bool file_exists(const filename_t& fname) static bool file_exists(const filename_t &fname)
{ {
return os::file_exists(fname); return os::file_exists(fname);
} }
...@@ -120,7 +115,7 @@ public: ...@@ -120,7 +115,7 @@ public:
// ".mylog" => (".mylog". "") // ".mylog" => (".mylog". "")
// "my_folder/.mylog" => ("my_folder/.mylog", "") // "my_folder/.mylog" => ("my_folder/.mylog", "")
// "my_folder/.mylog.txt" => ("my_folder/.mylog", ".txt") // "my_folder/.mylog.txt" => ("my_folder/.mylog", ".txt")
static std::tuple<filename_t, filename_t> split_by_extenstion(const spdlog::filename_t& fname) static std::tuple<filename_t, filename_t> split_by_extenstion(const spdlog::filename_t &fname)
{ {
auto ext_index = fname.rfind('.'); auto ext_index = fname.rfind('.');
...@@ -138,8 +133,7 @@ public: ...@@ -138,8 +133,7 @@ public:
} }
private: private:
FILE* _fd{ nullptr }; FILE *_fd{nullptr};
filename_t _filename; filename_t _filename;
}; };
} }} // namespace spdlog::details
}
...@@ -11,16 +11,13 @@ ...@@ -11,16 +11,13 @@
#include <string> #include <string>
#include <utility> #include <utility>
namespace spdlog namespace spdlog { namespace details {
{
namespace details
{
struct log_msg struct log_msg
{ {
log_msg() = default; log_msg() = default;
log_msg(const std::string *loggers_name, level::level_enum lvl) : log_msg(const std::string *loggers_name, level::level_enum lvl)
logger_name(loggers_name), : logger_name(loggers_name)
level(lvl) , level(lvl)
{ {
#ifndef SPDLOG_NO_DATETIME #ifndef SPDLOG_NO_DATETIME
time = os::now(); time = os::now();
...@@ -31,18 +28,16 @@ struct log_msg ...@@ -31,18 +28,16 @@ struct log_msg
#endif #endif
} }
log_msg(const log_msg& other) = delete; log_msg(const log_msg &other) = delete;
log_msg& operator=(log_msg&& other) = delete; log_msg &operator=(log_msg &&other) = delete;
log_msg(log_msg&& other) = delete; log_msg(log_msg &&other) = delete;
const std::string *logger_name{ nullptr }; const std::string *logger_name{nullptr};
level::level_enum level; level::level_enum level;
log_clock::time_point time; log_clock::time_point time;
size_t thread_id; size_t thread_id;
fmt::MemoryWriter raw; fmt::MemoryWriter raw;
fmt::MemoryWriter formatted; fmt::MemoryWriter formatted;
size_t msg_id{ 0 }; size_t msg_id{0};
}; };
} }} // namespace spdlog::details
}
This diff is collapsed.
...@@ -48,23 +48,19 @@ Distributed under the MIT License (http://opensource.org/licenses/MIT) ...@@ -48,23 +48,19 @@ Distributed under the MIT License (http://opensource.org/licenses/MIT)
#include <atomic> #include <atomic>
#include <utility> #include <utility>
namespace spdlog namespace spdlog { namespace details {
{
namespace details
{
template <typename T> template <typename T> class mpmc_bounded_queue
class mpmc_bounded_queue
{ {
public: public:
using item_type = T; using item_type = T;
explicit mpmc_bounded_queue(size_t buffer_size) explicit mpmc_bounded_queue(size_t buffer_size)
:max_size_(buffer_size), : max_size_(buffer_size)
buffer_(new cell_t[buffer_size]), , buffer_(new cell_t[buffer_size])
buffer_mask_(buffer_size - 1) , buffer_mask_(buffer_size - 1)
{ {
//queue size must be power of two // queue size must be power of two
if (!((buffer_size >= 2) && ((buffer_size & (buffer_size - 1)) == 0))) if (!((buffer_size >= 2) && ((buffer_size & (buffer_size - 1)) == 0)))
throw spdlog_ex("async logger queue size must be power of two"); throw spdlog_ex("async logger queue size must be power of two");
...@@ -79,12 +75,12 @@ public: ...@@ -79,12 +75,12 @@ public:
delete[] buffer_; delete[] buffer_;
} }
mpmc_bounded_queue(mpmc_bounded_queue const&) = delete; mpmc_bounded_queue(mpmc_bounded_queue const &) = delete;
void operator=(mpmc_bounded_queue const&) = delete; void operator=(mpmc_bounded_queue const &) = delete;
bool enqueue(T&& data) bool enqueue(T &&data)
{ {
cell_t* cell; cell_t *cell;
size_t pos = enqueue_pos_.load(std::memory_order_relaxed); size_t pos = enqueue_pos_.load(std::memory_order_relaxed);
for (;;) for (;;)
{ {
...@@ -110,15 +106,14 @@ public: ...@@ -110,15 +106,14 @@ public:
return true; return true;
} }
bool dequeue(T& data) bool dequeue(T &data)
{ {
cell_t* cell; cell_t *cell;
size_t pos = dequeue_pos_.load(std::memory_order_relaxed); size_t pos = dequeue_pos_.load(std::memory_order_relaxed);
for (;;) for (;;)
{ {
cell = &buffer_[pos & buffer_mask_]; cell = &buffer_[pos & buffer_mask_];
size_t seq = size_t seq = cell->sequence_.load(std::memory_order_acquire);
cell->sequence_.load(std::memory_order_acquire);
intptr_t dif = static_cast<intptr_t>(seq) - static_cast<intptr_t>(pos + 1); intptr_t dif = static_cast<intptr_t>(seq) - static_cast<intptr_t>(pos + 1);
if (dif == 0) if (dif == 0)
{ {
...@@ -144,8 +139,7 @@ public: ...@@ -144,8 +139,7 @@ public:
front = enqueue_pos_.load(std::memory_order_acquire); front = enqueue_pos_.load(std::memory_order_acquire);
back = dequeue_pos_.load(std::memory_order_acquire); back = dequeue_pos_.load(std::memory_order_acquire);
front1 = enqueue_pos_.load(std::memory_order_relaxed); front1 = enqueue_pos_.load(std::memory_order_relaxed);
} } while (front != front1);
while (front != front1);
return back == front; return back == front;
} }
...@@ -162,7 +156,7 @@ private: ...@@ -162,7 +156,7 @@ private:
using cacheline_pad_t = char[cacheline_size]; using cacheline_pad_t = char[cacheline_size];
cacheline_pad_t pad0_; cacheline_pad_t pad0_;
cell_t* const buffer_; cell_t *const buffer_;
size_t const buffer_mask_; size_t const buffer_mask_;
cacheline_pad_t pad1_; cacheline_pad_t pad1_;
std::atomic<size_t> enqueue_pos_; std::atomic<size_t> enqueue_pos_;
...@@ -171,5 +165,4 @@ private: ...@@ -171,5 +165,4 @@ private:
cacheline_pad_t pad3_; cacheline_pad_t pad3_;
}; };
} // ns details }} // namespace spdlog::details
} // ns spdlog
...@@ -8,10 +8,7 @@ ...@@ -8,10 +8,7 @@
#include <atomic> #include <atomic>
// null, no cost dummy "mutex" and dummy "atomic" int // null, no cost dummy "mutex" and dummy "atomic" int
namespace spdlog namespace spdlog { namespace details {
{
namespace details
{
struct null_mutex struct null_mutex
{ {
void lock() {} void lock() {}
...@@ -27,8 +24,10 @@ struct null_atomic_int ...@@ -27,8 +24,10 @@ struct null_atomic_int
int value; int value;
null_atomic_int() = default; null_atomic_int() = default;
explicit null_atomic_int(int val) : value(val) explicit null_atomic_int(int val)
{} : value(val)
{
}
int load(std::memory_order) const int load(std::memory_order) const
{ {
...@@ -41,5 +40,4 @@ struct null_atomic_int ...@@ -41,5 +40,4 @@ struct null_atomic_int
} }
}; };
} }} // namespace spdlog::details
}
This diff is collapsed.
...@@ -10,10 +10,10 @@ ...@@ -10,10 +10,10 @@
// If user requests a non existing logger, nullptr will be returned // If user requests a non existing logger, nullptr will be returned
// This class is thread safe // This class is thread safe
#include "../details/null_mutex.h"
#include "../logger.h"
#include "../async_logger.h" #include "../async_logger.h"
#include "../common.h" #include "../common.h"
#include "../details/null_mutex.h"
#include "../logger.h"
#include <chrono> #include <chrono>
#include <functional> #include <functional>
...@@ -22,16 +22,12 @@ ...@@ -22,16 +22,12 @@
#include <string> #include <string>
#include <unordered_map> #include <unordered_map>
namespace spdlog namespace spdlog { namespace details {
{ template <class Mutex> class registry_t
namespace details
{
template <class Mutex>
class registry_t
{ {
public: public:
registry_t<Mutex>(const registry_t<Mutex>&) = delete; registry_t<Mutex>(const registry_t<Mutex> &) = delete;
registry_t<Mutex>& operator=(const registry_t<Mutex>&) = delete; registry_t<Mutex> &operator=(const registry_t<Mutex> &) = delete;
void register_logger(std::shared_ptr<logger> logger) void register_logger(std::shared_ptr<logger> logger)
{ {
...@@ -41,21 +37,21 @@ public: ...@@ -41,21 +37,21 @@ public:
_loggers[logger_name] = logger; _loggers[logger_name] = logger;
} }
std::shared_ptr<logger> get(const std::string& logger_name) std::shared_ptr<logger> get(const std::string &logger_name)
{ {
std::lock_guard<Mutex> lock(_mutex); std::lock_guard<Mutex> lock(_mutex);
auto found = _loggers.find(logger_name); auto found = _loggers.find(logger_name);
return found == _loggers.end() ? nullptr : found->second; return found == _loggers.end() ? nullptr : found->second;
} }
template<class It> template <class It> std::shared_ptr<logger> create(const std::string &logger_name, const It &sinks_begin, const It &sinks_end)
std::shared_ptr<logger> create(const std::string& logger_name, const It& sinks_begin, const It& sinks_end)
{ {
std::lock_guard<Mutex> lock(_mutex); std::lock_guard<Mutex> lock(_mutex);
throw_if_exists(logger_name); throw_if_exists(logger_name);
std::shared_ptr<logger> new_logger; std::shared_ptr<logger> new_logger;
if (_async_mode) if (_async_mode)
new_logger = std::make_shared<async_logger>(logger_name, sinks_begin, sinks_end, _async_q_size, _overflow_policy, _worker_warmup_cb, _flush_interval_ms, _worker_teardown_cb); new_logger = std::make_shared<async_logger>(logger_name, sinks_begin, sinks_end, _async_q_size, _overflow_policy,
_worker_warmup_cb, _flush_interval_ms, _worker_teardown_cb);
else else
new_logger = std::make_shared<logger>(logger_name, sinks_begin, sinks_end); new_logger = std::make_shared<logger>(logger_name, sinks_begin, sinks_end);
...@@ -68,18 +64,21 @@ public: ...@@ -68,18 +64,21 @@ public:
new_logger->set_level(_level); new_logger->set_level(_level);
new_logger->flush_on(_flush_level); new_logger->flush_on(_flush_level);
// Add to registry
//Add to registry
_loggers[logger_name] = new_logger; _loggers[logger_name] = new_logger;
return new_logger; return new_logger;
} }
template<class It> template <class It>
std::shared_ptr<async_logger> create_async(const std::string& logger_name, size_t queue_size, const async_overflow_policy overflow_policy, const std::function<void()>& worker_warmup_cb, const std::chrono::milliseconds& flush_interval_ms, const std::function<void()>& worker_teardown_cb, const It& sinks_begin, const It& sinks_end) std::shared_ptr<async_logger> create_async(const std::string &logger_name, size_t queue_size,
const async_overflow_policy overflow_policy, const std::function<void()> &worker_warmup_cb,
const std::chrono::milliseconds &flush_interval_ms, const std::function<void()> &worker_teardown_cb, const It &sinks_begin,
const It &sinks_end)
{ {
std::lock_guard<Mutex> lock(_mutex); std::lock_guard<Mutex> lock(_mutex);
throw_if_exists(logger_name); throw_if_exists(logger_name);
auto new_logger = std::make_shared<async_logger>(logger_name, sinks_begin, sinks_end, queue_size, overflow_policy, worker_warmup_cb, flush_interval_ms, worker_teardown_cb); auto new_logger = std::make_shared<async_logger>(
logger_name, sinks_begin, sinks_end, queue_size, overflow_policy, worker_warmup_cb, flush_interval_ms, worker_teardown_cb);
if (_formatter) if (_formatter)
new_logger->set_formatter(_formatter); new_logger->set_formatter(_formatter);
...@@ -90,7 +89,7 @@ public: ...@@ -90,7 +89,7 @@ public:
new_logger->set_level(_level); new_logger->set_level(_level);
new_logger->flush_on(_flush_level); new_logger->flush_on(_flush_level);
//Add to registry // Add to registry
_loggers[logger_name] = new_logger; _loggers[logger_name] = new_logger;
return new_logger; return new_logger;
} }
...@@ -102,7 +101,7 @@ public: ...@@ -102,7 +101,7 @@ public:
fun(l.second); fun(l.second);
} }
void drop(const std::string& logger_name) void drop(const std::string &logger_name)
{ {
std::lock_guard<Mutex> lock(_mutex); std::lock_guard<Mutex> lock(_mutex);
_loggers.erase(logger_name); _loggers.erase(logger_name);
...@@ -114,46 +113,51 @@ public: ...@@ -114,46 +113,51 @@ public:
_loggers.clear(); _loggers.clear();
} }
std::shared_ptr<logger> create(const std::string& logger_name, sinks_init_list sinks) std::shared_ptr<logger> create(const std::string &logger_name, sinks_init_list sinks)
{ {
return create(logger_name, sinks.begin(), sinks.end()); return create(logger_name, sinks.begin(), sinks.end());
} }
std::shared_ptr<logger> create(const std::string& logger_name, sink_ptr sink) std::shared_ptr<logger> create(const std::string &logger_name, sink_ptr sink)
{ {
return create(logger_name, { sink }); return create(logger_name, {sink});
} }
std::shared_ptr<async_logger> create_async(const std::string& logger_name, size_t queue_size, const async_overflow_policy overflow_policy, const std::function<void()>& worker_warmup_cb, const std::chrono::milliseconds& flush_interval_ms, const std::function<void()>& worker_teardown_cb, sinks_init_list sinks) std::shared_ptr<async_logger> create_async(const std::string &logger_name, size_t queue_size,
const async_overflow_policy overflow_policy, const std::function<void()> &worker_warmup_cb,
const std::chrono::milliseconds &flush_interval_ms, const std::function<void()> &worker_teardown_cb, sinks_init_list sinks)
{ {
return create_async(logger_name, queue_size, overflow_policy, worker_warmup_cb, flush_interval_ms, worker_teardown_cb, sinks.begin(), sinks.end()); return create_async(
logger_name, queue_size, overflow_policy, worker_warmup_cb, flush_interval_ms, worker_teardown_cb, sinks.begin(), sinks.end());
} }
std::shared_ptr<async_logger> create_async(const std::string& logger_name, size_t queue_size, const async_overflow_policy overflow_policy, const std::function<void()>& worker_warmup_cb, const std::chrono::milliseconds& flush_interval_ms, const std::function<void()>& worker_teardown_cb, sink_ptr sink) std::shared_ptr<async_logger> create_async(const std::string &logger_name, size_t queue_size,
const async_overflow_policy overflow_policy, const std::function<void()> &worker_warmup_cb,
const std::chrono::milliseconds &flush_interval_ms, const std::function<void()> &worker_teardown_cb, sink_ptr sink)
{ {
return create_async(logger_name, queue_size, overflow_policy, worker_warmup_cb, flush_interval_ms, worker_teardown_cb, { sink }); return create_async(logger_name, queue_size, overflow_policy, worker_warmup_cb, flush_interval_ms, worker_teardown_cb, {sink});
} }
void formatter(formatter_ptr f) void formatter(formatter_ptr f)
{ {
std::lock_guard<Mutex> lock(_mutex); std::lock_guard<Mutex> lock(_mutex);
_formatter = f; _formatter = f;
for (auto& l : _loggers) for (auto &l : _loggers)
l.second->set_formatter(_formatter); l.second->set_formatter(_formatter);
} }
void set_pattern(const std::string& pattern) void set_pattern(const std::string &pattern)
{ {
std::lock_guard<Mutex> lock(_mutex); std::lock_guard<Mutex> lock(_mutex);
_formatter = std::make_shared<pattern_formatter>(pattern); _formatter = std::make_shared<pattern_formatter>(pattern);
for (auto& l : _loggers) for (auto &l : _loggers)
l.second->set_formatter(_formatter); l.second->set_formatter(_formatter);
} }
void set_level(level::level_enum log_level) void set_level(level::level_enum log_level)
{ {
std::lock_guard<Mutex> lock(_mutex); std::lock_guard<Mutex> lock(_mutex);
for (auto& l : _loggers) for (auto &l : _loggers)
l.second->set_level(log_level); l.second->set_level(log_level);
_level = log_level; _level = log_level;
} }
...@@ -161,19 +165,20 @@ public: ...@@ -161,19 +165,20 @@ public:
void flush_on(level::level_enum log_level) void flush_on(level::level_enum log_level)
{ {
std::lock_guard<Mutex> lock(_mutex); std::lock_guard<Mutex> lock(_mutex);
for (auto& l : _loggers) for (auto &l : _loggers)
l.second->flush_on(log_level); l.second->flush_on(log_level);
_flush_level = log_level; _flush_level = log_level;
} }
void set_error_handler(log_err_handler handler) void set_error_handler(log_err_handler handler)
{ {
for (auto& l : _loggers) for (auto &l : _loggers)
l.second->set_error_handler(handler); l.second->set_error_handler(handler);
_err_handler = handler; _err_handler = handler;
} }
void set_async_mode(size_t q_size, const async_overflow_policy overflow_policy, const std::function<void()>& worker_warmup_cb, const std::chrono::milliseconds& flush_interval_ms, const std::function<void()>& worker_teardown_cb) void set_async_mode(size_t q_size, const async_overflow_policy overflow_policy, const std::function<void()> &worker_warmup_cb,
const std::chrono::milliseconds &flush_interval_ms, const std::function<void()> &worker_teardown_cb)
{ {
std::lock_guard<Mutex> lock(_mutex); std::lock_guard<Mutex> lock(_mutex);
_async_mode = true; _async_mode = true;
...@@ -190,7 +195,7 @@ public: ...@@ -190,7 +195,7 @@ public:
_async_mode = false; _async_mode = false;
} }
static registry_t<Mutex>& instance() static registry_t<Mutex> &instance()
{ {
static registry_t<Mutex> s_instance; static registry_t<Mutex> s_instance;
return s_instance; return s_instance;
...@@ -206,7 +211,7 @@ private: ...@@ -206,7 +211,7 @@ private:
} }
Mutex _mutex; Mutex _mutex;
std::unordered_map <std::string, std::shared_ptr<logger>> _loggers; std::unordered_map<std::string, std::shared_ptr<logger>> _loggers;
formatter_ptr _formatter; formatter_ptr _formatter;
level::level_enum _level = level::info; level::level_enum _level = level::info;
level::level_enum _flush_level = level::off; level::level_enum _flush_level = level::off;
...@@ -225,5 +230,4 @@ using registry = registry_t<spdlog::details::null_mutex>; ...@@ -225,5 +230,4 @@ using registry = registry_t<spdlog::details::null_mutex>;
using registry = registry_t<std::mutex>; using registry = registry_t<std::mutex>;
#endif #endif
} }} // namespace spdlog::details
}
This diff is collapsed.
This diff is collapsed.
...@@ -13,14 +13,11 @@ ...@@ -13,14 +13,11 @@
#include "format.h" #include "format.h"
#include <ostream> #include <ostream>
namespace fmt namespace fmt {
{
namespace internal namespace internal {
{
template <class Char> template <class Char> class FormatBuf : public std::basic_streambuf<Char>
class FormatBuf : public std::basic_streambuf<Char>
{ {
private: private:
typedef typename std::basic_streambuf<Char>::int_type int_type; typedef typename std::basic_streambuf<Char>::int_type int_type;
...@@ -29,7 +26,10 @@ private: ...@@ -29,7 +26,10 @@ private:
Buffer<Char> &buffer_; Buffer<Char> &buffer_;
public: public:
FormatBuf(Buffer<Char> &buffer) : buffer_(buffer) {} FormatBuf(Buffer<Char> &buffer)
: buffer_(buffer)
{
}
protected: protected:
// The put-area is actually always empty. This makes the implementation // The put-area is actually always empty. This makes the implementation
...@@ -60,14 +60,12 @@ struct DummyStream : std::ostream ...@@ -60,14 +60,12 @@ struct DummyStream : std::ostream
DummyStream(); // Suppress a bogus warning in MSVC. DummyStream(); // Suppress a bogus warning in MSVC.
// Hide all operator<< overloads from std::ostream. // Hide all operator<< overloads from std::ostream.
template <typename T> template <typename T> typename EnableIf<sizeof(T) == 0>::type operator<<(const T &);
typename EnableIf<sizeof(T) == 0>::type operator<<(const T &);
}; };
No &operator<<(std::ostream &, int); No &operator<<(std::ostream &, int);
template <typename T> template <typename T> struct ConvertToIntImpl<T, true>
struct ConvertToIntImpl<T, true>
{ {
// Convert to int only if T doesn't have an overloaded operator<<. // Convert to int only if T doesn't have an overloaded operator<<.
enum enum
...@@ -82,8 +80,7 @@ FMT_API void write(std::ostream &os, Writer &w); ...@@ -82,8 +80,7 @@ FMT_API void write(std::ostream &os, Writer &w);
// Formats a value. // Formats a value.
template <typename Char, typename ArgFormatter_, typename T> template <typename Char, typename ArgFormatter_, typename T>
void format_arg(BasicFormatter<Char, ArgFormatter_> &f, void format_arg(BasicFormatter<Char, ArgFormatter_> &f, const Char *&format_str, const T &value)
const Char *&format_str, const T &value)
{ {
internal::MemoryBuffer<Char, internal::INLINE_BUFFER_SIZE> buffer; internal::MemoryBuffer<Char, internal::INLINE_BUFFER_SIZE> buffer;
...@@ -93,7 +90,7 @@ void format_arg(BasicFormatter<Char, ArgFormatter_> &f, ...@@ -93,7 +90,7 @@ void format_arg(BasicFormatter<Char, ArgFormatter_> &f,
output << value; output << value;
BasicStringRef<Char> str(&buffer[0], buffer.size()); BasicStringRef<Char> str(&buffer[0], buffer.size());
typedef internal::MakeArg< BasicFormatter<Char> > MakeArg; typedef internal::MakeArg<BasicFormatter<Char>> MakeArg;
format_str = f.format(format_str, MakeArg(str)); format_str = f.format(format_str, MakeArg(str));
} }
...@@ -111,7 +108,7 @@ FMT_VARIADIC(void, print, std::ostream &, CStringRef) ...@@ -111,7 +108,7 @@ FMT_VARIADIC(void, print, std::ostream &, CStringRef)
} // namespace fmt } // namespace fmt
#ifdef FMT_HEADER_ONLY #ifdef FMT_HEADER_ONLY
# include "ostream.cc" #include "ostream.cc"
#endif #endif
#endif // FMT_OSTREAM_H_ #endif // FMT_OSTREAM_H_
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
#if defined(__MINGW32__) || defined(__CYGWIN__) #if defined(__MINGW32__) || defined(__CYGWIN__)
// Workaround MinGW bug https://sourceforge.net/p/mingw/bugs/2024/. // Workaround MinGW bug https://sourceforge.net/p/mingw/bugs/2024/.
# undef __STRICT_ANSI__ #undef __STRICT_ANSI__
#endif #endif
#include <errno.h> #include <errno.h>
...@@ -24,48 +24,48 @@ ...@@ -24,48 +24,48 @@
#include <cstddef> #include <cstddef>
#if defined __APPLE__ || defined(__FreeBSD__) #if defined __APPLE__ || defined(__FreeBSD__)
# include <xlocale.h> // for LC_NUMERIC_MASK on OS X #include <xlocale.h> // for LC_NUMERIC_MASK on OS X
#endif #endif
#include "format.h" #include "format.h"
#ifndef FMT_POSIX #ifndef FMT_POSIX
# if defined(_WIN32) && !defined(__MINGW32__) #if defined(_WIN32) && !defined(__MINGW32__)
// Fix warnings about deprecated symbols. // Fix warnings about deprecated symbols.
# define FMT_POSIX(call) _##call #define FMT_POSIX(call) _##call
# else #else
# define FMT_POSIX(call) call #define FMT_POSIX(call) call
# endif #endif
#endif #endif
// Calls to system functions are wrapped in FMT_SYSTEM for testability. // Calls to system functions are wrapped in FMT_SYSTEM for testability.
#ifdef FMT_SYSTEM #ifdef FMT_SYSTEM
# define FMT_POSIX_CALL(call) FMT_SYSTEM(call) #define FMT_POSIX_CALL(call) FMT_SYSTEM(call)
#else #else
# define FMT_SYSTEM(call) call #define FMT_SYSTEM(call) call
# ifdef _WIN32 #ifdef _WIN32
// Fix warnings about deprecated symbols. // Fix warnings about deprecated symbols.
# define FMT_POSIX_CALL(call) ::_##call #define FMT_POSIX_CALL(call) ::_##call
# else #else
# define FMT_POSIX_CALL(call) ::call #define FMT_POSIX_CALL(call) ::call
# endif #endif
#endif #endif
// Retries the expression while it evaluates to error_result and errno // Retries the expression while it evaluates to error_result and errno
// equals to EINTR. // equals to EINTR.
#ifndef _WIN32 #ifndef _WIN32
# define FMT_RETRY_VAL(result, expression, error_result) \ #define FMT_RETRY_VAL(result, expression, error_result) \
do { \ do \
{ \
result = (expression); \ result = (expression); \
} while (result == error_result && errno == EINTR) } while (result == error_result && errno == EINTR)
#else #else
# define FMT_RETRY_VAL(result, expression, error_result) result = (expression) #define FMT_RETRY_VAL(result, expression, error_result) result = (expression)
#endif #endif
#define FMT_RETRY(result, expression) FMT_RETRY_VAL(result, expression, -1) #define FMT_RETRY(result, expression) FMT_RETRY_VAL(result, expression, -1)
namespace fmt namespace fmt {
{
// An error code. // An error code.
class ErrorCode class ErrorCode
...@@ -74,8 +74,7 @@ private: ...@@ -74,8 +74,7 @@ private:
int value_; int value_;
public: public:
explicit ErrorCode(int value = 0) FMT_NOEXCEPT : explicit ErrorCode(int value = 0) FMT_NOEXCEPT : value_(value) {}
value_(value) {}
int get() const FMT_NOEXCEPT int get() const FMT_NOEXCEPT
{ {
...@@ -91,12 +90,14 @@ private: ...@@ -91,12 +90,14 @@ private:
friend class File; friend class File;
explicit BufferedFile(FILE *f) : file_(f) {} explicit BufferedFile(FILE *f)
: file_(f)
{
}
public: public:
// Constructs a BufferedFile object which doesn't represent any file. // Constructs a BufferedFile object which doesn't represent any file.
BufferedFile() FMT_NOEXCEPT : BufferedFile() FMT_NOEXCEPT : file_(FMT_NULL) {}
file_(FMT_NULL) {}
// Destroys the object closing the file it represents if any. // Destroys the object closing the file it represents if any.
FMT_API ~BufferedFile() FMT_NOEXCEPT; FMT_API ~BufferedFile() FMT_NOEXCEPT;
...@@ -115,12 +116,10 @@ private: ...@@ -115,12 +116,10 @@ private:
public: public:
// A "move constructor" for moving from a temporary. // A "move constructor" for moving from a temporary.
BufferedFile(Proxy p) FMT_NOEXCEPT : BufferedFile(Proxy p) FMT_NOEXCEPT : file_(p.file) {}
file_(p.file) {}
// A "move constructor" for moving from an lvalue. // A "move constructor" for moving from an lvalue.
BufferedFile(BufferedFile &f) FMT_NOEXCEPT : BufferedFile(BufferedFile &f) FMT_NOEXCEPT : file_(f.file_)
file_(f.file_)
{ {
f.file_ = FMT_NULL; f.file_ = FMT_NULL;
} }
...@@ -156,13 +155,12 @@ private: ...@@ -156,13 +155,12 @@ private:
FMT_DISALLOW_COPY_AND_ASSIGN(BufferedFile); FMT_DISALLOW_COPY_AND_ASSIGN(BufferedFile);
public: public:
BufferedFile(BufferedFile &&other) FMT_NOEXCEPT : BufferedFile(BufferedFile &&other) FMT_NOEXCEPT : file_(other.file_)
file_(other.file_)
{ {
other.file_ = FMT_NULL; other.file_ = FMT_NULL;
} }
BufferedFile& operator=(BufferedFile &&other) BufferedFile &operator=(BufferedFile &&other)
{ {
close(); close();
file_ = other.file_; file_ = other.file_;
...@@ -185,7 +183,7 @@ BufferedFile(BufferedFile &&other) FMT_NOEXCEPT : ...@@ -185,7 +183,7 @@ BufferedFile(BufferedFile &&other) FMT_NOEXCEPT :
// We place parentheses around fileno to workaround a bug in some versions // We place parentheses around fileno to workaround a bug in some versions
// of MinGW that define fileno as a macro. // of MinGW that define fileno as a macro.
FMT_API int (fileno)() const; FMT_API int(fileno)() const;
void print(CStringRef format_str, const ArgList &args) void print(CStringRef format_str, const ArgList &args)
{ {
...@@ -206,7 +204,10 @@ private: ...@@ -206,7 +204,10 @@ private:
int fd_; // File descriptor. int fd_; // File descriptor.
// Constructs a File object with a given descriptor. // Constructs a File object with a given descriptor.
explicit File(int fd) : fd_(fd) {} explicit File(int fd)
: fd_(fd)
{
}
public: public:
// Possible values for the oflag argument to the constructor. // Possible values for the oflag argument to the constructor.
...@@ -218,8 +219,7 @@ public: ...@@ -218,8 +219,7 @@ public:
}; };
// Constructs a File object which doesn't represent any file. // Constructs a File object which doesn't represent any file.
File() FMT_NOEXCEPT : File() FMT_NOEXCEPT : fd_(-1) {}
fd_(-1) {}
// Opens a file and constructs a File object representing this file. // Opens a file and constructs a File object representing this file.
FMT_API File(CStringRef path, int oflag); FMT_API File(CStringRef path, int oflag);
...@@ -238,12 +238,10 @@ private: ...@@ -238,12 +238,10 @@ private:
public: public:
// A "move constructor" for moving from a temporary. // A "move constructor" for moving from a temporary.
File(Proxy p) FMT_NOEXCEPT : File(Proxy p) FMT_NOEXCEPT : fd_(p.fd) {}
fd_(p.fd) {}
// A "move constructor" for moving from an lvalue. // A "move constructor" for moving from an lvalue.
File(File &other) FMT_NOEXCEPT : File(File &other) FMT_NOEXCEPT : fd_(other.fd_)
fd_(other.fd_)
{ {
other.fd_ = -1; other.fd_ = -1;
} }
...@@ -279,13 +277,12 @@ private: ...@@ -279,13 +277,12 @@ private:
FMT_DISALLOW_COPY_AND_ASSIGN(File); FMT_DISALLOW_COPY_AND_ASSIGN(File);
public: public:
File(File &&other) FMT_NOEXCEPT : File(File &&other) FMT_NOEXCEPT : fd_(other.fd_)
fd_(other.fd_)
{ {
other.fd_ = -1; other.fd_ = -1;
} }
File& operator=(File &&other) File &operator=(File &&other)
{ {
close(); close();
fd_ = other.fd_; fd_ = other.fd_;
...@@ -340,9 +337,8 @@ File(File &&other) FMT_NOEXCEPT : ...@@ -340,9 +337,8 @@ File(File &&other) FMT_NOEXCEPT :
// Returns the memory page size. // Returns the memory page size.
long getpagesize(); long getpagesize();
#if (defined(LC_NUMERIC_MASK) || defined(_MSC_VER)) && \ #if (defined(LC_NUMERIC_MASK) || defined(_MSC_VER)) && !defined(__ANDROID__) && !defined(__CYGWIN__)
!defined(__ANDROID__) && !defined(__CYGWIN__) #define FMT_LOCALE
# define FMT_LOCALE
#endif #endif
#ifdef FMT_LOCALE #ifdef FMT_LOCALE
...@@ -350,10 +346,13 @@ long getpagesize(); ...@@ -350,10 +346,13 @@ long getpagesize();
class Locale class Locale
{ {
private: private:
# ifdef _MSC_VER #ifdef _MSC_VER
typedef _locale_t locale_t; typedef _locale_t locale_t;
enum { LC_NUMERIC_MASK = LC_NUMERIC }; enum
{
LC_NUMERIC_MASK = LC_NUMERIC
};
static locale_t newlocale(int category_mask, const char *locale, locale_t) static locale_t newlocale(int category_mask, const char *locale, locale_t)
{ {
...@@ -369,7 +368,7 @@ private: ...@@ -369,7 +368,7 @@ private:
{ {
return _strtod_l(nptr, endptr, locale); return _strtod_l(nptr, endptr, locale);
} }
# endif #endif
locale_t locale_; locale_t locale_;
...@@ -378,7 +377,8 @@ private: ...@@ -378,7 +377,8 @@ private:
public: public:
typedef locale_t Type; typedef locale_t Type;
Locale() : locale_(newlocale(LC_NUMERIC_MASK, "C", FMT_NULL)) Locale()
: locale_(newlocale(LC_NUMERIC_MASK, "C", FMT_NULL))
{ {
if (!locale_) if (!locale_)
FMT_THROW(fmt::SystemError(errno, "cannot create locale")); FMT_THROW(fmt::SystemError(errno, "cannot create locale"));
...@@ -407,8 +407,7 @@ public: ...@@ -407,8 +407,7 @@ public:
} // namespace fmt } // namespace fmt
#if !FMT_USE_RVALUE_REFERENCES #if !FMT_USE_RVALUE_REFERENCES
namespace std namespace std {
{
// For compatibility with C++98. // For compatibility with C++98.
inline fmt::BufferedFile &move(fmt::BufferedFile &f) inline fmt::BufferedFile &move(fmt::BufferedFile &f)
{ {
...@@ -418,7 +417,7 @@ inline fmt::File &move(fmt::File &f) ...@@ -418,7 +417,7 @@ inline fmt::File &move(fmt::File &f)
{ {
return f; return f;
} }
} } // namespace std
#endif #endif
#endif // FMT_POSIX_H_ #endif // FMT_POSIX_H_
...@@ -15,18 +15,14 @@ ...@@ -15,18 +15,14 @@
#include "ostream.h" #include "ostream.h"
namespace fmt namespace fmt {
{ namespace internal {
namespace internal
{
// Checks if a value fits in int - used to avoid warnings about comparing // Checks if a value fits in int - used to avoid warnings about comparing
// signed and unsigned integers. // signed and unsigned integers.
template <bool IsSigned> template <bool IsSigned> struct IntChecker
struct IntChecker
{ {
template <typename T> template <typename T> static bool fits_in_int(T value)
static bool fits_in_int(T value)
{ {
unsigned max = std::numeric_limits<int>::max(); unsigned max = std::numeric_limits<int>::max();
return value <= max; return value <= max;
...@@ -37,14 +33,11 @@ struct IntChecker ...@@ -37,14 +33,11 @@ struct IntChecker
} }
}; };
template <> template <> struct IntChecker<true>
struct IntChecker<true>
{ {
template <typename T> template <typename T> static bool fits_in_int(T value)
static bool fits_in_int(T value)
{ {
return value >= std::numeric_limits<int>::min() && return value >= std::numeric_limits<int>::min() && value <= std::numeric_limits<int>::max();
value <= std::numeric_limits<int>::max();
} }
static bool fits_in_int(int) static bool fits_in_int(int)
{ {
...@@ -60,8 +53,7 @@ public: ...@@ -60,8 +53,7 @@ public:
FMT_THROW(FormatError("precision is not integer")); FMT_THROW(FormatError("precision is not integer"));
} }
template <typename T> template <typename T> int visit_any_int(T value)
int visit_any_int(T value)
{ {
if (!IntChecker<std::numeric_limits<T>::is_signed>::fits_in_int(value)) if (!IntChecker<std::numeric_limits<T>::is_signed>::fits_in_int(value))
FMT_THROW(FormatError("number is too big")); FMT_THROW(FormatError("number is too big"));
...@@ -73,8 +65,7 @@ public: ...@@ -73,8 +65,7 @@ public:
class IsZeroInt : public ArgVisitor<IsZeroInt, bool> class IsZeroInt : public ArgVisitor<IsZeroInt, bool>
{ {
public: public:
template <typename T> template <typename T> bool visit_any_int(T value)
bool visit_any_int(T value)
{ {
return value == 0; return value == 0;
} }
...@@ -99,14 +90,12 @@ public: ...@@ -99,14 +90,12 @@ public:
return 'p'; return 'p';
} }
template <typename T> template <typename T> char visit_any_int(T)
char visit_any_int(T)
{ {
return 'd'; return 'd';
} }
template <typename T> template <typename T> char visit_any_double(T)
char visit_any_double(T)
{ {
return 'g'; return 'g';
} }
...@@ -117,24 +106,27 @@ public: ...@@ -117,24 +106,27 @@ public:
} }
}; };
template <typename T, typename U> template <typename T, typename U> struct is_same
struct is_same
{ {
enum { value = 0 }; enum
{
value = 0
};
}; };
template <typename T> template <typename T> struct is_same<T, T>
struct is_same<T, T>
{ {
enum { value = 1 }; enum
{
value = 1
};
}; };
// An argument visitor that converts an integer argument to T for printf, // An argument visitor that converts an integer argument to T for printf,
// if T is an integral type. If T is void, the argument is converted to // if T is an integral type. If T is void, the argument is converted to
// corresponding signed or unsigned type depending on the type specifier: // corresponding signed or unsigned type depending on the type specifier:
// 'd' and 'i' - signed, other - unsigned) // 'd' and 'i' - signed, other - unsigned)
template <typename T = void> template <typename T = void> class ArgConverter : public ArgVisitor<ArgConverter<T>, void>
class ArgConverter : public ArgVisitor<ArgConverter<T>, void>
{ {
private: private:
internal::Arg &arg_; internal::Arg &arg_;
...@@ -144,7 +136,10 @@ private: ...@@ -144,7 +136,10 @@ private:
public: public:
ArgConverter(internal::Arg &arg, wchar_t type) ArgConverter(internal::Arg &arg, wchar_t type)
: arg_(arg), type_(type) {} : arg_(arg)
, type_(type)
{
}
void visit_bool(bool value) void visit_bool(bool value)
{ {
...@@ -158,8 +153,7 @@ public: ...@@ -158,8 +153,7 @@ public:
visit_any_int(value); visit_any_int(value);
} }
template <typename U> template <typename U> void visit_any_int(U value)
void visit_any_int(U value)
{ {
bool is_signed = type_ == 'd' || type_ == 'i'; bool is_signed = type_ == 'd' || type_ == 'i';
if (type_ == 's') if (type_ == 's')
...@@ -168,8 +162,7 @@ public: ...@@ -168,8 +162,7 @@ public:
} }
using internal::Arg; using internal::Arg;
typedef typename internal::Conditional< typedef typename internal::Conditional<is_same<T, void>::value, U, T>::type TargetType;
is_same<T, void>::value, U, T>::type TargetType;
if (const_check(sizeof(TargetType) <= sizeof(int))) if (const_check(sizeof(TargetType) <= sizeof(int)))
{ {
// Extra casts are used to silence warnings. // Extra casts are used to silence warnings.
...@@ -198,8 +191,7 @@ public: ...@@ -198,8 +191,7 @@ public:
else else
{ {
arg_.type = Arg::ULONG_LONG; arg_.type = Arg::ULONG_LONG;
arg_.ulong_long_value = arg_.ulong_long_value = static_cast<typename internal::MakeUnsigned<U>::Type>(value);
static_cast<typename internal::MakeUnsigned<U>::Type>(value);
} }
} }
} }
...@@ -214,10 +206,12 @@ private: ...@@ -214,10 +206,12 @@ private:
FMT_DISALLOW_COPY_AND_ASSIGN(CharConverter); FMT_DISALLOW_COPY_AND_ASSIGN(CharConverter);
public: public:
explicit CharConverter(internal::Arg &arg) : arg_(arg) {} explicit CharConverter(internal::Arg &arg)
: arg_(arg)
{
}
template <typename T> template <typename T> void visit_any_int(T value)
void visit_any_int(T value)
{ {
arg_.type = internal::Arg::CHAR; arg_.type = internal::Arg::CHAR;
arg_.int_value = static_cast<char>(value); arg_.int_value = static_cast<char>(value);
...@@ -234,15 +228,17 @@ private: ...@@ -234,15 +228,17 @@ private:
FMT_DISALLOW_COPY_AND_ASSIGN(WidthHandler); FMT_DISALLOW_COPY_AND_ASSIGN(WidthHandler);
public: public:
explicit WidthHandler(FormatSpec &spec) : spec_(spec) {} explicit WidthHandler(FormatSpec &spec)
: spec_(spec)
{
}
void report_unhandled_arg() void report_unhandled_arg()
{ {
FMT_THROW(FormatError("width is not integer")); FMT_THROW(FormatError("width is not integer"));
} }
template <typename T> template <typename T> unsigned visit_any_int(T value)
unsigned visit_any_int(T value)
{ {
typedef typename internal::IntTraits<T>::MainType UnsignedType; typedef typename internal::IntTraits<T>::MainType UnsignedType;
UnsignedType width = static_cast<UnsignedType>(value); UnsignedType width = static_cast<UnsignedType>(value);
...@@ -276,9 +272,7 @@ public: ...@@ -276,9 +272,7 @@ public:
superclass will be called. superclass will be called.
\endrst \endrst
*/ */
template <typename Impl, typename Char, typename Spec> template <typename Impl, typename Char, typename Spec> class BasicPrintfArgFormatter : public internal::ArgFormatterBase<Impl, Char, Spec>
class BasicPrintfArgFormatter :
public internal::ArgFormatterBase<Impl, Char, Spec>
{ {
private: private:
void write_null_pointer() void write_null_pointer()
...@@ -298,7 +292,9 @@ public: ...@@ -298,7 +292,9 @@ public:
\endrst \endrst
*/ */
BasicPrintfArgFormatter(BasicWriter<Char> &w, Spec &s) BasicPrintfArgFormatter(BasicWriter<Char> &w, Spec &s)
: internal::ArgFormatterBase<Impl, Char, Spec>(w, s) {} : internal::ArgFormatterBase<Impl, Char, Spec>(w, s)
{
}
/** Formats an argument of type ``bool``. */ /** Formats an argument of type ``bool``. */
void visit_bool(bool value) void visit_bool(bool value)
...@@ -371,19 +367,18 @@ public: ...@@ -371,19 +367,18 @@ public:
}; };
/** The default printf argument formatter. */ /** The default printf argument formatter. */
template <typename Char> template <typename Char> class PrintfArgFormatter : public BasicPrintfArgFormatter<PrintfArgFormatter<Char>, Char, FormatSpec>
class PrintfArgFormatter :
public BasicPrintfArgFormatter<PrintfArgFormatter<Char>, Char, FormatSpec>
{ {
public: public:
/** Constructs an argument formatter object. */ /** Constructs an argument formatter object. */
PrintfArgFormatter(BasicWriter<Char> &w, FormatSpec &s) PrintfArgFormatter(BasicWriter<Char> &w, FormatSpec &s)
: BasicPrintfArgFormatter<PrintfArgFormatter<Char>, Char, FormatSpec>(w, s) {} : BasicPrintfArgFormatter<PrintfArgFormatter<Char>, Char, FormatSpec>(w, s)
{
}
}; };
/** This template formats data and writes the output to a writer. */ /** This template formats data and writes the output to a writer. */
template <typename Char, typename ArgFormatter = PrintfArgFormatter<Char> > template <typename Char, typename ArgFormatter = PrintfArgFormatter<Char>> class PrintfFormatter : private internal::FormatterBase
class PrintfFormatter : private internal::FormatterBase
{ {
private: private:
BasicWriter<Char> &writer_; BasicWriter<Char> &writer_;
...@@ -392,9 +387,7 @@ private: ...@@ -392,9 +387,7 @@ private:
// Returns the argument with specified index or, if arg_index is equal // Returns the argument with specified index or, if arg_index is equal
// to the maximum unsigned value, the next argument. // to the maximum unsigned value, the next argument.
internal::Arg get_arg( internal::Arg get_arg(const Char *s, unsigned arg_index = (std::numeric_limits<unsigned>::max)());
const Char *s,
unsigned arg_index = (std::numeric_limits<unsigned>::max)());
// Parses argument index, flags and width and returns the argument index. // Parses argument index, flags and width and returns the argument index.
unsigned parse_header(const Char *&s, FormatSpec &spec); unsigned parse_header(const Char *&s, FormatSpec &spec);
...@@ -408,14 +401,16 @@ public: ...@@ -408,14 +401,16 @@ public:
\endrst \endrst
*/ */
explicit PrintfFormatter(const ArgList &al, BasicWriter<Char> &w) explicit PrintfFormatter(const ArgList &al, BasicWriter<Char> &w)
: FormatterBase(al), writer_(w) {} : FormatterBase(al)
, writer_(w)
{
}
/** Formats stored arguments and writes the output to the writer. */ /** Formats stored arguments and writes the output to the writer. */
void format(BasicCStringRef<Char> format_str); void format(BasicCStringRef<Char> format_str);
}; };
template <typename Char, typename AF> template <typename Char, typename AF> void PrintfFormatter<Char, AF>::parse_flags(FormatSpec &spec, const Char *&s)
void PrintfFormatter<Char, AF>::parse_flags(FormatSpec &spec, const Char *&s)
{ {
for (;;) for (;;)
{ {
...@@ -443,22 +438,17 @@ void PrintfFormatter<Char, AF>::parse_flags(FormatSpec &spec, const Char *&s) ...@@ -443,22 +438,17 @@ void PrintfFormatter<Char, AF>::parse_flags(FormatSpec &spec, const Char *&s)
} }
} }
template <typename Char, typename AF> template <typename Char, typename AF> internal::Arg PrintfFormatter<Char, AF>::get_arg(const Char *s, unsigned arg_index)
internal::Arg PrintfFormatter<Char, AF>::get_arg(const Char *s,
unsigned arg_index)
{ {
(void)s; (void)s;
const char *error = FMT_NULL; const char *error = FMT_NULL;
internal::Arg arg = arg_index == std::numeric_limits<unsigned>::max() ? internal::Arg arg = arg_index == std::numeric_limits<unsigned>::max() ? next_arg(error) : FormatterBase::get_arg(arg_index - 1, error);
next_arg(error) : FormatterBase::get_arg(arg_index - 1, error);
if (error) if (error)
FMT_THROW(FormatError(!*s ? "invalid format string" : error)); FMT_THROW(FormatError(!*s ? "invalid format string" : error));
return arg; return arg;
} }
template <typename Char, typename AF> template <typename Char, typename AF> unsigned PrintfFormatter<Char, AF>::parse_header(const Char *&s, FormatSpec &spec)
unsigned PrintfFormatter<Char, AF>::parse_header(
const Char *&s, FormatSpec &spec)
{ {
unsigned arg_index = std::numeric_limits<unsigned>::max(); unsigned arg_index = std::numeric_limits<unsigned>::max();
Char c = *s; Char c = *s;
...@@ -499,15 +489,15 @@ unsigned PrintfFormatter<Char, AF>::parse_header( ...@@ -499,15 +489,15 @@ unsigned PrintfFormatter<Char, AF>::parse_header(
return arg_index; return arg_index;
} }
template <typename Char, typename AF> template <typename Char, typename AF> void PrintfFormatter<Char, AF>::format(BasicCStringRef<Char> format_str)
void PrintfFormatter<Char, AF>::format(BasicCStringRef<Char> format_str)
{ {
const Char *start = format_str.c_str(); const Char *start = format_str.c_str();
const Char *s = start; const Char *s = start;
while (*s) while (*s)
{ {
Char c = *s++; Char c = *s++;
if (c != '%') continue; if (c != '%')
continue;
if (*s == c) if (*s == c)
{ {
write(writer_, start, s); write(writer_, start, s);
...@@ -706,7 +696,7 @@ FMT_VARIADIC(int, fprintf, std::ostream &, CStringRef) ...@@ -706,7 +696,7 @@ FMT_VARIADIC(int, fprintf, std::ostream &, CStringRef)
} // namespace fmt } // namespace fmt
#ifdef FMT_HEADER_ONLY #ifdef FMT_HEADER_ONLY
# include "printf.cc" #include "printf.cc"
#endif #endif
#endif // FMT_PRINTF_H_ #endif // FMT_PRINTF_H_
...@@ -14,16 +14,13 @@ ...@@ -14,16 +14,13 @@
#include <ctime> #include <ctime>
#ifdef _MSC_VER #ifdef _MSC_VER
# pragma warning(push) #pragma warning(push)
# pragma warning(disable: 4702) // unreachable code #pragma warning(disable : 4702) // unreachable code
# pragma warning(disable: 4996) // "deprecated" functions #pragma warning(disable : 4996) // "deprecated" functions
#endif #endif
namespace fmt namespace fmt {
{ template <typename ArgFormatter> void format_arg(BasicFormatter<char, ArgFormatter> &f, const char *&format_str, const std::tm &tm)
template <typename ArgFormatter>
void format_arg(BasicFormatter<char, ArgFormatter> &f,
const char *&format_str, const std::tm &tm)
{ {
if (*format_str == ':') if (*format_str == ':')
++format_str; ++format_str;
...@@ -60,8 +57,7 @@ void format_arg(BasicFormatter<char, ArgFormatter> &f, ...@@ -60,8 +57,7 @@ void format_arg(BasicFormatter<char, ArgFormatter> &f,
format_str = end + 1; format_str = end + 1;
} }
namespace internal namespace internal {
{
inline Null<> localtime_r(...) inline Null<> localtime_r(...)
{ {
return Null<>(); return Null<>();
...@@ -78,7 +74,7 @@ inline Null<> gmtime_s(...) ...@@ -78,7 +74,7 @@ inline Null<> gmtime_s(...)
{ {
return Null<>(); return Null<>();
} }
} } // namespace internal
// Thread-safe replacement for std::localtime // Thread-safe replacement for std::localtime
inline std::tm localtime(std::time_t time) inline std::tm localtime(std::time_t time)
...@@ -88,7 +84,10 @@ inline std::tm localtime(std::time_t time) ...@@ -88,7 +84,10 @@ inline std::tm localtime(std::time_t time)
std::time_t time_; std::time_t time_;
std::tm tm_; std::tm tm_;
LocalTime(std::time_t t): time_(t) {} LocalTime(std::time_t t)
: time_(t)
{
}
bool run() bool run()
{ {
...@@ -116,7 +115,8 @@ inline std::tm localtime(std::time_t time) ...@@ -116,7 +115,8 @@ inline std::tm localtime(std::time_t time)
{ {
using namespace fmt::internal; using namespace fmt::internal;
std::tm *tm = std::localtime(&time_); std::tm *tm = std::localtime(&time_);
if (tm) tm_ = *tm; if (tm)
tm_ = *tm;
return tm != FMT_NULL; return tm != FMT_NULL;
} }
}; };
...@@ -136,7 +136,10 @@ inline std::tm gmtime(std::time_t time) ...@@ -136,7 +136,10 @@ inline std::tm gmtime(std::time_t time)
std::time_t time_; std::time_t time_;
std::tm tm_; std::tm tm_;
GMTime(std::time_t t): time_(t) {} GMTime(std::time_t t)
: time_(t)
{
}
bool run() bool run()
{ {
...@@ -163,7 +166,8 @@ inline std::tm gmtime(std::time_t time) ...@@ -163,7 +166,8 @@ inline std::tm gmtime(std::time_t time)
bool fallback(internal::Null<>) bool fallback(internal::Null<>)
{ {
std::tm *tm = std::gmtime(&time_); std::tm *tm = std::gmtime(&time_);
if (tm != FMT_NULL) tm_ = *tm; if (tm != FMT_NULL)
tm_ = *tm;
return tm != FMT_NULL; return tm != FMT_NULL;
} }
}; };
...@@ -174,10 +178,10 @@ inline std::tm gmtime(std::time_t time) ...@@ -174,10 +178,10 @@ inline std::tm gmtime(std::time_t time)
FMT_THROW(fmt::FormatError("time_t value out of range")); FMT_THROW(fmt::FormatError("time_t value out of range"));
return std::tm(); return std::tm();
} }
} //namespace fmt } // namespace fmt
#ifdef _MSC_VER #ifdef _MSC_VER
# pragma warning(pop) #pragma warning(pop)
#endif #endif
#endif // FMT_TIME_H_ #endif // FMT_TIME_H_
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
#include "bundled/printf.h" #include "bundled/printf.h"
#endif #endif
#else //external fmtlib #else // external fmtlib
#include <fmt/format.h> #include <fmt/format.h>
#if defined(SPDLOG_FMT_PRINTF) #if defined(SPDLOG_FMT_PRINTF)
...@@ -31,4 +31,3 @@ ...@@ -31,4 +31,3 @@
#endif #endif
#endif #endif
...@@ -8,10 +8,8 @@ ...@@ -8,10 +8,8 @@
// include external or bundled copy of fmtlib's ostream support // include external or bundled copy of fmtlib's ostream support
// //
#if !defined(SPDLOG_FMT_EXTERNAL) #if !defined(SPDLOG_FMT_EXTERNAL)
#include "fmt.h"
#include "bundled/ostream.h" #include "bundled/ostream.h"
#include "fmt.h"
#else #else
#include <fmt/ostream.h> #include <fmt/ostream.h>
#endif #endif
...@@ -7,14 +7,12 @@ ...@@ -7,14 +7,12 @@
#include "details/log_msg.h" #include "details/log_msg.h"
#include <vector>
#include <string>
#include <memory> #include <memory>
#include <string>
#include <vector>
namespace spdlog namespace spdlog {
{ namespace details {
namespace details
{
class flag_formatter; class flag_formatter;
} }
...@@ -22,26 +20,27 @@ class formatter ...@@ -22,26 +20,27 @@ class formatter
{ {
public: public:
virtual ~formatter() = default; virtual ~formatter() = default;
virtual void format(details::log_msg& msg) = 0; virtual void format(details::log_msg &msg) = 0;
}; };
class pattern_formatter SPDLOG_FINAL : public formatter class pattern_formatter SPDLOG_FINAL : public formatter
{ {
public: public:
explicit pattern_formatter(const std::string& pattern, pattern_time_type pattern_time = pattern_time_type::local, std::string eol = spdlog::details::os::default_eol); explicit pattern_formatter(const std::string &pattern, pattern_time_type pattern_time = pattern_time_type::local,
pattern_formatter(const pattern_formatter&) = delete; std::string eol = spdlog::details::os::default_eol);
pattern_formatter& operator=(const pattern_formatter&) = delete; pattern_formatter(const pattern_formatter &) = delete;
void format(details::log_msg& msg) override; pattern_formatter &operator=(const pattern_formatter &) = delete;
void format(details::log_msg &msg) override;
private: private:
const std::string _eol; const std::string _eol;
const std::string _pattern; const std::string _pattern;
const pattern_time_type _pattern_time; const pattern_time_type _pattern_time;
std::vector<std::unique_ptr<details::flag_formatter>> _formatters; std::vector<std::unique_ptr<details::flag_formatter>> _formatters;
std::tm get_time(details::log_msg& msg); std::tm get_time(details::log_msg &msg);
void handle_flag(char flag); void handle_flag(char flag);
void compile_pattern(const std::string& pattern); void compile_pattern(const std::string &pattern);
}; };
} } // namespace spdlog
#include "details/pattern_formatter_impl.h" #include "details/pattern_formatter_impl.h"
...@@ -12,63 +12,61 @@ ...@@ -12,63 +12,61 @@
// 2. Format the message using the formatter function // 2. Format the message using the formatter function
// 3. Pass the formatted message to its sinks to performa the actual logging // 3. Pass the formatted message to its sinks to performa the actual logging
#include "sinks/base_sink.h"
#include "common.h" #include "common.h"
#include "sinks/base_sink.h"
#include <vector>
#include <memory> #include <memory>
#include <string> #include <string>
#include <vector>
namespace spdlog namespace spdlog {
{
class logger class logger
{ {
public: public:
logger(const std::string& name, sink_ptr single_sink); logger(const std::string &name, sink_ptr single_sink);
logger(const std::string& name, sinks_init_list sinks); logger(const std::string &name, sinks_init_list sinks);
template <class It> template <class It> logger(std::string name, const It &begin, const It &end);
logger(std::string name, const It& begin, const It& end);
virtual ~logger(); virtual ~logger();
logger(const logger&) = delete; logger(const logger &) = delete;
logger& operator=(const logger&) = delete; logger &operator=(const logger &) = delete;
template <typename... Args> void log(level::level_enum lvl, const char* fmt, const Args&... args); template <typename... Args> void log(level::level_enum lvl, const char *fmt, const Args &... args);
template <typename... Args> void log(level::level_enum lvl, const char* msg); template <typename... Args> void log(level::level_enum lvl, const char *msg);
template <typename Arg1, typename... Args> void trace(const char* fmt, const Arg1&, const Args&... args); template <typename Arg1, typename... Args> void trace(const char *fmt, const Arg1 &, const Args &... args);
template <typename Arg1, typename... Args> void debug(const char* fmt, const Arg1&, const Args&... args); template <typename Arg1, typename... Args> void debug(const char *fmt, const Arg1 &, const Args &... args);
template <typename Arg1, typename... Args> void info(const char* fmt, const Arg1&, const Args&... args); template <typename Arg1, typename... Args> void info(const char *fmt, const Arg1 &, const Args &... args);
template <typename Arg1, typename... Args> void warn(const char* fmt, const Arg1&, const Args&... args); template <typename Arg1, typename... Args> void warn(const char *fmt, const Arg1 &, const Args &... args);
template <typename Arg1, typename... Args> void error(const char* fmt, const Arg1&, const Args&... args); template <typename Arg1, typename... Args> void error(const char *fmt, const Arg1 &, const Args &... args);
template <typename Arg1, typename... Args> void critical(const char* fmt, const Arg1&, const Args&... args); template <typename Arg1, typename... Args> void critical(const char *fmt, const Arg1 &, const Args &... args);
#ifdef SPDLOG_WCHAR_TO_UTF8_SUPPORT #ifdef SPDLOG_WCHAR_TO_UTF8_SUPPORT
template <typename... Args> void log(level::level_enum lvl, const wchar_t* msg); template <typename... Args> void log(level::level_enum lvl, const wchar_t *msg);
template <typename... Args> void log(level::level_enum lvl, const wchar_t* fmt, const Args&... args); template <typename... Args> void log(level::level_enum lvl, const wchar_t *fmt, const Args &... args);
template <typename... Args> void trace(const wchar_t* fmt, const Args&... args); template <typename... Args> void trace(const wchar_t *fmt, const Args &... args);
template <typename... Args> void debug(const wchar_t* fmt, const Args&... args); template <typename... Args> void debug(const wchar_t *fmt, const Args &... args);
template <typename... Args> void info(const wchar_t* fmt, const Args&... args); template <typename... Args> void info(const wchar_t *fmt, const Args &... args);
template <typename... Args> void warn(const wchar_t* fmt, const Args&... args); template <typename... Args> void warn(const wchar_t *fmt, const Args &... args);
template <typename... Args> void error(const wchar_t* fmt, const Args&... args); template <typename... Args> void error(const wchar_t *fmt, const Args &... args);
template <typename... Args> void critical(const wchar_t* fmt, const Args&... args); template <typename... Args> void critical(const wchar_t *fmt, const Args &... args);
#endif // SPDLOG_WCHAR_TO_UTF8_SUPPORT #endif // SPDLOG_WCHAR_TO_UTF8_SUPPORT
template <typename T> void log(level::level_enum lvl, const T&); template <typename T> void log(level::level_enum lvl, const T &);
template <typename T> void trace(const T& msg); template <typename T> void trace(const T &msg);
template <typename T> void debug(const T& msg); template <typename T> void debug(const T &msg);
template <typename T> void info(const T& msg); template <typename T> void info(const T &msg);
template <typename T> void warn(const T& msg); template <typename T> void warn(const T &msg);
template <typename T> void error(const T& msg); template <typename T> void error(const T &msg);
template <typename T> void critical(const T& msg); template <typename T> void critical(const T &msg);
bool should_log(level::level_enum msg_level) const; bool should_log(level::level_enum msg_level) const;
void set_level(level::level_enum log_level); void set_level(level::level_enum log_level);
level::level_enum level() const; level::level_enum level() const;
const std::string& name() const; const std::string &name() const;
void set_pattern(const std::string& pattern, pattern_time_type pattern_time = pattern_time_type::local); void set_pattern(const std::string &pattern, pattern_time_type pattern_time = pattern_time_type::local);
void set_formatter(formatter_ptr msg_formatter); void set_formatter(formatter_ptr msg_formatter);
// automatically call flush() if message level >= log_level // automatically call flush() if message level >= log_level
...@@ -76,25 +74,25 @@ public: ...@@ -76,25 +74,25 @@ public:
virtual void flush(); virtual void flush();
const std::vector<sink_ptr>& sinks() const; const std::vector<sink_ptr> &sinks() const;
// error handler // error handler
virtual void set_error_handler(log_err_handler err_handler); virtual void set_error_handler(log_err_handler err_handler);
virtual log_err_handler error_handler(); virtual log_err_handler error_handler();
protected: protected:
virtual void _sink_it(details::log_msg& msg); virtual void _sink_it(details::log_msg &msg);
virtual void _set_pattern(const std::string& pattern, pattern_time_type pattern_time); virtual void _set_pattern(const std::string &pattern, pattern_time_type pattern_time);
virtual void _set_formatter(formatter_ptr msg_formatter); virtual void _set_formatter(formatter_ptr msg_formatter);
// default error handler: print the error to stderr with the max rate of 1 message/minute // default error handler: print the error to stderr with the max rate of 1 message/minute
virtual void _default_err_handler(const std::string &msg); virtual void _default_err_handler(const std::string &msg);
// return true if the given message level should trigger a flush // return true if the given message level should trigger a flush
bool _should_flush_on(const details::log_msg& msg); bool _should_flush_on(const details::log_msg &msg);
// increment the message count (only if defined(SPDLOG_ENABLE_MESSAGE_COUNTER)) // increment the message count (only if defined(SPDLOG_ENABLE_MESSAGE_COUNTER))
void _incr_msg_counter(details::log_msg& msg); void _incr_msg_counter(details::log_msg &msg);
const std::string _name; const std::string _name;
std::vector<sink_ptr> _sinks; std::vector<sink_ptr> _sinks;
...@@ -105,6 +103,6 @@ protected: ...@@ -105,6 +103,6 @@ protected:
std::atomic<time_t> _last_err_time; std::atomic<time_t> _last_err_time;
std::atomic<size_t> _msg_counter; std::atomic<size_t> _msg_counter;
}; };
} } // namespace spdlog
#include "details/logger_impl.h" #include "details/logger_impl.h"
...@@ -7,34 +7,35 @@ ...@@ -7,34 +7,35 @@
#if defined(__ANDROID__) #if defined(__ANDROID__)
#include "sink.h"
#include "../details/os.h" #include "../details/os.h"
#include "sink.h"
#include <android/log.h>
#include <chrono>
#include <mutex> #include <mutex>
#include <string> #include <string>
#include <android/log.h>
#include <thread> #include <thread>
#include <chrono>
#if !defined(SPDLOG_ANDROID_RETRIES) #if !defined(SPDLOG_ANDROID_RETRIES)
#define SPDLOG_ANDROID_RETRIES 2 #define SPDLOG_ANDROID_RETRIES 2
#endif #endif
namespace spdlog namespace spdlog { namespace sinks {
{
namespace sinks
{
/* /*
* Android sink (logging using __android_log_write) * Android sink (logging using __android_log_write)
* __android_log_write is thread-safe. No lock is needed. * __android_log_write is thread-safe. No lock is needed.
*/ */
class android_sink : public sink class android_sink : public sink
{ {
public: public:
explicit android_sink(const std::string& tag = "spdlog", bool use_raw_msg = false): _tag(tag), _use_raw_msg(use_raw_msg) {} explicit android_sink(const std::string &tag = "spdlog", bool use_raw_msg = false)
: _tag(tag)
, _use_raw_msg(use_raw_msg)
{
}
void log(const details::log_msg& msg) override void log(const details::log_msg &msg) override
{ {
const android_LogPriority priority = convert_to_android(msg.level); const android_LogPriority priority = convert_to_android(msg.level);
const char *msg_output = (_use_raw_msg ? msg.raw.c_str() : msg.formatted.c_str()); const char *msg_output = (_use_raw_msg ? msg.raw.c_str() : msg.formatted.c_str());
...@@ -42,7 +43,7 @@ public: ...@@ -42,7 +43,7 @@ public:
// See system/core/liblog/logger_write.c for explanation of return value // See system/core/liblog/logger_write.c for explanation of return value
int ret = __android_log_write(priority, _tag.c_str(), msg_output); int ret = __android_log_write(priority, _tag.c_str(), msg_output);
int retry_count = 0; int retry_count = 0;
while ((ret == -11/*EAGAIN*/) && (retry_count < SPDLOG_ANDROID_RETRIES)) while ((ret == -11 /*EAGAIN*/) && (retry_count < SPDLOG_ANDROID_RETRIES))
{ {
details::os::sleep_for_millis(5); details::os::sleep_for_millis(5);
ret = __android_log_write(priority, _tag.c_str(), msg_output); ret = __android_log_write(priority, _tag.c_str(), msg_output);
...@@ -55,14 +56,12 @@ public: ...@@ -55,14 +56,12 @@ public:
} }
} }
void flush() override void flush() override {}
{
}
private: private:
static android_LogPriority convert_to_android(spdlog::level::level_enum level) static android_LogPriority convert_to_android(spdlog::level::level_enum level)
{ {
switch(level) switch (level)
{ {
case spdlog::level::trace: case spdlog::level::trace:
return ANDROID_LOG_VERBOSE; return ANDROID_LOG_VERBOSE;
...@@ -85,7 +84,6 @@ private: ...@@ -85,7 +84,6 @@ private:
bool _use_raw_msg; bool _use_raw_msg;
}; };
} }} // namespace spdlog::sinks
}
#endif #endif
This diff is collapsed.
...@@ -10,27 +10,23 @@ ...@@ -10,27 +10,23 @@
// all locking is taken care of here so no locking needed by the implementers.. // all locking is taken care of here so no locking needed by the implementers..
// //
#include "sink.h"
#include "../formatter.h"
#include "../common.h" #include "../common.h"
#include "../details/log_msg.h" #include "../details/log_msg.h"
#include "../formatter.h"
#include "sink.h"
#include <mutex> #include <mutex>
namespace spdlog namespace spdlog { namespace sinks {
{ template <class Mutex> class base_sink : public sink
namespace sinks
{
template<class Mutex>
class base_sink : public sink
{ {
public: public:
base_sink() = default; 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 details::log_msg& msg) SPDLOG_FINAL override void log(const details::log_msg &msg) SPDLOG_FINAL override
{ {
std::lock_guard<Mutex> lock(_mutex); std::lock_guard<Mutex> lock(_mutex);
_sink_it(msg); _sink_it(msg);
...@@ -43,9 +39,8 @@ public: ...@@ -43,9 +39,8 @@ public:
} }
protected: protected:
virtual void _sink_it(const details::log_msg& msg) = 0; virtual void _sink_it(const details::log_msg &msg) = 0;
virtual void _flush() = 0; virtual void _flush() = 0;
Mutex _mutex; Mutex _mutex;
}; };
} }} // namespace spdlog::sinks
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment