Skip to content

Commit 597900c

Browse files
committed
flush the log before throwing exceptions
1 parent fec264d commit 597900c

File tree

5 files changed

+61
-25
lines changed

5 files changed

+61
-25
lines changed

exec/devTest/CMakeLists.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ set(SOURCE_FILES
77

88
# create target
99
add_executable(devTest ${SOURCE_FILES})
10-
#set_target_properties( devTest PROPERTIES CUDA_SEPARABLE_COMPILATION ON)
1110

1211
# link libraries
1312
target_link_libraries(devTest mpUtils)

exec/devTest/cudaTest.cu

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ void add(size_t n, Array& x, Array& y)
5858

5959
void testCuda()
6060
{
61-
size_t N = 1<<20;
61+
size_t N = 1<<28;
6262
auto x=std::make_unique<Array>(N);
6363
auto y=std::make_unique<Array>(N);
6464

src/Cuda/cudaUtils.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,12 @@ inline void _cudaAssert(cudaError_t code, std::string&& filepos)
6464
{
6565
std::string message("Cuda error: " + std::string(cudaGetErrorString(code)));
6666

67-
if (!(mpu::Log::noGlobal() || mpu::Log::getGlobal().getLogLevel() < mpu::LogLvl::FATAL_ERROR))
68-
mpu::Log::getGlobal()(mpu::LogLvl::FATAL_ERROR, std::move(filepos), "cuda") << message;
67+
if (!(mpu::Log::noGlobal()))
68+
{
69+
if(mpu::Log::getGlobal().getLogLevel() >= mpu::LogLvl::FATAL_ERROR)
70+
mpu::Log::getGlobal()(mpu::LogLvl::FATAL_ERROR, std::move(filepos), "cuda") << message;
71+
mpu::Log::getGlobal().flush();
72+
}
6973

7074
throw std::runtime_error("Cuda error: " + message);
7175
}

src/Log/Log.cpp

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ void Log::close()
4848
LogLvl oldLvl = logLvl;
4949
logLvl = LogLvl::NOLOG;
5050

51-
// wait for the logger to print all queued messages and join the thread
51+
// flush it
5252
std::unique_lock<std::mutex> lck(loggerMtx);
5353
if(bShouldLoggerRun)
5454
{
@@ -65,6 +65,34 @@ void Log::close()
6565
logLvl = oldLvl;
6666
}
6767

68+
void Log::flush()
69+
{
70+
std::unique_lock<std::mutex> lck(loggerMtx);
71+
72+
// accept no more messages
73+
LogLvl oldLvl = logLvl;
74+
logLvl = LogLvl::NOLOG;
75+
76+
// wait for the logger to print all queued messages and join the thread
77+
if(bShouldLoggerRun)
78+
{
79+
bShouldLoggerRun = false;
80+
loggerCv.notify_one();
81+
}
82+
lck.unlock();
83+
if(loggerMainThread.joinable())
84+
loggerMainThread.join();
85+
lck.lock();
86+
87+
// restart the logger
88+
logLvl = oldLvl;
89+
if(!bShouldLoggerRun)
90+
{
91+
bShouldLoggerRun = true;
92+
loggerMainThread = std::thread(&Log::loggerMainfunc, this);
93+
}
94+
}
95+
6896
void Log::logMessage(LogMessage* lm)
6997
{
7098
if(!printFunctions.empty() && lm->lvl <= logLvl)

src/Log/Log.h

Lines changed: 25 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,9 @@
4848
else mpu::Log::getGlobal()(mpu::LogLvl::WARNING, MPU_FILEPOS, MODULE)
4949
#define logINFO(MODULE) if(mpu::Log::noGlobal() || mpu::Log::getGlobal().getLogLevel() < mpu::LogLvl::INFO) ; \
5050
else mpu::Log::getGlobal()(mpu::LogLvl::INFO, MPU_FILEPOS, MODULE)
51-
#define assert_critical(TEST,MODULE,MESSAGE) if(!( TEST )){ logFATAL_ERROR(MODULE) << "Assert failed: " << (MESSAGE) ; throw std::runtime_error(MESSAGE);}
51+
#define assert_critical(TEST,MODULE,MESSAGE) if(!( TEST )){ logFATAL_ERROR(MODULE) << "Assert failed: " << (MESSAGE) ; \
52+
if(!mpu::Log::noGlobal()) mpu::Log::getGlobal().flush(); \
53+
throw std::runtime_error(MESSAGE);}
5254

5355
// debug is disabled on release build
5456
#ifdef NDEBUG
@@ -61,7 +63,9 @@
6163
else mpu::Log::getGlobal()(mpu::LogLvl::DEBUG, MPU_FILEPOS, MODULE)
6264
#define logDEBUG2(MODULE) if(mpu::Log::noGlobal() || mpu::Log::getGlobal().getLogLevel() < mpu::LogLvl::DEBUG2) ; \
6365
else mpu::Log::getGlobal()(mpu::LogLvl::DEBUG2, MPU_FILEPOS, MODULE)
64-
#define assert_true(TEST,MODULE,MESSAGE) if(!( TEST )){ logERROR(MODULE) << "Assert failed: " << (MESSAGE) ; throw std::runtime_error(MESSAGE);}
66+
#define assert_true(TEST,MODULE,MESSAGE) if(!( TEST )){ logERROR(MODULE) << "Assert failed: " << (MESSAGE) ; \
67+
if(!mpu::Log::noGlobal()) mpu::Log::getGlobal().flush(); \
68+
throw std::runtime_error(MESSAGE);}
6569
#endif
6670
//--------------------
6771

@@ -152,19 +156,20 @@ class Log
152156
~Log(); // destructor
153157

154158
template <class FIRST_SINK, class... OTHER_SINKS>
155-
void addSinks(FIRST_SINK&& sink, OTHER_SINKS&&... tail); // add a number of sinks
159+
void addSinks(FIRST_SINK&& sink, OTHER_SINKS&&... tail); //!< add a number of sinks
156160
void addSinks(){}
157-
void removeSink(int index); // removes a given sink (be carefull)
158-
void close(); // removes all sinks and closes the logger thread (queue is flushed), is called automatically before open and on destruction
161+
void removeSink(int index); //!< removes a given sink (be carefull)
162+
void close(); //!< removes all sinks and closes the logger thread (queue is flushed), is called automatically before open and on destruction
163+
void flush(); //!< flush the log without closing it. Quite costly. Mainly used before throwing an exception.
159164

160-
void logMessage(LogMessage* lm); // logs a message to the log
165+
void logMessage(LogMessage* lm); //!< logs a message to the log
161166

162167
// getter and setter
163-
void setLogLevel(LogLvl lvl) {logLvl = lvl;} // set the current log level
164-
LogLvl getLogLevel() const {return logLvl;} // get the current log level
165-
void makeGlobal() {globalLog = this;} // makes the current log global
166-
static Log &getGlobal() {return *globalLog;} // gets the global log
167-
static bool noGlobal() {return (globalLog == nullptr);} // checks if there is no global log set
168+
void setLogLevel(LogLvl lvl) {logLvl = lvl;} //!< set the current log level
169+
LogLvl getLogLevel() const {return logLvl;} //!< get the current log level
170+
void makeGlobal() {globalLog = this;} //!< makes the current log global
171+
static Log &getGlobal() {return *globalLog;} //!< gets the global log
172+
static bool noGlobal() {return (globalLog == nullptr);} //!< checks if there is no global log set
168173

169174
// operators
170175
LogStream operator()(LogLvl lvl, std::string&& sFilepos ="", std::string&& sModule="");
@@ -176,20 +181,20 @@ class Log
176181
Log& operator=(const Log&& that) = delete;
177182

178183
private:
179-
std::atomic<LogLvl> logLvl; // the log level
184+
std::atomic<LogLvl> logLvl; //!< the log level
180185

181-
static Log* globalLog; // point this to the global log
186+
static Log* globalLog; //!< point this to the global log
182187

183-
std::queue< LogMessage*> messageQueue; // queue to collect messages from all threads
188+
std::queue< LogMessage*> messageQueue; //!< queue to collect messages from all threads
184189

185190
// thread management
186-
std::mutex queueMtx; // mutex to protect the queue
187-
std::mutex loggerMtx; // protect the logging operation
188-
std::condition_variable loggerCv; // cv to notify the logger when new messages arrive
189-
bool bShouldLoggerRun; // controle if the logger thread is running
191+
std::mutex queueMtx; //!< mutex to protect the queue
192+
std::mutex loggerMtx; //!< protect the logging operation
193+
std::condition_variable loggerCv; //!< cv to notify the logger when new messages arrive
194+
bool bShouldLoggerRun; //!< controle if the logger thread is running
190195

191-
std::thread loggerMainThread; // the logger main thread
192-
void loggerMainfunc(); // the mainfunc of the second thread
196+
std::thread loggerMainThread; //!< the logger main thread
197+
void loggerMainfunc(); //!< the mainfunc of the second thread
193198

194199
std::vector<std::function<void(const LogMessage& msg)>> printFunctions; // the funtion used to print a message to the log
195200
};

0 commit comments

Comments
 (0)