MPMA Framework 0.4
|
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