basic_messenger.hh

Go to the documentation of this file.
00001 //
00002 // $Id: basic_messenger.hh,v 1.4 2003/11/18 11:27:31 cholm Exp $ 
00003 //  
00004 //  ylmm::basic_messenger
00005 //  Copyright (C) 2002 Christian Holm Christensen <cholm@nbi.dk> 
00006 //
00007 //  This library is free software; you can redistribute it and/or 
00008 //  modify it under the terms of the GNU Lesser General Public License 
00009 //  as published by the Free Software Foundation; either version 2.1 
00010 //  of the License, or (at your option) any later version. 
00011 //
00012 //  This library is distributed in the hope that it will be useful, 
00013 //  but WITHOUT ANY WARRANTY; without even the implied warranty of 
00014 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
00015 //  Lesser General Public License for more details. 
00016 // 
00017 //  You should have received a copy of the GNU Lesser General Public 
00018 //  License along with this library; if not, write to the Free 
00019 //  Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 
00020 //  02111-1307 USA 
00021 //
00022 #ifndef YLMM_basic_messenger
00023 #define YLMM_basic_messenger
00024 #ifndef __IOSTREAM__
00025 #include <iostream>
00026 #endif
00027 #ifndef __CSTDARG__
00028 #include <cstdarg>
00029 #endif
00030 #ifndef __CSTDIO__
00031 #include <cstdio>
00032 #endif
00033 
00034 /** @file   ylmm/basic_messenger.hh
00035     @author Christian Holm
00036     @date   Sat Jan 18 03:37:32 2003
00037     @brief  Base class for I/O handling */
00038 
00039 /** @defgroup common Common classes */
00040 
00041 namespace ylmm
00042 {
00043   //================================================================
00044   /** @class basic_lock basic_messenger.hh <ylmm/basic_messenger.hh>
00045       @brief Single threaded locking object.  
00046 
00047       Used by ylmm::basic_messenger to insure thread safe static
00048       creation of the default output handler. This implementation does
00049       nothing.  In a real multi-threaded application, the user should
00050       pass a proper mutex locking class, defining at a minimum the
00051       lock and unlock member functions.  
00052       @see @ref thread_issues 
00053       @ingroup common
00054   */ 
00055   class basic_lock 
00056   {
00057   public:
00058     /** Aquire this lock.  This implemtation does nothing. */
00059     void lock() {}
00060     /** Release this lock.  This implemtation does nothing. */
00061     void unlock() {}
00062   };
00063   
00064   //================================================================
00065   /** @class basic_messenger basic_messenger.hh <ylmm/basic_messenger.hh>
00066       @brief Base class for output handling.
00067       @see @ref messenger_doc
00068       @param lock The type of thread syncronisation locks used in the 
00069       application.  Per default a single threaded locking mechanism
00070       (that is - no locks) is used. The application should pass the
00071       appropiate type here to make the use of this class thread safe.
00072       @ingroup common
00073    */
00074   template <typename Lock=basic_lock>
00075   class basic_messenger
00076   {
00077   private:
00078     static basic_messenger* _default_handler; /** The default handler
00079                                                */
00080     static Lock _lock;          /** Lock used to insure safe thread
00081                                     creation of the default handler */
00082   protected:
00083     std::ostream* _err_stream;  /** The stream to write errors to */
00084     std::ostream* _msg_stream;  /** The stream to write messages to */
00085     /// 
00086     /** The real print method
00087         @param o      Output stream
00088         @param format @c printf like format string
00089         @param ap     variadic arugment list */
00090     void print(std::ostream* o, const char* format, va_list ap);
00091   public:
00092     /** Constructor. */
00093     basic_messenger(std::ostream& msg=std::cout, 
00094                          std::ostream& err=std::cerr);
00095     /** Destructor. */
00096     virtual ~basic_messenger() {}
00097 
00098     //@{
00099     /// @name Handling streams
00100     /** Set stream to write errors to. 
00101         @param err_str The stream to write to
00102         @return @a err_str */
00103     std::ostream& error_stream(std::ostream& err_str);  
00104     /** Get the error stream 
00105         @return the error stream */
00106     std::ostream& error_stream() { return *_err_stream; }
00107     /** Set stream to write messages to. 
00108         @param msg_str The stream to write to 
00109         @return @a msg_str */
00110     std::ostream& message_stream(std::ostream& msg_str); 
00111     /** Get the messages stream 
00112         @return the messages stream */
00113     std::ostream& message_stream() { return *_msg_stream; }    
00114     //@}
00115 
00116     //@{
00117     /// @name Normal messages
00118     /** Print a message on the message stream. 
00119         @param format The @c printf like format string */
00120     virtual void message(const char* format, ...);
00121     /** Print a message on the message stream. 
00122         @param format The @c printf like format string
00123         @param ap The variadic arguments. */
00124     virtual void message(const char* format, va_list ap);
00125     //@}
00126     
00127     //@{
00128     /// @name Error messages 
00129     /** Print a error on the error stream. 
00130         @param format The @c printf like format string */
00131     virtual void error(const char* format, ...);
00132     /** Print a error on the error stream. 
00133         @param format The @c printf like format string 
00134         @param ap The variadic arguments. */
00135     virtual void error(const char* format, va_list ap);
00136     //@}
00137     
00138     /** Get the default handler.
00139         @return the default handler. */
00140     static basic_messenger* default_handler();
00141   };
00142   //__________________________________________________________________
00143   template<typename L>
00144   inline 
00145   basic_messenger<L>::basic_messenger(std::ostream& msg_str,
00146                                              std::ostream& err_str)
00147   {
00148     _msg_stream = 0;
00149     _err_stream = 0;
00150     message_stream(msg_str);
00151     error_stream(err_str);
00152   }
00153   //__________________________________________________________________
00154   template<typename L>
00155   inline std::ostream& 
00156   basic_messenger<L>::error_stream(std::ostream& s) 
00157   {
00158     _err_stream = &s;
00159     return *_err_stream;
00160   }
00161   //__________________________________________________________________
00162   template<typename L>
00163   inline std::ostream& 
00164   basic_messenger<L>::message_stream(std::ostream& s) 
00165   {
00166     _msg_stream = &s;
00167     return *_msg_stream;
00168   }
00169   //__________________________________________________________________
00170   template<typename L>
00171   inline void 
00172   basic_messenger<L>::print(std::ostream* o, const char* f, va_list ap)
00173   {
00174     static char buf[1024];
00175     if (!o || o->bad()) return;
00176 #ifdef HAVE_VSNPRINTF
00177     vsnprintf(buf, 1024, f, ap);
00178 #else 
00179     vsprintf(buf, f, ap);
00180 #endif
00181     *o << buf << std::flush;
00182   }    
00183   //__________________________________________________________________
00184   template<typename L>
00185   inline void 
00186   basic_messenger<L>::message(const char* msg, ...) 
00187   {
00188     va_list ap;
00189     va_start(ap, msg);
00190     message(msg, ap);
00191     va_end(ap);
00192   }  
00193   //__________________________________________________________________
00194   template<typename L>
00195   inline void 
00196   basic_messenger<L>::message(const char* msg, va_list ap) 
00197   {
00198     print(_msg_stream, msg, ap);
00199   }
00200   //__________________________________________________________________
00201   template<typename L>
00202   inline void 
00203   basic_messenger<L>::error(const char* err, ...) 
00204   {
00205     va_list ap;
00206     va_start(ap, err);
00207     error(err, ap);
00208     va_end(ap);
00209   }  
00210   //__________________________________________________________________
00211   template<typename L>
00212   inline void 
00213   basic_messenger<L>::error(const char* err, va_list ap) 
00214   {
00215     print(_err_stream, err, ap);
00216   }
00217   //__________________________________________________________________
00218   template<typename L>
00219   inline basic_messenger<L>*
00220   basic_messenger<L>::default_handler() 
00221   {
00222     // Double checking locking idom to avoid race conditions. 
00223     if (!_default_handler) {
00224       _lock.lock();
00225       if (!_default_handler) 
00226         _default_handler = new basic_messenger(std::cout,std::cerr);
00227       _lock.unlock();
00228     }
00229     return _default_handler;
00230   }
00231   //__________________________________________________________________
00232   template<typename L> basic_messenger<L>* 
00233   basic_messenger<L>::_default_handler = 0;
00234   //__________________________________________________________________
00235   template<typename L> L basic_messenger<L>::_lock;
00236 }
00237 
00238 #endif
00239 //____________________________________________________________________
00240 //
00241 // EOF
00242 //
Top of page
Christian Holm (home page)
Last update Fri Jul 8 12:58:03 2005
Created by DoxyGen 1.4.3-20050530