MPMA Framework 0.4
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 normally occurs in a different thread, minimizing overhead on the caller thread.
00007 If used before or after the framework is inited, all output is syncronous.
00008 
00009 For example:
00010 One might create a DebugRouter for errors and a DebugRouter for informational messages.
00011 The errors router could output everything to an error file.
00012 The informational router could output everything to an informational file.
00013 They both could also output to a third router instance, which in turns outputs everything to a debug window.
00014 [Output Error File]<-----------------+--------[error Input]<-----------
00015                                     /                                  \
00016 [Output Debug Window]<-------[merged Input]                        [Program]
00017                                     \                                  /
00018 [Output Info File]<------------------+--------[info Input]<------------
00019 
00020 */
00021 
00022 #pragma once
00023 
00024 #include "Locks.h"
00025 #include "Vary.h"
00026 #include "Thread.h"
00027 #include "File.h" //for Filename
00028 #include <string>
00029 #include <list>
00030 #include "Setup.h"
00031 
00032 namespace MPMA
00033 {
00034     namespace MPMAInternal
00035     {
00036         class AutoInitReports;
00037     }
00038 
00039     // -- Router system
00040 
00042     class RouterOutput
00043     {
00044     public:
00045         inline RouterOutput(): bufferedDataProcessing(true) {}
00046         virtual ~RouterOutput();
00047 
00049         virtual void Output(const uint8 *data, nuint dataLen);
00050 
00052         inline bool IsBufferProcessing() {return bufferedDataProcessing;}
00053 
00054         //Flushes all output from all sources that connect to this output.
00055         //It is recemmonded that your derived classes's destructor call this first thing, to ensure that all buffered output makes it through.
00056         virtual void FlushInputSources();
00057 
00058     protected:
00059         //your derived class can choose to change this from the default (true) during construction to disable buffered output
00060         bool bufferedDataProcessing;
00061 
00062     private:
00063         SpinLock feedLock;
00064         std::list<class RouterInput*> reportFeeds;
00065         void DetachFeed(RouterInput *feed);
00066 
00067         friend class RouterInput;
00068 
00069         //you cannot duplicate this
00070         RouterOutput(const RouterOutput&);
00071         const RouterOutput& operator=(const RouterOutput&);
00072     };
00073 
00074 #ifdef DEBUGROUTER_ENABLED
00075 
00076     class RouterInput: public RouterOutput
00077     {
00078     public:
00079         //
00080         RouterInput();
00081         ~RouterInput();
00082 
00084         inline RouterInput& operator<<(const Vary &v) {const std::string &s=v; Output((const uint8*)&s[0], s.size()); return *this;}
00085         inline friend RouterInput& operator<<(RouterInput &db, RouterInput &db2) {return db;}
00086 
00088         void Output(const uint8 *data, nuint dataLen);
00089         inline void Output(const Vary &v) {*this<<v;}
00090 
00092         void AddOutputMethod(RouterOutput *outputter);
00093 
00095         void RemoveOutputMethod(RouterOutput *outputter, bool flushOutputFirst=true, bool removeChildLink=true);
00096 
00097     private:
00098         bool IsBufferProcessing();
00099         void FlushOutput();
00100         virtual void FlushInputSources();
00101 
00102         std::list<RouterOutput*> outputs;
00103         MutexLock outputLock;
00104 
00105         //data marshelling
00106         Thread *dataMover;
00107         static void ThreadProc(Thread &thread, ThreadParam param);
00108         volatile bool endingThreadedMode;
00109         BlockingObject workerWaiter;
00110         BlockingObject routerWaiter;
00111         volatile uint8 *buffer;
00112         volatile nuint bufferLen;
00113         SpinLock dataLock;
00114         MutexLock addDataLock;
00115         SpinLock threadWorkingLock;
00116 
00117         nuint numNonbufferedOutputs;
00118         bool alive;
00119 
00120         bool isThreadedMode;
00121         void DemoteToUnthreaded();
00122 
00123         friend class RouterOutput;
00124         friend class MPMAInternal::AutoInitReports;
00125 
00126         //you cannot duplicate this
00127         RouterInput(const RouterInput&);
00128         const RouterInput& operator=(const RouterInput&);
00129     };
00130 #else //dummy do-nothing implementation - when reporder is disabled
00131     class RouterInput: public RouterOutput
00132     {
00133     public:
00134         inline RouterInput& operator<<(const Vary &v) {return *this;}
00135         inline friend RouterInput& operator<<(RouterInput &db, RouterInput &db2) {return db;}
00136 
00137         inline void Output(const uint8 *data, nuint dataLen) {}
00138         inline void Output(const Vary &v) {}
00139         inline void AddOutputMethod(RouterOutput *outputter) {}
00140         inline void RemoveOutputMethod(RouterOutput *outputter, bool flushOutputFirst=true, bool removeChildLink=true) {}
00141 
00142         friend class RouterOutput;
00143     };
00144 #endif
00145 
00146 
00147     // -- Some useful output implementations
00148 
00150     class RouterOutputFile: public RouterOutput
00151     {
00152     public:
00154         RouterOutputFile(const Filename &fileName, bool textMode=true);
00155         ~RouterOutputFile();
00156 
00157         void Output(const uint8 *data, nuint dataLen);
00158     private:
00159 #ifdef DEBUGROUTER_ENABLED
00160         FILE *f;
00161         MutexLock lock;
00162 #endif
00163 
00164         //you cannot duplicate this
00165         RouterOutputFile(const RouterOutputFile&);
00166         const RouterOutputFile& operator=(const RouterOutputFile&);
00167     };
00168 
00170     class RouterOutputStdout: public RouterOutput
00171     {
00172     public:
00173         ~RouterOutputStdout();
00174         void Output(const uint8 *data, nuint dataLen);
00175     };
00176 
00177 
00178     // -- framework error reporter
00179     //Use "MPMA::ErrorReport()" for anything that happens that should never happen within the framework.
00180 
00182     RouterInput& ErrorReport();
00183 
00184 
00185 } //namespace MPMA
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends