DebugRouter.h

Go to the documentation of this file.
00001 
00002 //Luke Lenhart, 2007
00003 //See /docs/License.txt for details on how this code may be used.
00004 /*
00005 This system allows you to hook up chains of outputs systems.
00006 The actual output occurs in a different thread, minimizing overhead on the caller thread.
00007 
00008 For example:
00009 One might create a DebugRouter for errors and a DebugRouter for informational messages.
00010 The errors router could output everything to an error file.
00011 The informational router could output everything to an informational file.
00012 They both could also output to a third router instance, which in turns outputs everything to a debug window.
00013 [Output Error File]<-----------------+--------[error Input]<-----------
00014                                     /                                  \
00015 [Output Debug Window]<-------[merged Input]                        [Program]
00016                                     \                                  /
00017 [Output Info File]<------------------+--------[info Input]<------------
00018 
00019 */
00020 
00021 #pragma once
00022 
00023 #include "Locks.h"
00024 #include "Vary.h"
00025 #include "Thread.h"
00026 #include "File.h" //for Filename
00027 #include <string>
00028 #include <list>
00029 #include "Setup.h"
00030 
00031 namespace MPMA
00032 {
00033     // -- Router system
00034 
00036     class RouterOutput
00037     {
00038     public:
00039         inline RouterOutput(): bufferedDataProcessing(true) {}
00040         virtual ~RouterOutput();
00041 
00043         virtual void Output(const uint8 *data, uint dataLen);
00044 
00046         inline bool IsBufferProcessing() {return bufferedDataProcessing;}
00047 
00048         //Flushes all output from all sources that connect to this output.
00049         //It is recemmonded that your derived classes's destructor call this first thing, to ensure that all buffered output makes it through.
00050         virtual void FlushInputSources();
00051 
00052     protected:
00053         //your derived class can choose to change this from the default (true) during construction to disable buffered output
00054         bool bufferedDataProcessing;
00055 
00056     private:
00057         SpinLock feedLock;
00058         std::list<class RouterInput*> reportFeeds;
00059         void DetachFeed(RouterInput *feed);
00060 
00061         friend class RouterInput;
00062 
00063         //you cannot duplicate this
00064         RouterOutput(const RouterOutput&);
00065         const RouterOutput& operator=(const RouterOutput&);
00066     };
00067 
00068 #ifdef DEBUGROUTER_ENABLED
00070     class RouterInput: public RouterOutput
00071     {
00072     public:
00073         //
00074         RouterInput();
00075         ~RouterInput();
00076 
00078         inline RouterInput& operator<<(const Vary &v) {const std::string &s=v; Output((const uint8*)&s[0], s.size()); return *this;}
00079         inline friend RouterInput& operator<<(RouterInput &db, RouterInput &db2) {return db;}
00080 
00082         void Output(const uint8 *data, uint dataLen);
00083         inline void Output(const Vary &v) {*this<<v;}
00084 
00086         void AddOutputMethod(RouterOutput *outputter);
00087 
00089         void RemoveOutputMethod(RouterOutput *outputter, bool flushOutputFirst=true, bool removeChildLink=true);
00090 
00091     private:
00092         bool IsBufferProcessing();
00093         void FlushOutput();
00094         virtual void FlushInputSources();
00095 
00096         std::list<RouterOutput*> outputs;
00097         MutexLock outputLock;
00098 
00099         //data marshelling
00100         Thread *dataMover;
00101         static void ThreadProc(Thread &thread, ThreadParam param);
00102         volatile bool destructing;
00103         BlockingObject workerWaiter;
00104         BlockingObject routerWaiter;
00105         volatile uint8 *buffer;
00106         volatile uint bufferLen;
00107         SpinLock dataLock;
00108         MutexLock addDataLock;
00109         SpinLock threadWorkingLock;
00110 
00111         uint numNonbufferedOutputs;
00112         bool alive;
00113 
00114         friend class RouterOutput;
00115 
00116         //you cannot duplicate this
00117         RouterInput(const RouterInput&);
00118         const RouterInput& operator=(const RouterInput&);
00119     };
00120 #else //dummy do-nothing implementation - when reporder is disabled
00121     class RouterInput: public RouterOutput
00122     {
00123     public:
00124         inline RouterInput& operator<<(const Vary &v) {return *this;}
00125         inline friend RouterInput& operator<<(RouterInput &db, RouterInput &db2) {return db;}
00126 
00127         inline void Output(const uint8 *data, uint dataLen) {}
00128         inline void Output(const Vary &v) {}
00129         inline void AddOutputMethod(RouterOutput *outputter) {}
00130         inline void RemoveOutputMethod(RouterOutput *outputter, bool flushOutputFirst=true, bool removeChildLink=true) {}
00131 
00132         friend class RouterOutput;
00133     };
00134 #endif
00135 
00136 
00137     // -- Some useful output implementations
00138 
00140     class RouterOutputFile: public RouterOutput
00141     {
00142     public:
00144         RouterOutputFile(const Filename &fileName, bool textMode=true);
00145         ~RouterOutputFile();
00146 
00147         void Output(const uint8 *data, uint dataLen);
00148     private:
00149 #ifdef DEBUGROUTER_ENABLED
00150         FILE *f;
00151         MutexLock lock;
00152 #endif
00153 
00154         //you cannot duplicate this
00155         RouterOutputFile(const RouterOutputFile&);
00156         const RouterOutputFile& operator=(const RouterOutputFile&);
00157     };
00158 
00160     class RouterOutputStdout: public RouterOutput
00161     {
00162     public:
00163         ~RouterOutputStdout();
00164         void Output(const uint8 *data, uint dataLen);
00165     };
00166 
00167 
00168     // -- framework error reporter
00169     //After you initialize the framework, you should add a destination to "MPMA::ErrorReport()".
00170 
00171     //Use "MPMA::ErrorReport()" for anything that happens that should never happen within the framework.
00172     extern RouterInput *errorReportPointer;
00173 
00175     inline RouterInput& ErrorReport()
00176     {
00177 #ifdef _DEBUG
00178         if (errorReportPointer==0) throw "Error RouterInput pointer is null.  Maybe you need to Initialize the framework before using it.";
00179 #endif
00180         return *errorReportPointer;
00181     }
00182 
00183 
00184 } //namespace MPMA

Generated on Wed Feb 13 20:57:04 2008 for MPMA Framework by  doxygen 1.5.4