ARGoS  3
A parallel, multi-engine simulator for swarm robotics
core/utility/logging/argos_log.h
Go to the documentation of this file.
00001 
00016 #ifndef ARGOSLOG_H
00017 #define ARGOSLOG_H
00018 
00019 #include <argos3/core/config.h>
00020 #include <iomanip>
00021 #include <string>
00022 #include <iostream>
00023 #include <fstream>
00024 #include <cstdio>
00025 #include <cstring>
00026 #include <cstdlib>
00027 
00028 #ifdef ARGOS_THREADSAFE_LOG
00029 #include <pthread.h>
00030 #include <sstream>
00031 #include <map>
00032 #include <vector>
00033 #endif
00034 
00035 namespace argos {
00036    class CARGOSLogger;
00037 }
00038 
00039 #include <argos3/core/utility/logging/argos_colored_text.h>
00040 
00041 namespace argos {
00042 
00043    class CARGoSLog {
00044 
00045    private:
00046 
00048       std::ostream& m_cStream;
00049 
00051       SLogColor m_sLogColor;
00052 
00054       bool m_bColoredOutput;
00055 
00056 #ifdef ARGOS_THREADSAFE_LOG
00057 
00058       std::map<pthread_t, size_t> m_mapStreamOrder;
00059 
00061       std::vector<std::stringstream*> m_vecStreams;
00062 
00064       pthread_mutex_t m_tMutex;
00065 #endif
00066 
00067    public:
00068 
00069       CARGoSLog(std::ostream& c_stream,
00070                 const SLogColor& s_log_color,
00071                 bool b_colored_output_enabled = true) :
00072          m_cStream(c_stream),
00073          m_sLogColor(s_log_color),
00074          m_bColoredOutput(b_colored_output_enabled) {
00075 #ifdef ARGOS_THREADSAFE_LOG
00076          pthread_mutex_init(&m_tMutex, NULL);
00077          AddThreadSafeBuffer();
00078 #endif
00079       }
00080 
00081       ~CARGoSLog() {
00082 #ifdef ARGOS_THREADSAFE_LOG
00083          pthread_mutex_destroy(&m_tMutex);
00084          while(!m_vecStreams.empty()) {
00085             delete m_vecStreams.back();
00086             m_vecStreams.pop_back();
00087          }
00088 #endif
00089          if(m_bColoredOutput) {
00090             reset(m_cStream);
00091          }
00092       }
00093 
00094       inline void EnableColoredOutput() {
00095          m_bColoredOutput = true;
00096       }
00097 
00098       inline void DisableColoredOutput() {
00099          m_bColoredOutput = false;
00100       }
00101 
00102       inline bool IsColoredOutput() const {
00103          return m_bColoredOutput;
00104       }
00105 
00106       inline std::ostream& GetStream() {
00107          return m_cStream;
00108       }
00109 
00110 #ifdef ARGOS_THREADSAFE_LOG
00111       inline void Flush() {
00112          pthread_mutex_lock(&m_tMutex);
00113          for(size_t i = 0; i < m_vecStreams.size(); ++i) {
00114             m_cStream << m_vecStreams[i]->str();
00115             m_vecStreams[i]->str("");
00116          }
00117          pthread_mutex_unlock(&m_tMutex);
00118       }
00119 
00120       inline void AddThreadSafeBuffer() {
00121          pthread_mutex_lock(&m_tMutex);
00122          m_mapStreamOrder.insert(std::make_pair<pthread_t, size_t>(pthread_self(), m_vecStreams.size()));
00123          m_vecStreams.push_back(new std::stringstream);
00124          pthread_mutex_unlock(&m_tMutex);
00125       }
00126 #else
00127       void Flush() {}
00128 #endif
00129       
00130       inline CARGoSLog& operator<<(std::ostream& (*c_stream)(std::ostream&)) {
00131 #ifdef ARGOS_THREADSAFE_LOG
00132          *(m_vecStreams[m_mapStreamOrder.find(pthread_self())->second]) << c_stream;
00133 #else
00134          m_cStream << c_stream;
00135 #endif
00136          return *this;
00137       }
00138 
00139       template <typename T> CARGoSLog& operator<<(const T t_msg) {
00140          if(m_bColoredOutput) {
00141 #ifdef ARGOS_THREADSAFE_LOG
00142             *(m_vecStreams[m_mapStreamOrder.find(pthread_self())->second]) << m_sLogColor << t_msg << reset;
00143 #else
00144             m_cStream << m_sLogColor << t_msg << reset;
00145 #endif
00146          }
00147          else {
00148 #ifdef ARGOS_THREADSAFE_LOG
00149             *(m_vecStreams[m_mapStreamOrder.find(pthread_self())->second]) << t_msg;
00150 #else
00151             m_cStream << m_sLogColor << t_msg << reset;
00152 #endif
00153          }
00154          return *this;
00155       }
00156 
00157    };
00158 
00159    extern CARGoSLog LOG;
00160    extern CARGoSLog LOGERR;
00161 
00162 }
00163 
00164 #define RLOG    LOG    << "[" << GetId() << "] "
00165 #define RLOGERR LOGERR << "[" << GetId() << "] "
00166 
00167 #endif