Merge pull request #25 from remia/fix/non-pod-variadic-warning
[asdcplib.git] / src / KM_log.h
index 671c072af58fabc4fe172ee6bcdfb90104e503aa..9279f300a41c6d0e9736a53be8f969adf7e22184 100755 (executable)
@@ -1,5 +1,5 @@
 /*
-Copyright (c) 2004-2007, John Hurst
+Copyright (c) 2004-2009, John Hurst
 All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
@@ -39,6 +39,7 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <stdarg.h>
 #include <errno.h>
 #include <iosfwd>
+#include <set>
 
 #define LOG_MSG_IMPL(t) \
   va_list args; \
@@ -87,6 +88,7 @@ namespace Kumu
     LOG_NOTICE,   // application user info
     LOG_ALERT,    // application non-fatal or near-miss error
     LOG_CRIT,     // application fatal error
+    LOG_MAX
   };
 
 
@@ -149,6 +151,18 @@ namespace Kumu
     protected:
       i32_t m_filter;
       i32_t m_options;
+      Mutex m_lock;
+      std::set<ILogSink*> m_listeners;
+
+      // you must obtain m_lock BEFORE calling this from your own WriteEntry
+      void WriteEntryToListeners(const LogEntry& entry)
+      {
+       std::set<ILogSink*>::iterator i;
+       for ( i = m_listeners.begin(); i != m_listeners.end(); ++i )
+         (*i)->WriteEntry(entry);
+      }
+
+      KM_NO_COPY_CONSTRUCT(ILogSink);
 
     public:
     ILogSink() : m_filter(LOG_ALLOW_ALL), m_options(LOG_OPTION_NONE) {}
@@ -162,6 +176,19 @@ namespace Kumu
       void  UnsetOptionFlag(i32_t o) { m_options &= ~o; }
       bool  TestOptionFlag(i32_t o) const  { return ((m_options & o) == o); }
 
+      void AddListener(ILogSink& s) {
+       if ( &s != this )
+         {
+           AutoMutex l(m_lock);
+           m_listeners.insert(&s);
+         }
+      }
+
+      void DelListener(ILogSink& s) {
+       AutoMutex l(m_lock);
+       m_listeners.erase(&s);
+      }
+
       // library messages
       void Error(const char* fmt, ...)    { LOG_MSG_IMPL(LOG_ERROR); }
       void Warn(const char* fmt, ...)     { LOG_MSG_IMPL(LOG_WARN);  }
@@ -190,51 +217,35 @@ namespace Kumu
   ILogSink& DefaultLogSink();
 
 
-  // Sets a log sink as the default until the object is destroyed.
-  // The original default sink is saved and then restored on delete.
-  class LogSinkContext
-  {
-    KM_NO_COPY_CONSTRUCT(LogSinkContext);
-    LogSinkContext();
-    ILogSink* m_orig;
+  // attach a log sink as a listener until deleted
+  class LogSinkListenContext
+    {
+      ILogSink* m_log_source;
+      ILogSink* m_sink;
+      KM_NO_COPY_CONSTRUCT(LogSinkListenContext);
+      LogSinkListenContext();
+
+    public:
+      LogSinkListenContext(ILogSink& source, ILogSink& sink)
+       {
+         m_log_source = &source;
+         m_sink = &sink;
+         m_log_source->AddListener(*m_sink);
+       }
+
+      ~LogSinkListenContext()
+       {
+         m_log_source->DelListener(*m_sink);
+       }
+    };
 
-  public:
-    LogSinkContext(ILogSink& sink) {
-      m_orig = &DefaultLogSink();
-      SetDefaultLogSink(&sink);
-    }
-
-    ~LogSinkContext() {
-      SetDefaultLogSink(m_orig);
-    }
-  };
 
   //------------------------------------------------------------------------------------------
   //
 
-  // write messages to two subordinate log sinks 
-  class TeeLogSink : public ILogSink
-  {
-    KM_NO_COPY_CONSTRUCT(TeeLogSink);
-    TeeLogSink();
-
-    ILogSink& m_a;
-    ILogSink& m_b;
-
-  public:
-    TeeLogSink(ILogSink& a, ILogSink& b) : m_a(a), m_b(b) {}
-    virtual ~TeeLogSink() {}
-
-    void WriteEntry(const LogEntry& Entry) {
-      m_a.WriteEntry(Entry);
-      m_b.WriteEntry(Entry);
-    }
-  };
-
   // collect log messages into the given list, does not test filter
   class EntryListLogSink : public ILogSink
   {
-    Mutex m_Lock;
     LogEntryList& m_Target;
     KM_NO_COPY_CONSTRUCT(EntryListLogSink);
     EntryListLogSink();
@@ -250,7 +261,6 @@ namespace Kumu
   // write messages to a POSIX stdio stream
   class StdioLogSink : public ILogSink
     {
-      Mutex m_Lock;
       FILE* m_stream;
       KM_NO_COPY_CONSTRUCT(StdioLogSink);
 
@@ -266,7 +276,6 @@ namespace Kumu
   // write messages to the Win32 debug stream
   class WinDbgLogSink : public ILogSink
     {
-      Mutex m_Lock;
       KM_NO_COPY_CONSTRUCT(WinDbgLogSink);
 
     public:
@@ -281,7 +290,6 @@ namespace Kumu
   // write messages to a POSIX file descriptor
   class StreamLogSink : public ILogSink
     {
-      Mutex m_Lock;
       int   m_fd;
       KM_NO_COPY_CONSTRUCT(StreamLogSink);
       StreamLogSink();
@@ -292,6 +300,22 @@ namespace Kumu
 
       void WriteEntry(const LogEntry&);
     };
+
+  // write messages to the syslog facility
+  class SyslogLogSink : public ILogSink
+    {
+      KM_NO_COPY_CONSTRUCT(SyslogLogSink);
+      SyslogLogSink();
+  
+    public:
+      SyslogLogSink(const std::string& source_name, int facility);
+      virtual ~SyslogLogSink();
+      void WriteEntry(const LogEntry&);
+    };
+
+  // convert a string into the appropriate syslog facility id
+  int SyslogNameToFacility(const std::string& facility_name);
+
 #endif