00001 /*!@file Util/TextLog.C Functions for logging model/simulation events */ 00002 00003 // //////////////////////////////////////////////////////////////////// // 00004 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2000-2005 // 00005 // by the University of Southern California (USC) and the iLab at USC. // 00006 // See http://iLab.usc.edu for information about this project. // 00007 // //////////////////////////////////////////////////////////////////// // 00008 // Major portions of the iLab Neuromorphic Vision Toolkit are protected // 00009 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency // 00010 // in Visual Environments, and Applications'' by Christof Koch and // 00011 // Laurent Itti, California Institute of Technology, 2001 (patent // 00012 // pending; application number 09/912,225 filed July 23, 2001; see // 00013 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status). // 00014 // //////////////////////////////////////////////////////////////////// // 00015 // This file is part of the iLab Neuromorphic Vision C++ Toolkit. // 00016 // // 00017 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can // 00018 // redistribute it and/or modify it under the terms of the GNU General // 00019 // Public License as published by the Free Software Foundation; either // 00020 // version 2 of the License, or (at your option) any later version. // 00021 // // 00022 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope // 00023 // that it will be useful, but WITHOUT ANY WARRANTY; without even the // 00024 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // 00025 // PURPOSE. See the GNU General Public License for more details. // 00026 // // 00027 // You should have received a copy of the GNU General Public License // 00028 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write // 00029 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, // 00030 // Boston, MA 02111-1307 USA. // 00031 // //////////////////////////////////////////////////////////////////// // 00032 // 00033 // Primary maintainer for this file: Rob Peters <rjpeters at usc dot edu> 00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Util/TextLog.C $ 00035 // $Id: TextLog.C 6528 2006-04-25 18:57:30Z rjpeters $ 00036 // 00037 00038 #ifndef UTIL_TEXTLOG_C_DEFINED 00039 #define UTIL_TEXTLOG_C_DEFINED 00040 00041 #include "Util/TextLog.H" 00042 00043 #include "Util/Assert.H" 00044 #include "Util/SimTime.H" 00045 #include "Util/log.H" 00046 #include "Util/sformat.H" 00047 #include "rutz/mutex.h" 00048 00049 #include <fstream> 00050 #include <map> 00051 00052 /* A note on the implementation strategy here for the text-logging 00053 functions: internally, we keep a map of TextLogger objects, one per 00054 filename. When one of the public functions is called, we look up 00055 the associated TextLogger object, creating it if needed, and then 00056 perform the requested logging action on that object. 00057 */ 00058 00059 namespace 00060 { 00061 // ###################################################################### 00062 class TextLogger 00063 { 00064 public: 00065 TextLogger(const std::string& fname) 00066 : 00067 itsMutex(), 00068 itsStream(fname.c_str()), 00069 itsTime(SimTime::ZERO()) 00070 { 00071 pthread_mutex_init(&itsMutex, 0); 00072 00073 if (!itsStream.is_open()) 00074 { 00075 LFATAL("Couldn't open text log file '%s' for writing", 00076 fname.c_str()); 00077 } 00078 else 00079 { 00080 LINFO("Opened textlog file '%s'", fname.c_str()); 00081 } 00082 } 00083 00084 void log(const std::string& event, 00085 const std::string& details) 00086 { 00087 this->log(event, details, itsTime); 00088 } 00089 00090 void log(const std::string& event, 00091 const std::string& details, 00092 const SimTime& t) 00093 { 00094 GVX_MUTEX_LOCK(&itsMutex); 00095 00096 itsStream 00097 << sformat("%010.02fms %-20s ", t.msecs(), event.c_str()) 00098 << details << std::endl; 00099 itsStream.flush(); // don't lose messages if ctrl-C 00100 } 00101 00102 void setTime(const SimTime& t) 00103 { 00104 GVX_MUTEX_LOCK(&itsMutex); 00105 00106 itsTime = t; 00107 } 00108 00109 private: 00110 pthread_mutex_t itsMutex; 00111 std::ofstream itsStream; 00112 SimTime itsTime; 00113 }; 00114 00115 // ###################################################################### 00116 typedef std::map<std::string, TextLogger*> LoggerMap; 00117 00118 LoggerMap* g_loggers; 00119 pthread_mutex_t g_loggers_mutex = PTHREAD_MUTEX_INITIALIZER; 00120 00121 pthread_once_t g_loggers_init_once = PTHREAD_ONCE_INIT; 00122 void loggers_init() 00123 { 00124 ASSERT(g_loggers == 0); 00125 g_loggers = new LoggerMap; 00126 } 00127 00128 // ###################################################################### 00129 TextLogger* get_logger(const std::string& fname) 00130 { 00131 pthread_once(&g_loggers_init_once, loggers_init); 00132 00133 ASSERT(g_loggers != 0); 00134 00135 GVX_MUTEX_LOCK(&g_loggers_mutex); 00136 00137 LoggerMap::iterator itr = g_loggers->find(fname); 00138 00139 if (itr != g_loggers->end()) 00140 { 00141 return (*itr).second; 00142 } 00143 00144 // else, let's create a new logger for the given fname 00145 TextLogger* logger = new TextLogger(fname); 00146 g_loggers->insert(LoggerMap::value_type(fname, logger)); 00147 return logger; 00148 } 00149 } 00150 00151 // ###################################################################### 00152 void textLog(const std::string& fname, 00153 const std::string& event, 00154 const std::string& details) 00155 { 00156 if (!fname.empty()) 00157 get_logger(fname)->log(event, details); 00158 } 00159 00160 // ###################################################################### 00161 void textLog(const std::string& fname, 00162 const std::string& event, 00163 const std::string& details, 00164 const SimTime& t) 00165 { 00166 if (!fname.empty()) 00167 get_logger(fname)->log(event, details, t); 00168 } 00169 00170 // ###################################################################### 00171 void setLogTime(const std::string& fname, 00172 const SimTime& t) 00173 { 00174 if (!fname.empty()) 00175 get_logger(fname)->setTime(t); 00176 } 00177 00178 // ###################################################################### 00179 /* So things look consistent in everyone's emacs... */ 00180 /* Local Variables: */ 00181 /* mode: c++ */ 00182 /* indent-tabs-mode: nil */ 00183 /* End: */ 00184 00185 #endif // UTIL_TEXTLOG_C_DEFINED