You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
193 lines
5.1 KiB
193 lines
5.1 KiB
// David Eberly, Geometric Tools, Redmond WA 98052
|
|
// Copyright (c) 1998-2021
|
|
// Distributed under the Boost Software License, Version 1.0.
|
|
// https://www.boost.org/LICENSE_1_0.txt
|
|
// https://www.geometrictools.com/License/Boost/LICENSE_1_0.txt
|
|
// Version: 4.0.2019.08.13
|
|
|
|
#pragma once
|
|
|
|
#include <mutex>
|
|
#include <set>
|
|
#include <stdexcept>
|
|
#include <string>
|
|
|
|
namespace gte
|
|
{
|
|
class Logger
|
|
{
|
|
public:
|
|
// Listeners subscribe to Logger to receive message strings.
|
|
class Listener
|
|
{
|
|
public:
|
|
enum
|
|
{
|
|
LISTEN_FOR_NOTHING = 0x00000000,
|
|
LISTEN_FOR_ASSERTION = 0x00000001,
|
|
LISTEN_FOR_ERROR = 0x00000002,
|
|
LISTEN_FOR_WARNING = 0x00000004,
|
|
LISTEN_FOR_INFORMATION = 0x00000008,
|
|
LISTEN_FOR_ALL = 0xFFFFFFFF
|
|
};
|
|
|
|
// Construction and destruction.
|
|
virtual ~Listener() = default;
|
|
|
|
Listener(int flags = LISTEN_FOR_NOTHING)
|
|
:
|
|
mFlags(flags)
|
|
{
|
|
}
|
|
|
|
// What the listener wants to hear.
|
|
inline int GetFlags() const
|
|
{
|
|
return mFlags;
|
|
}
|
|
|
|
// Handlers for the messages received from the logger.
|
|
void Assertion(std::string const& message)
|
|
{
|
|
Report("\nGTE ASSERTION:\n" + message);
|
|
}
|
|
|
|
void Error(std::string const& message)
|
|
{
|
|
Report("\nGTE ERROR:\n" + message);
|
|
}
|
|
|
|
void Warning(std::string const& message)
|
|
{
|
|
Report("\nGTE WARNING:\n" + message);
|
|
}
|
|
|
|
void Information(std::string const& message)
|
|
{
|
|
Report("\nGTE INFORMATION:\n" + message);
|
|
}
|
|
|
|
private:
|
|
virtual void Report(std::string const& message)
|
|
{
|
|
// Stub for derived classes.
|
|
(void)message;
|
|
}
|
|
|
|
int mFlags;
|
|
};
|
|
|
|
// Construction. The Logger object is designed to exist only for a
|
|
// single-line call. A string is generated from the input parameters and
|
|
// is used for reporting.
|
|
Logger(char const* file, char const* function, int line, std::string const& message)
|
|
{
|
|
mMessage =
|
|
"File: " + std::string(file) + "\n" +
|
|
"Func: " + std::string(function) + "\n" +
|
|
"Line: " + std::to_string(line) + "\n" +
|
|
message + "\n\n";
|
|
}
|
|
|
|
// Notify current listeners about the logged information.
|
|
void Assertion()
|
|
{
|
|
Mutex().lock();
|
|
for (auto listener : Listeners())
|
|
{
|
|
if (listener->GetFlags() & Listener::LISTEN_FOR_ASSERTION)
|
|
{
|
|
listener->Assertion(mMessage);
|
|
}
|
|
}
|
|
Mutex().unlock();
|
|
}
|
|
|
|
void Error()
|
|
{
|
|
Mutex().lock();
|
|
for (auto listener : Listeners())
|
|
{
|
|
if (listener->GetFlags() & Listener::LISTEN_FOR_ERROR)
|
|
{
|
|
listener->Error(mMessage);
|
|
}
|
|
}
|
|
Mutex().unlock();
|
|
}
|
|
|
|
void Warning()
|
|
{
|
|
Mutex().lock();
|
|
for (auto listener : Listeners())
|
|
{
|
|
if (listener->GetFlags() & Listener::LISTEN_FOR_WARNING)
|
|
{
|
|
listener->Warning(mMessage);
|
|
}
|
|
}
|
|
Mutex().unlock();
|
|
}
|
|
void Information()
|
|
{
|
|
Mutex().lock();
|
|
for (auto listener : Listeners())
|
|
{
|
|
if (listener->GetFlags() & Listener::LISTEN_FOR_INFORMATION)
|
|
{
|
|
listener->Information(mMessage);
|
|
}
|
|
}
|
|
Mutex().unlock();
|
|
}
|
|
|
|
static void Subscribe(Listener* listener)
|
|
{
|
|
Mutex().lock();
|
|
Listeners().insert(listener);
|
|
Mutex().unlock();
|
|
}
|
|
|
|
static void Unsubscribe(Listener* listener)
|
|
{
|
|
Mutex().lock();
|
|
Listeners().erase(listener);
|
|
Mutex().unlock();
|
|
}
|
|
|
|
|
|
private:
|
|
std::string mMessage;
|
|
|
|
static std::mutex& Mutex()
|
|
{
|
|
static std::mutex sMutex;
|
|
return sMutex;
|
|
}
|
|
|
|
static std::set<Listener*>& Listeners()
|
|
{
|
|
static std::set<Listener*> sListeners;
|
|
return sListeners;
|
|
}
|
|
};
|
|
|
|
}
|
|
|
|
|
|
#define LogAssert(condition, message) \
|
|
if (!(condition)) \
|
|
{ \
|
|
gte::Logger(__FILE__, __FUNCTION__, __LINE__, message).Assertion(); \
|
|
throw std::runtime_error(message); \
|
|
}
|
|
|
|
#define LogError(message) \
|
|
gte::Logger(__FILE__, __FUNCTION__, __LINE__, message).Error(); \
|
|
throw std::runtime_error(message)
|
|
|
|
#define LogWarning(message) \
|
|
gte::Logger(__FILE__, __FUNCTION__, __LINE__, message).Warning()
|
|
|
|
#define LogInformation(message) \
|
|
gte::Logger(__FILE__, __FUNCTION__, __LINE__, message).Information()
|
|
|