Commit 7df9415cbeaa0c099f77d03fceb90ae477460fa7

Authored by Peter M. Groen
1 parent ef4d66e0

Embedded logger into library.

CMakeLists.txt
@@ -7,7 +7,6 @@ LIST(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/submodules/cmake) @@ -7,7 +7,6 @@ LIST(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/submodules/cmake)
7 include(projectheader) 7 include(projectheader)
8 project_header(osdev_mqtt) 8 project_header(osdev_mqtt)
9 9
10 -add_subdirectory(submodules/logger)  
11 add_subdirectory(src) 10 add_subdirectory(src)
12 add_subdirectory(examples/pub) 11 add_subdirectory(examples/pub)
13 add_subdirectory(examples/sub) 12 add_subdirectory(examples/sub)
scripts/submodules.list
1 -SUB_MODULES_OPEN="cmake  
2 -logger" 1 +SUB_MODULES_OPEN="cmake"
3 2
4 SUB_MODULES_CLOSED="" 3 SUB_MODULES_CLOSED=""
src/CMakeLists.txt
@@ -14,6 +14,8 @@ include_directories( @@ -14,6 +14,8 @@ include_directories(
14 ) 14 )
15 15
16 set(SRC_LIST 16 set(SRC_LIST
  17 + ${CMAKE_CURRENT_SOURCE_DIR}/log.cpp
  18 + ${CMAKE_CURRENT_SOURCE_DIR}/threadcontext.cpp
17 ${CMAKE_CURRENT_SOURCE_DIR}/mqttpublisherbase.cpp 19 ${CMAKE_CURRENT_SOURCE_DIR}/mqttpublisherbase.cpp
18 ${CMAKE_CURRENT_SOURCE_DIR}/mqttsubscriberbase.cpp 20 ${CMAKE_CURRENT_SOURCE_DIR}/mqttsubscriberbase.cpp
19 ${CMAKE_CURRENT_SOURCE_DIR}/clientpaho.cpp 21 ${CMAKE_CURRENT_SOURCE_DIR}/clientpaho.cpp
@@ -47,7 +49,6 @@ add_libraries( @@ -47,7 +49,6 @@ add_libraries(
47 Boost::boost 49 Boost::boost
48 Boost::regex 50 Boost::regex
49 paho-mqtt3a 51 paho-mqtt3a
50 - ${CMAKE_SOURCE_DIR}/build/lib/liblogger.a  
51 ) 52 )
52 53
53 include(installation) 54 include(installation)
src/log.cpp 0 → 100644
  1 +/* ****************************************************************************
  2 + * Copyright 2019 Open Systems Development BV *
  3 + * *
  4 + * Permission is hereby granted, free of charge, to any person obtaining a *
  5 + * copy of this software and associated documentation files (the "Software"), *
  6 + * to deal in the Software without restriction, including without limitation *
  7 + * the rights to use, copy, modify, merge, publish, distribute, sublicense, *
  8 + * and/or sell copies of the Software, and to permit persons to whom the *
  9 + * Software is furnished to do so, subject to the following conditions: *
  10 + * *
  11 + * The above copyright notice and this permission notice shall be included in *
  12 + * all copies or substantial portions of the Software. *
  13 + * *
  14 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
  15 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
  16 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
  17 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *
  18 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *
  19 + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *
  20 + * DEALINGS IN THE SOFTWARE. *
  21 + * ***************************************************************************/
  22 +
  23 +#include "log.h"
  24 +#include "threadcontext.h"
  25 +
  26 +namespace osdev {
  27 +namespace components {
  28 +namespace log {
  29 +
  30 +int toInt( LogLevel level )
  31 +{
  32 + switch( level )
  33 + {
  34 + case LogLevel::Emergency:
  35 + return 0;
  36 + case LogLevel::Alert:
  37 + return 1;
  38 + case LogLevel::Critical:
  39 + return 2;
  40 + case LogLevel::Error:
  41 + return 3;
  42 + case LogLevel::Warning:
  43 + return 4;
  44 + case LogLevel::Notice:
  45 + return 5;
  46 + case LogLevel::Info:
  47 + return 6;
  48 + case LogLevel::Debug:
  49 + return 7;
  50 + }
  51 + return -1;
  52 +}
  53 +
  54 +std::string Log::s_context = std::string();
  55 +std::string Log::s_fileName = std::string();
  56 +LogLevel Log::s_logLevel = LogLevel::Error;
  57 +LogMask Log::s_logMask = LogMask::None;
  58 +
  59 +void Log::init( const std::string& context, const std::string& logFile, LogLevel logDepth )
  60 +{
  61 + s_logLevel = logDepth;
  62 + s_context = context;
  63 +
  64 + if ( !logFile.empty() )
  65 + {
  66 + s_fileName = logFile;
  67 + }
  68 +}
  69 +
  70 +void Log::terminate()
  71 +{
  72 + s_context.clear();
  73 + s_fileName.clear();
  74 + s_logLevel = LogLevel::Debug;
  75 + s_logMask = LogMask::None;
  76 +}
  77 +
  78 +void Log::write( const int &priority, const std::string &message, const std::string& context )
  79 +{
  80 + switch( s_logMask )
  81 + {
  82 + case LogMask::Mask:
  83 + setlogmask( LOG_MASK( toInt( s_logLevel ) ) );
  84 + break;
  85 + case LogMask::Upto:
  86 + setlogmask( LOG_UPTO( toInt( s_logLevel ) ) );
  87 + break;
  88 + case LogMask::None:
  89 + setlogmask( LOG_UPTO( toInt( LogLevel::Debug ) ) );
  90 + break;
  91 + default:
  92 + break;
  93 + }
  94 +
  95 + if( !context.empty() )
  96 + {
  97 + s_context = context;
  98 + openlog( s_context.c_str(), LOG_PID, LOG_USER );
  99 + }
  100 + else
  101 + {
  102 + openlog( NULL, LOG_PID, LOG_USER );
  103 + }
  104 +
  105 + syslog( priority, "%s", message.c_str() );
  106 + closelog();
  107 +}
  108 +
  109 +std::string Log::fileinfoMessage( const char* file, int line, const std::string& message )
  110 +{
  111 + (void)file;
  112 + (void)line;
  113 +
  114 + return message;
  115 +}
  116 +
  117 +void Log::log( const std::string &category, const std::string &message, LogLevel level )
  118 +{
  119 + std::string logCategory = category;
  120 + std::string logMessage = message;
  121 + if( logMessage.empty() )
  122 + {
  123 + static const std::string emptyMessage( "--" );
  124 + logMessage = emptyMessage;
  125 + }
  126 + else
  127 + {
  128 + // Replace % signs
  129 + ReplaceAll( logMessage, "%", "%%" );
  130 + }
  131 +
  132 + write( toInt( level ), logMessage, logCategory );
  133 +}
  134 +
  135 +// Static functions
  136 +void Log::emergency( const char *file, int line, const std::string &category, const std::string &message )
  137 +{
  138 + log( category, fileinfoMessage( file, line, message ), LogLevel::Emergency );
  139 +}
  140 +
  141 +void Log::alert( const char *file, int line, const std::string &category, const std::string &message )
  142 +{
  143 + log( category, fileinfoMessage( file, line, message ), LogLevel::Alert );
  144 +}
  145 +
  146 +void Log::critical( const char *file, int line, const std::string &category, const std::string &message )
  147 +{
  148 + log( category, fileinfoMessage( file, line, message ), LogLevel::Critical );
  149 +}
  150 +
  151 +void Log::error( const char *file, int line, const std::string &category, const std::string &message )
  152 +{
  153 + log( category, fileinfoMessage( file, line, message ), LogLevel::Error );
  154 +}
  155 +
  156 +void Log::warning( const char *file, int line, const std::string &category, const std::string &message )
  157 +{
  158 + log( category, fileinfoMessage( file, line, message ), LogLevel::Warning );
  159 +}
  160 +
  161 +void Log::notice( const char *file, int line, const std::string &category, const std::string &message )
  162 +{
  163 + log( category, fileinfoMessage( file, line, message ), LogLevel::Notice );
  164 +}
  165 +
  166 +void Log::info( const char *file, int line, const std::string &category, const std::string &message )
  167 +{
  168 + log( category, fileinfoMessage( file, line, message ), LogLevel::Info );
  169 +}
  170 +
  171 +void Log::debug( const char *file, int line, const std::string &category, const std::string &message )
  172 +{
  173 + log( category, fileinfoMessage( file, line, message ), LogLevel::Debug );
  174 +}
  175 +
  176 +// Protected functions
  177 +void Log::emergency( const std::string &category, const std::string &message )
  178 +{
  179 + write( toInt( LogLevel::Emergency ), message, category );
  180 +}
  181 +
  182 +void Log::alert( const std::string &category, const std::string &message )
  183 +{
  184 + write( toInt( LogLevel::Alert ), message, category );
  185 +}
  186 +
  187 +void Log::critical( const std::string &category, const std::string &message )
  188 +{
  189 + write( toInt( LogLevel::Critical ), message, category );
  190 +}
  191 +
  192 +void Log::error( const std::string &category, const std::string &message )
  193 +{
  194 + write( toInt( LogLevel::Error ), message, category );
  195 +}
  196 +
  197 +void Log::warning( const std::string &category, const std::string &message )
  198 +{
  199 + write( toInt( LogLevel::Warning ), message, category );
  200 +}
  201 +
  202 +void Log::notice( const std::string &category, const std::string &message )
  203 +{
  204 + write( toInt( LogLevel::Notice ), message, category );
  205 +}
  206 +
  207 +void Log::info( const std::string &category, const std::string &message )
  208 +{
  209 + write( toInt( LogLevel::Info ), message, category );
  210 +}
  211 +
  212 +void Log::debug( const std::string &category, const std::string &message )
  213 +{
  214 + write( toInt( LogLevel::Debug ), message, category );
  215 +}
  216 +
  217 +void Log::ReplaceAll( std::string &strToReplace, const std::string& from_chars, const std::string& to_chars )
  218 +{
  219 + size_t start_pos = 0;
  220 + while( ( start_pos = strToReplace.find( from_chars, start_pos ) ) != std::string::npos )
  221 + {
  222 + strToReplace.replace( start_pos, from_chars.length(), to_chars );
  223 + start_pos += to_chars.length(); // Handles case where 'to' is a substring of 'from'
  224 + }
  225 +}
  226 +
  227 +} /* End namespace log */
  228 +} /* End namespace components */
  229 +} /* End namespace osdev */
src/log.h 0 → 100644
  1 +/* ****************************************************************************
  2 + * Copyright 2019 Open Systems Development BV *
  3 + * *
  4 + * Permission is hereby granted, free of charge, to any person obtaining a *
  5 + * copy of this software and associated documentation files (the "Software"), *
  6 + * to deal in the Software without restriction, including without limitation *
  7 + * the rights to use, copy, modify, merge, publish, distribute, sublicense, *
  8 + * and/or sell copies of the Software, and to permit persons to whom the *
  9 + * Software is furnished to do so, subject to the following conditions: *
  10 + * *
  11 + * The above copyright notice and this permission notice shall be included in *
  12 + * all copies or substantial portions of the Software. *
  13 + * *
  14 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
  15 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
  16 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
  17 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *
  18 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *
  19 + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *
  20 + * DEALINGS IN THE SOFTWARE. *
  21 + * ***************************************************************************/
  22 +#pragma once
  23 +
  24 +#include <string>
  25 +#include <syslog.h>
  26 +
  27 +namespace osdev {
  28 +namespace components {
  29 +namespace log {
  30 +
  31 +#define LogEmergency(context, text) \
  32 + if (osdev::components::log::Log::level() >= osdev::components::log::LogLevel::Emergency)\
  33 + { \
  34 + osdev::components::log::Log::emergency(__FILE__, __LINE__, context, text); \
  35 + }
  36 +
  37 +#define LogAlert(context, text) \
  38 + if (osdev::components::log::Log::level() >= osdev::components::log::LogLevel::Alert) \
  39 + { \
  40 + osdev::components::log::Log::alert(__FILE__, __LINE__, context, text); \
  41 + }
  42 +
  43 +#define LogCritical(context, text) \
  44 + if (osdev::components::log::Log::level() >= osdev::components::log::LogLevel::Critical) \
  45 + { \
  46 + osdev::components::log::Log::critical(__FILE__, __LINE__, context, text); \
  47 + }
  48 +
  49 +#define LogError(context, text) \
  50 + if (osdev::components::log::Log::level() >= osdev::components::log::LogLevel::Error) \
  51 + { \
  52 + osdev::components::log::Log::error(__FILE__, __LINE__, context, text); \
  53 + }
  54 +
  55 +#define LogWarning(context, text) \
  56 + if (osdev::components::log::Log::level() >= osdev::components::log::LogLevel::Warning) \
  57 + { \
  58 + osdev::components::log::Log::warning(__FILE__, __LINE__, context, text); \
  59 + }
  60 +
  61 +#define LogNotice(context, text) \
  62 + if (osdev::components::log::Log::level() >= osdev::components::log::LogLevel::Notice) \
  63 + { \
  64 + osdev::components::log::Log::notice(__FILE__, __LINE__, context, text); \
  65 + }
  66 +
  67 +#define LogInfo(context, text) \
  68 + if (osdev::components::log::Log::level() >= osdev::components::log::LogLevel::Info) \
  69 + { \
  70 + osdev::components::log::Log::info(__FILE__, __LINE__, context, text); \
  71 + }
  72 +
  73 +#define LogDebug(context, text) \
  74 + if (osdev::components::log::Log::level() >= osdev::components::log::LogLevel::Debug) \
  75 + { \
  76 + osdev::components::log::Log::debug(__FILE__, __LINE__, context, text); \
  77 + }
  78 +
  79 +/*!
  80 + * \brief The LogLevel enum
  81 + * Enumeration class dealing with LogLevels.
  82 + * Used to convert to syslog macro's.
  83 + */
  84 +enum class LogLevel
  85 +{
  86 + Emergency = 0,
  87 + Alert,
  88 + Critical,
  89 + Error,
  90 + Warning,
  91 + Notice,
  92 + Info,
  93 + Debug
  94 +};
  95 +
  96 +/*!
  97 + * \brief The LogMask enum
  98 + * Enumeration class dealing with LogMask.
  99 + * Used to convert to syslog macro's.
  100 + */
  101 +enum class LogMask
  102 +{
  103 + Mask = 0,
  104 + Upto,
  105 + None
  106 +};
  107 +
  108 +/*! \class Log
  109 + \brief Basic logging mechanism.
  110 +*/
  111 +class Log
  112 +{
  113 +public:
  114 + /**
  115 + * @brief Initialize the logging mechanism
  116 + * @param context - The main context
  117 + * @param logFile - Logfile if available
  118 + * @param logDepth - Initial log-depth
  119 + */
  120 + static void init( const std::string& context,
  121 + const std::string& logFile = std::string(),
  122 + LogLevel logDepth = LogLevel::Info );
  123 +
  124 + //! Shutdown the logging mechanism
  125 + static void terminate();
  126 +
  127 + /*!
  128 + * \brief Write to syslog
  129 + * \param priority - priority level [from debug up to emergency]
  130 + * \param message - The string to print
  131 + * \param context - The context name. default name is the name of the executable.
  132 + */
  133 + static void write( const int &priority, const std::string &message, const std::string &context = std::string() );
  134 +
  135 + /**
  136 + * @brief Log an emergency message in a category.
  137 + * @param file - Name of the source-file
  138 + * @param line - The line number in the source-file
  139 + * @param category - The category of the message.
  140 + * @param message - The string to print
  141 + */
  142 + static void emergency( const char* file, int line, const std::string& category, const std::string& message );
  143 + /**
  144 + * @brief Log an alert message in a category.
  145 + * @param file - Name of the source-file
  146 + * @param line - The line number in the source-file
  147 + * @param category - The category of the message.
  148 + * @param message - The string to print
  149 + */
  150 + static void alert ( const char* file, int line, const std::string& category, const std::string& message );
  151 + /**
  152 + * @brief Log a critical message in a category.
  153 + * @param file - Name of the source-file
  154 + * @param line - The line number in the source-file
  155 + * @param category - The category of the message.
  156 + * @param message - The string to print
  157 + */
  158 + static void critical ( const char* file, int line, const std::string& category, const std::string& message );
  159 + /**
  160 + * @brief Log an error message in a category.
  161 + * @param file - Name of the source-file
  162 + * @param line - The line number in the source-file
  163 + * @param category - The category of the message.
  164 + * @param message - The string to print
  165 + */
  166 + static void error ( const char* file, int line, const std::string& category, const std::string& message );
  167 + /**
  168 + * @brief Log a warning message in a category.
  169 + * @param file - Name of the source-file
  170 + * @param line - The line number in the source-file
  171 + * @param category - The category of the message.
  172 + * @param message - The string to print
  173 + */
  174 + static void warning ( const char* file, int line, const std::string& category, const std::string& message );
  175 + /**
  176 + * @brief Log a notice message in a category.
  177 + * @param file - Name of the source-file
  178 + * @param line - The line number in the source-file
  179 + * @param category - The category of the message.
  180 + * @param message - The string to print
  181 + */
  182 + static void notice ( const char* file, int line, const std::string& category, const std::string& message );
  183 + /**
  184 + * @brief Log an info message in a category.
  185 + * @param file - Name of the source-file
  186 + * @param line - The line number in the source-file
  187 + * @param category - The category of the message.
  188 + * @param message - The string to print
  189 + */
  190 + static void info ( const char* file, int line, const std::string& category, const std::string& message );
  191 + /**
  192 + * @brief Log a debug message in a category.
  193 + * @param file - Name of the source-file
  194 + * @param line - The line number in the source-file
  195 + * @param category - The category of the message.
  196 + * @param message - The string to print
  197 + */
  198 + static void debug ( const char* file, int line, const std::string& category, const std::string& message );
  199 +
  200 + /**
  201 + * @return The current log level.
  202 + */
  203 + static LogLevel level()
  204 + {
  205 + if( s_logMask == LogMask::None )
  206 + {
  207 + return LogLevel::Debug;
  208 + }
  209 + return s_logLevel;
  210 + }
  211 +
  212 + /*!
  213 + * \brief setMask update the current logMask
  214 + * \param logMask - Enum defining the logmask used.
  215 + */
  216 + static void setMask ( LogMask logMask ) { s_logMask = logMask; }
  217 + /*!
  218 + * \brief setLogLevel update the current logLevel
  219 + * \param logLevel - Enum defining the logLevel used, in combination with Mask.
  220 + */
  221 + static void setLogLevel( LogLevel logLevel ) { s_logLevel = logLevel; }
  222 + /*!
  223 + * \brief setContext update the current context
  224 + * \param context - String containing the new context name.
  225 + */
  226 + static void setContext ( std::string context ) { s_context = context; }
  227 +
  228 +protected:
  229 + /**
  230 + * @brief Log an emergency message in a category.
  231 + * @param category The category of the message.
  232 + * @param message The string to print.
  233 + */
  234 + static void emergency( const std::string& category, const std::string& message );
  235 + /**
  236 + * @brief Log an alert message in a category.
  237 + * @param category The category of the message.
  238 + * @param message The string to print.
  239 + */
  240 + static void alert ( const std::string& category, const std::string& message );
  241 + /**
  242 + * @brief Log a critical message in a category.
  243 + * @param category The category of the message.
  244 + * @param message The string to print.
  245 + */
  246 + static void critical ( const std::string& category, const std::string& message );
  247 + /**
  248 + * @brief Log an error message in a category.
  249 + * @param category The category of the message.
  250 + * @param message The string to print.
  251 + */
  252 + static void error ( const std::string& category, const std::string& message );
  253 + /**
  254 + * @brief Log a warning message in a category.
  255 + * @param category The category of the message.
  256 + * @param message The string to print.
  257 + */
  258 + static void warning ( const std::string& category, const std::string& message );
  259 + /**
  260 + * @brief Log a notice message in a category.
  261 + * @param category The category of the message.
  262 + * @param message The string to print.
  263 + */
  264 + static void notice ( const std::string& category, const std::string& message );
  265 + /**
  266 + * @brief Log an info message in a category.
  267 + * @param category The category of the message.
  268 + * @param message The string to print.
  269 + */
  270 + static void info ( const std::string& category, const std::string& message );
  271 + /**
  272 + * @brief Log an debug message in a category.
  273 + * @param category The category of the message.
  274 + * @param message The string to print.
  275 + */
  276 + static void debug ( const std::string& category, const std::string& message );
  277 +
  278 + /**
  279 + * @brief Log an error message in a category.
  280 + * @param category The category of the message.
  281 + * @param message The string to print.
  282 + * @param level Selected log level
  283 + */
  284 + static void log( const std::string &category,
  285 + const std::string &message,
  286 + LogLevel level );
  287 +
  288 +private:
  289 + /**
  290 + * @brief Replace the characters in a std::string with other characters.
  291 + * @param strToReplace The string we want to replace characters in
  292 + * @param from_chars The characters we want to replace
  293 + * @param to_chars The characters we want to replace with.
  294 + * @return strToReplace This is the original string with the replaced characters.
  295 + */
  296 + static void ReplaceAll( std::string &strToReplace, const std::string& from_chars, const std::string& to_chars );
  297 +
  298 + /**
  299 + * @brief Put filename, line-number and message in one string
  300 + * @param file Source-file
  301 + * @param line Line in source-file
  302 + * @param message The string to print
  303 + * @return Formatted string with file, line and message
  304 + */
  305 + static std::string fileinfoMessage(const char* file, int line,
  306 + const std::string& message);
  307 +
  308 + //! The main context.
  309 + static std::string s_context;
  310 +
  311 + //! The name of the LogFile.
  312 + static std::string s_fileName;
  313 +
  314 + //! The amount of logging
  315 + static LogLevel s_logLevel;
  316 +
  317 + //! The mask
  318 + static LogMask s_logMask;
  319 +};
  320 +
  321 +} // End namespace log
  322 +} // End namespace components
  323 +} // End namespace osdev
  324 +
src/threadcontext.cpp 0 → 100644
  1 +/* ****************************************************************************
  2 + * Copyright 2019 Open Systems Development BV *
  3 + * *
  4 + * Permission is hereby granted, free of charge, to any person obtaining a *
  5 + * copy of this software and associated documentation files (the "Software"), *
  6 + * to deal in the Software without restriction, including without limitation *
  7 + * the rights to use, copy, modify, merge, publish, distribute, sublicense, *
  8 + * and/or sell copies of the Software, and to permit persons to whom the *
  9 + * Software is furnished to do so, subject to the following conditions: *
  10 + * *
  11 + * The above copyright notice and this permission notice shall be included in *
  12 + * all copies or substantial portions of the Software. *
  13 + * *
  14 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
  15 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
  16 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
  17 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *
  18 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *
  19 + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *
  20 + * DEALINGS IN THE SOFTWARE. *
  21 + * ***************************************************************************/
  22 +
  23 +#include "threadcontext.h"
  24 +
  25 +// std
  26 +#include <thread>
  27 +
  28 +using namespace osdev::components;
  29 +
  30 +ThreadContextScope::ThreadContextScope(const std::string& _context)
  31 + : m_previousContext(ThreadContext::instance().context())
  32 +{
  33 + ThreadContext::instance().setContext(_context);
  34 +}
  35 +
  36 +ThreadContextScope::~ThreadContextScope()
  37 +{
  38 + ThreadContext::instance().setContext(m_previousContext);
  39 +}
  40 +
  41 +// static
  42 +ThreadContext& ThreadContext::instance()
  43 +{
  44 + static thread_local ThreadContext tc;
  45 + return tc;
  46 +}
  47 +
  48 +ThreadContext::ThreadContext()
  49 + : m_context("default")
  50 +{
  51 +}
  52 +
src/threadcontext.h 0 → 100644
  1 +/* ****************************************************************************
  2 + * Copyright 2019 Open Systems Development BV *
  3 + * *
  4 + * Permission is hereby granted, free of charge, to any person obtaining a *
  5 + * copy of this software and associated documentation files (the "Software"), *
  6 + * to deal in the Software without restriction, including without limitation *
  7 + * the rights to use, copy, modify, merge, publish, distribute, sublicense, *
  8 + * and/or sell copies of the Software, and to permit persons to whom the *
  9 + * Software is furnished to do so, subject to the following conditions: *
  10 + * *
  11 + * The above copyright notice and this permission notice shall be included in *
  12 + * all copies or substantial portions of the Software. *
  13 + * *
  14 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
  15 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
  16 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
  17 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *
  18 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *
  19 + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *
  20 + * DEALINGS IN THE SOFTWARE. *
  21 + * ***************************************************************************/
  22 +#ifndef OSDEV_COMPONENTS_THREADCONTEXT_H
  23 +#define OSDEV_COMPONENTS_THREADCONTEXT_H
  24 +
  25 +// Qt
  26 +#include <string>
  27 +
  28 +namespace osdev {
  29 +namespace components {
  30 +
  31 +/**
  32 + * @brief Set the current thread context.
  33 + * The context is restored to the previous context when this object goes out of scope.
  34 + * @note This object is meant to be used on the stack.
  35 + */
  36 +class ThreadContextScope
  37 +{
  38 +public:
  39 + /**
  40 + * @brief Construct a scoped object that sets the current thread context.
  41 + * @param context The context that will be used by the logging framework.
  42 + */
  43 + explicit ThreadContextScope(const std::string& context);
  44 + ~ThreadContextScope();
  45 +
  46 + // Non copyable and non movable
  47 + ThreadContextScope(const ThreadContextScope&) = delete;
  48 + ThreadContextScope& operator=(const ThreadContextScope&) = delete;
  49 + ThreadContextScope(ThreadContextScope&&) = delete;
  50 + ThreadContextScope& operator=(ThreadContextScope&&) = delete;
  51 +
  52 +private:
  53 + std::string m_previousContext; ///< Copy of the previous context.
  54 +};
  55 +
  56 +/**
  57 + * @brief Add context to a thread.
  58 + * For every thread only one specific instance of this object will exist.
  59 + * @note Contexts can only be set by using a ThreadContextScope object.
  60 + */
  61 +class ThreadContext
  62 +{
  63 +
  64 +// Contexts can only be set by using a ThreadContextScope object.
  65 +friend class ThreadContextScope;
  66 +
  67 +public:
  68 + static ThreadContext& instance();
  69 +
  70 + /**
  71 + * @brief Return the thread context.
  72 + */
  73 + const std::string& context() const
  74 + {
  75 + return m_context;
  76 + }
  77 +
  78 +private:
  79 + /**
  80 + * @brief Set the thread context.
  81 + */
  82 + void setContext(const std::string& contextString)
  83 + {
  84 + m_context = contextString;
  85 + }
  86 +
  87 + /**
  88 + * Construct a ThreadContext object.
  89 + * The context is set to "default"
  90 + */
  91 + ThreadContext();
  92 +
  93 + // Non copyable and non movable
  94 + ThreadContext(const ThreadContext&) = delete;
  95 + ThreadContext& operator=(const ThreadContext&) = delete;
  96 + ThreadContext(ThreadContext&&) = delete;
  97 + ThreadContext& operator=(ThreadContext&&) = delete;
  98 +
  99 + std::string m_context; ///< The context string
  100 +};
  101 +
  102 +} /* End namespace components */
  103 +} /* End namespace osdev */
  104 +
  105 +#endif // OSDEV_COMPONENTS_THREADCONTEXT_H