Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- 1 #include <iostream>
- 2 #include <cstdint>
- 3 #include <thread>
- 4 #include <mutex>
- 5 #include <fstream>
- 6 #include <string>
- 7 #include <sstream>
- 8 #include <chrono>
- 9 #include <map>
- 10 #include <iomanip>
- 11 #include <ctime>
- 12 #include <functional>
- 13
- 14 ///
- 15 /// \brief The logger struct
- 16 ///
- 17 struct logger {
- 18 enum level : int16_t { debug = 0, info = 1, warn = 2, error = 3, fatal = 4 };
- 19
- 20 ~logger() {
- 21 write_all();
- 22 }
- 23
- 24 logger & operator()(level p_level) {
- 25 add(true)
- 26 << "[" << get_level(p_level) << "]"
- 27 << "[" << std::time(NULL) << "]"
- 28 << "[" << std::this_thread::get_id() << "] ";
- 29 return *this;
- 30 }
- 31
- 32 template <typename T>
- 33 logger & operator << (const T & p_val) {
- 34 add() << p_val;
- 35 return *this;
- 36 }
- 37 private:
- 38
- 39 struct at_thread_end {
- 40 at_thread_end (std::function<void (std::thread::id)> p_callback
- 41 , std::thread::id p_id)
- 42 : m_callback(p_callback)
- 43 , m_id(p_id){}
- 44
- 45 at_thread_end(at_thread_end && p_at_thread_end)
- 46 : m_callback(std::move(p_at_thread_end.m_callback))
- 47 , m_id(std::move(p_at_thread_end.m_id)) {}
- 48
- 49 at_thread_end & operator=(at_thread_end && p_at_thread_end) {
- 50 m_callback = std::move(p_at_thread_end.m_callback);
- 51 m_id = std::move(p_at_thread_end.m_id);
- 52 return *this;
- 53 }
- 54
- 55 ~at_thread_end() {
- 56 m_callback(m_id);
- 57 }
- 58
- 59 private:
- 60 std::function<void (std::thread::id)> m_callback;
- 61 std::thread::id m_id;
- 62 };
- 63
- 64 typedef std::map<std::thread::id, std::stringstream> streams;
- 65
- 66 void on_thread_end(std::thread::id p_id) {
- 67 std::cout << "thread " << p_id << " ended" << std::endl;
- 68 streams::iterator _ite = m_streams.find(p_id);
- 69 if (_ite != m_streams.end()) {
- 70 write(_ite->second.str());
- 71 std::lock_guard<std::mutex> _lock(m_mutex_streams);
- 72 m_streams.erase(_ite);
- 73 }
- 74 }
- 75
- 76 std::stringstream & add(bool p_clean = false) {
- 77 std::thread::id _id = std::this_thread::get_id();
- 78 streams::iterator _ite = m_streams.find(_id);
- 79 if (_ite != m_streams.end()) {
- 80 if (p_clean) {
- 81 write(_ite->second.str());
- 82 _ite->second.str("");
- 83 }
- 84 return _ite->second;
- 85 }
- 86
- 87
- 88 using std::placeholders::_1;
- 89 thread_local at_thread_end
- 90 _at_thread_end(std::bind(&logger::on_thread_end, this, _1)
- 91 ,_id);
- 92
- 93 std::lock_guard<std::mutex> _lock(m_mutex_streams);
- 94 m_streams[_id] = std::stringstream();
- 95 return m_streams[_id];
- 96 }
- 97
- 98 std::string get_level(level p_level) {
- 99 switch (p_level) {
- 100 case level::debug:
- 101 return "DEB";
- 102 case level::info:
- 103 return "INF";
- 104 case level::warn:
- 105 return "WAR";
- 106 case level::error:
- 107 return "ERR";
- 108 case level::fatal:
- 109 return "FAT";
- 110 }
- 111 return "LEVEL UNKNOW";
- 112 }
- 113
- 114 void write(const std::string & p_str) {
- 115 std::lock_guard<std::mutex> _lock(m_mutex_write);
- 116 if (p_str.size()) {
- 117 std::cout << p_str << std::endl;
- 118 }
- 119 }
- 120
- 121 void write_all() {
- 122 std::lock_guard<std::mutex> _lock(m_mutex_streams);
- 123 streams::iterator _end = m_streams.end();
- 124 for (streams::iterator _ite = m_streams.begin(); _ite != _end; ++_ite) {
- 125 write(_ite->second.str());
- 126 }
- 127 }
- 128
- 129 streams m_streams;
- 130 std::mutex m_mutex_streams;
- 131 std::mutex m_mutex_write;
- 132
- 133 };
- 134
- 135
- 136 ///
- 137 /// \brief The tester struct
- 138 ///
- 139 struct tester {
- 140
- 141 tester(uint16_t p_id, uint16_t p_max
- 142 , std::chrono::milliseconds p_pause
- 143 , logger * p_logger)
- 144 : m_id(p_id)
- 145 , m_max(p_max)
- 146 , m_pause(p_pause)
- 147 , m_logger(p_logger) {}
- 148
- 149 void operator()() {
- 150 for (uint16_t _i = 0;_i < m_max; ++_i) {
- 151 (*m_logger)(logger::level::debug) << "id = " << std::setfill('0')
- 152 << std::setw(2) << m_id
- 153 << ", i = " << std::setw(4) << _i << ", "
- 154 << "hello 0, " << "hello 1, "
- 155 << "a sentence, "
- 156 << "hello 2, " << "hello 3, "
- 157 << "a longer sentence, "
- 158 << "hello 4, " << "hello 5, "
- 159 << "a even longer sentence, "
- 160 << "hello 6, " << "hello 7, "
- 161 << "a quite very long sentence, "
- 162 << "hello 8, " << "hello 9";
- 163 std::this_thread::sleep_for(m_pause);
- 164 }
- 165 }
- 166
- 167 private:
- 168 uint16_t m_id;
- 169 uint16_t m_max;
- 170 std::chrono::milliseconds m_pause;
- 171 logger * m_logger;
- 172 };
- 173
- 174 int main() {
- 175
- 176 logger _logger;
- 177 tester _p1(1, 15000, std::chrono::milliseconds(90), &_logger);
- 178 tester _p2(2, 16000, std::chrono::milliseconds(80), &_logger);
- 179 tester _p3(3, 17000, std::chrono::milliseconds(70), &_logger);
- 180 tester _p4(4, 18000, std::chrono::milliseconds(60), &_logger);
- 181 tester _p5(5, 19000, std::chrono::milliseconds(50), &_logger);
- 182
- 183 std::thread _t1(std::ref(_p1));
- 184 std::thread _t2(std::ref(_p2));
- 185 std::thread _t3(std::ref(_p3));
- 186 std::thread _t4(std::ref(_p4));
- 187 std::thread _t5(std::ref(_p5));
- 188
- 189 _t1.join();
- 190 _t2.join();
- 191 _t3.join();
- 192 _t4.join();
- 193 _t5.join();
- 194 }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement