PeriDyno 1.0.0
Loading...
Searching...
No Matches
Log.cpp
Go to the documentation of this file.
1//#define _CRT_SECURE_NO_WARNINGS
2
3#include "Log.h"
4#include "FilePath.h"
5
6
7namespace dyno
8{
9 std::string Log::sOutputFile;
10 std::ofstream Log::sOutputStream;
11 void(*Log::receiver)(const Message&) = nullptr;
13
14 std::atomic<Log*> Log::sLogInstance = nullptr;
15 std::queue<Log::Message> Log::sMessageQueue;
16
17#define LOG_DEBUG(format, ...) Log::instance()->writeMessage(Log::DebugInfo, format, ##__VA_ARGS__)
18#define LOG_INFO(format, ...) Log::instance()->writeMessage(Log::Info, format, ##__VA_ARGS__)
19#define LOG_ERROR(format, ...) Log::instance()->writeMessage(Log::Error, format, ##__VA_ARGS__)
20#define LOG_WARN(format, ...) Log::instance()->writeMessage(Log::Warning, format, ##__VA_ARGS__)
21#define LOG_USER(format, ...) Log::instance()->writeMessage(Log::User, format, ##__VA_ARGS__)
22#define LOG_DISPLAY(format, ...) Log::instance()->writeMessage(Log::Display, format, ##__VA_ARGS__)
23
24 void Log::writeMessage(MessageType level, const char* format, ...)
25 {
26 // log message
28 m.type = level;
29 m.text = std::string(format);
30 time_t t = time(NULL);
31 m.when = localtime(&t);
32
33 //Finish create Message and push into queue
34 {
35 std::lock_guard<std::mutex> lock(mtx);
36 sMessageQueue.push(m); //push message into queue
37 mCondition.notify_one();
38 }
39 }
40
41 void Log::sendMessage(MessageType type, const std::string& text)
42 {
43 // Skip logging to file if minimum level is higher
44 if ((int)type < (int)sLogLevel)
45 return;
46
47 switch (type)
48 {
49 case DebugInfo: LOG_DEBUG(text.c_str()); break;
50 case Info: LOG_INFO(text.c_str()); break;
51 case Warning: LOG_WARN(text.c_str()); break;
52 case Error: LOG_ERROR(text.c_str()); break;
53 default: LOG_USER(text.c_str());
54 }
55 }
56
57 void Log::setUserReceiver(void (*userFunc)(const Message&))
58 {
59 receiver = userFunc;
60 }
61
63 {
64 sLogLevel = level;
65 }
66
67 void Log::setOutput(const std::string& filename)
68 {
69 sOutputFile = filename;
70
71 // close old one
72 if (sOutputStream.is_open())
73 sOutputStream.close();
74
75 // create file
76 sOutputStream.open(filename.c_str());
77 if (!sOutputStream.is_open())
78 sendMessage(Error, "Cannot create/open '" + filename + "' for logging");
79 }
80
81 const std::string& Log::getOutput()
82 {
83 return sOutputFile;
84 }
85
87 {
88 static std::mutex mutex;
89 Log* ins = sLogInstance.load(std::memory_order_acquire);
90
91 if (!ins) {
92 std::lock_guard<std::mutex> tLock(mutex);
93 ins = sLogInstance.load(std::memory_order_relaxed);
94 if (!ins) {
95 ins = new Log();
96 sLogInstance.store(ins, std::memory_order_release);
97 }
98 }
99
100 return ins;
101 }
102
104 : mRunning(true)
105 {
106 mThread = std::thread(&Log::outputThread, this);
107 }
108
110 {
111
112 mCondition.notify_one();
113 if (mThread.joinable()) {
114 mThread.join();
115 }
116
117 mRunning = false;
118 }
119
121 {
122 while (mRunning) {
123 std::unique_lock<std::mutex> lock(mtx);
124 mCondition.wait(lock, [&]() { return !sMessageQueue.empty() || !mRunning; });
125
126 while (!sMessageQueue.empty()) {
127 auto m = sMessageQueue.front();
128 sMessageQueue.pop();
129
130 if (receiver) {
131 receiver(m);
132 }
133
134 // if enabled logging to file
135 if (sOutputStream.is_open())
136 {
137 // print time
138 char buffer[9];
139 strftime(buffer, 9, "%X", m.when);
140 sOutputStream << buffer;
141
142 // print type
143 switch (m.type)
144 {
145 case DebugInfo: sOutputStream << " | Debug | "; break;
146 case Info: sOutputStream << " | Info | "; break;
147 case Warning: sOutputStream << " | warning | "; break;
148 case Error: sOutputStream << " | ERROR | "; break;
149 default: sOutputStream << " | user | ";
150 }
151
152 // print description
153 sOutputStream << m.text << std::endl;
154 }
155 }
156
157 }
158 }
159}
#define LOG_WARN(format,...)
Definition Log.cpp:20
#define LOG_INFO(format,...)
Definition Log.cpp:18
#define LOG_DEBUG(format,...)
Definition Log.cpp:17
#define LOG_ERROR(format,...)
Definition Log.cpp:19
#define LOG_USER(format,...)
Definition Log.cpp:21
bool mRunning
Definition Log.h:102
static void(* receiver)(const Message &)
Definition Log.h:114
MessageType
Definition Log.h:46
@ Warning
Warning information.
Definition Log.h:49
@ Info
Information to user.
Definition Log.h:48
@ DebugInfo
Message with some debug information.
Definition Log.h:47
@ Error
Error information while executing something.
Definition Log.h:50
std::condition_variable mCondition
Definition Log.h:106
std::thread mThread
Definition Log.h:105
static void setLevel(MessageType level)
Set minimum level of message to be logged to file.
Definition Log.cpp:62
static std::queue< Message > sMessageQueue
Definition Log.h:110
static std::ofstream sOutputStream
Definition Log.h:113
static MessageType sLogLevel
Definition Log.h:111
static std::string sOutputFile
Definition Log.h:112
void writeMessage(MessageType level, const char *format,...)
Definition Log.cpp:24
std::mutex mtx
Definition Log.h:104
void outputThread()
Definition Log.cpp:120
static std::atomic< Log * > sLogInstance
Definition Log.h:108
static void setUserReceiver(void(*userFunc)(const Message &))
Set user function to receive newly sent messages to logger.
Definition Log.cpp:57
static const std::string & getOutput()
Get the filename of log.
Definition Log.cpp:81
static void sendMessage(MessageType type, const std::string &text)
Add a new message to log.
Definition Log.cpp:41
static void setOutput(const std::string &filename)
Open file where to log the messages.
Definition Log.cpp:67
static Log * instance()
Definition Log.cpp:86
This is an implementation of AdditiveCCD based on peridyno.
Definition Array.h:25
std::string text
Definition Log.h:56
MessageType type
Definition Log.h:55