ompl/util/src/Console.cpp
00001 /*********************************************************************
00002 * Software License Agreement (BSD License)
00003 *
00004 *  Copyright (c) 2008, Willow Garage, Inc.
00005 *  All rights reserved.
00006 *
00007 *  Redistribution and use in source and binary forms, with or without
00008 *  modification, are permitted provided that the following conditions
00009 *  are met:
00010 *
00011 *   * Redistributions of source code must retain the above copyright
00012 *     notice, this list of conditions and the following disclaimer.
00013 *   * Redistributions in binary form must reproduce the above
00014 *     copyright notice, this list of conditions and the following
00015 *     disclaimer in the documentation and/or other materials provided
00016 *     with the distribution.
00017 *   * Neither the name of the Willow Garage nor the names of its
00018 *     contributors may be used to endorse or promote products derived
00019 *     from this software without specific prior written permission.
00020 *
00021 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00022 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00023 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00024 *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00025 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00026 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00027 *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00028 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00029 *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00030 *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00031 *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00032 *  POSSIBILITY OF SUCH DAMAGE.
00033 *********************************************************************/
00034 
00035 /* Author: Ioan Sucan */
00036 
00037 #include "ompl/util/Console.h"
00038 #include <boost/thread/mutex.hpp>
00039 #include <iostream>
00040 #include <cstdio>
00041 #include <cstdarg>
00042 
00044 
00045 struct DefaultOutputHandler
00046 {
00047     DefaultOutputHandler()
00048     {
00049         output_handler_ = static_cast<ompl::msg::OutputHandler*>(&std_output_handler_);
00050         previous_output_handler_ = output_handler_;
00051         logLevel_ = ompl::msg::LOG_DEBUG;
00052     }
00053 
00054     ompl::msg::OutputHandlerSTD std_output_handler_;
00055     ompl::msg::OutputHandler   *output_handler_;
00056     ompl::msg::OutputHandler   *previous_output_handler_;
00057     ompl::msg::LogLevel         logLevel_;
00058     boost::mutex                lock_; // it is likely the outputhandler does some I/O, so we serialize it
00059 };
00060 
00061 // we use this function because we want to handle static initialization correctly
00062 // however, the first run of this function is not thread safe, due to the use of a static
00063 // variable inside the function. For this reason, we ensure the first call happens during
00064 // static initialization using a proxy class
00065 static DefaultOutputHandler* getDOH()
00066 {
00067     static DefaultOutputHandler DOH;
00068     return &DOH;
00069 }
00070 
00071 #define USE_DOH                                                                \
00072     DefaultOutputHandler *doh = getDOH();                                      \
00073     boost::mutex::scoped_lock slock(doh->lock_)
00074 
00075 #define MAX_BUFFER_SIZE 1024
00076 
00078 
00079 void ompl::msg::noOutputHandler()
00080 {
00081     USE_DOH;
00082     doh->previous_output_handler_ = doh->output_handler_;
00083     doh->output_handler_ = NULL;
00084 }
00085 
00086 void ompl::msg::restorePreviousOutputHandler()
00087 {
00088     USE_DOH;
00089     std::swap(doh->previous_output_handler_, doh->output_handler_);
00090 }
00091 
00092 void ompl::msg::useOutputHandler(OutputHandler *oh)
00093 {
00094     USE_DOH;
00095     doh->previous_output_handler_ = doh->output_handler_;
00096     doh->output_handler_ = oh;
00097 }
00098 
00099 ompl::msg::OutputHandler* ompl::msg::getOutputHandler()
00100 {
00101     return getDOH()->output_handler_;
00102 }
00103 
00104 void ompl::msg::log(const char *file, int line, LogLevel level, const char *m, ...)
00105 {
00106     USE_DOH;
00107     if (doh->output_handler_ && level >= doh->logLevel_)
00108     {
00109         va_list __ap;
00110         va_start(__ap, m);
00111         char buf[MAX_BUFFER_SIZE];
00112         vsnprintf(buf, sizeof(buf), m, __ap);
00113         va_end(__ap);
00114         buf[MAX_BUFFER_SIZE - 1] = '\0';
00115 
00116         doh->output_handler_->log(buf, level, file, line);
00117     }
00118 }
00119 
00120 void ompl::msg::setLogLevel(LogLevel level)
00121 {
00122     USE_DOH;
00123     doh->logLevel_ = level;
00124 }
00125 
00126 ompl::msg::LogLevel ompl::msg::getLogLevel()
00127 {
00128     USE_DOH;
00129     return doh->logLevel_;
00130 }
00131 
00132 static const char *LogLevelString[4] = {"Debug:   ", "Info:    ", "Warning: ", "Error:   "};
00133 
00134 void ompl::msg::OutputHandlerSTD::log(const std::string &text, LogLevel level, const char *filename, int line)
00135 {
00136     if (level >= LOG_WARN)
00137     {
00138         std::cerr << LogLevelString[level] << text << std::endl;
00139         std::cerr << "         at line " << line << " in " << filename << std::endl;
00140         std::cerr.flush();
00141     }
00142     else
00143     {
00144         std::cout << LogLevelString[level] << text << std::endl;
00145         std::cout.flush();
00146     }
00147 }
00148 
00149 ompl::msg::OutputHandlerFile::OutputHandlerFile(const char *filename) : OutputHandler()
00150 {
00151     file_ = fopen(filename, "a");
00152     if (!file_)
00153         std::cerr << "Unable to open log file: '" << filename << "'" << std::endl;
00154 }
00155 
00156 ompl::msg::OutputHandlerFile::~OutputHandlerFile()
00157 {
00158     if (file_)
00159         if (fclose(file_) != 0)
00160             std::cerr << "Error closing logfile" << std::endl;
00161 }
00162 
00163 void ompl::msg::OutputHandlerFile::log(const std::string &text, LogLevel level, const char *filename, int line)
00164 {
00165     if (file_)
00166     {
00167         fprintf(file_, "%s%s\n", LogLevelString[level], text.c_str());
00168         if(level >= LOG_WARN)
00169             fprintf(file_, "         at line %d in %s\n", line, filename);
00170         fflush(file_);
00171     }
00172 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines