00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "JackMessageBuffer.h"
00023 #include "JackGlobals.h"
00024 #include "JackError.h"
00025 #include "JackTime.h"
00026
00027 namespace Jack
00028 {
00029
00030 JackMessageBuffer* JackMessageBuffer::fInstance = NULL;
00031
00032 JackMessageBuffer::JackMessageBuffer()
00033 :fInit(NULL),
00034 fInitArg(NULL),
00035 fThread(this),
00036 fGuard(),
00037 fInBuffer(0),
00038 fOutBuffer(0),
00039 fOverruns(0),
00040 fRunning(false)
00041 {}
00042
00043 JackMessageBuffer::~JackMessageBuffer()
00044 {}
00045
00046 bool JackMessageBuffer::Start()
00047 {
00048
00049 fRunning = true;
00050 if (fThread.StartSync() == 0) {
00051 return true;
00052 } else {
00053 fRunning = false;
00054 return false;
00055 }
00056 }
00057
00058 bool JackMessageBuffer::Stop()
00059 {
00060 if (fOverruns > 0) {
00061 jack_error("WARNING: %d message buffer overruns!", fOverruns);
00062 } else {
00063 jack_log("no message buffer overruns");
00064 }
00065
00066 if (fGuard.Lock()) {
00067 fRunning = false;
00068 fGuard.Signal();
00069 fGuard.Unlock();
00070 fThread.Stop();
00071 } else {
00072 fThread.Kill();
00073 }
00074
00075 Flush();
00076 return true;
00077 }
00078
00079 void JackMessageBuffer::Flush()
00080 {
00081 while (fOutBuffer != fInBuffer) {
00082 jack_log_function(fBuffers[fOutBuffer].level, fBuffers[fOutBuffer].message);
00083 fOutBuffer = MB_NEXT(fOutBuffer);
00084 }
00085 }
00086
00087 void JackMessageBuffer::AddMessage(int level, const char *message)
00088 {
00089 if (fGuard.Trylock()) {
00090 fBuffers[fInBuffer].level = level;
00091 strncpy(fBuffers[fInBuffer].message, message, MB_BUFFERSIZE);
00092 fInBuffer = MB_NEXT(fInBuffer);
00093 fGuard.Signal();
00094 fGuard.Unlock();
00095 } else {
00096 INC_ATOMIC(&fOverruns);
00097 }
00098 }
00099
00100 bool JackMessageBuffer::Execute()
00101 {
00102 if (fGuard.Lock()) {
00103 while (fRunning) {
00104 fGuard.Wait();
00105
00106
00107
00108 if (fInit) {
00109 fInit(fInitArg);
00110 fInit = NULL;
00111
00112 fGuard.Signal();
00113 }
00114
00115
00116 fGuard.Unlock();
00117 Flush();
00118 fGuard.Lock();
00119 }
00120 fGuard.Unlock();
00121 } else {
00122 jack_error("JackMessageBuffer::Execute lock cannot be taken");
00123 }
00124
00125 return false;
00126 }
00127
00128 bool JackMessageBuffer::Create()
00129 {
00130 if (fInstance == NULL) {
00131 fInstance = new JackMessageBuffer();
00132 if (!fInstance->Start()) {
00133 jack_error("JackMessageBuffer::Create cannot start thread");
00134 delete fInstance;
00135 fInstance = NULL;
00136 return false;
00137 }
00138 }
00139
00140 return true;
00141 }
00142
00143 bool JackMessageBuffer::Destroy()
00144 {
00145 if (fInstance != NULL) {
00146 fInstance->Stop();
00147 delete fInstance;
00148 fInstance = NULL;
00149 return true;
00150 } else {
00151 return false;
00152 }
00153 }
00154
00155 void JackMessageBufferAdd(int level, const char *message)
00156 {
00157 if (Jack::JackMessageBuffer::fInstance == NULL) {
00158
00159 jack_log_function(LOG_LEVEL_ERROR, "messagebuffer not initialized, skip message");
00160 } else {
00161 Jack::JackMessageBuffer::fInstance->AddMessage(level, message);
00162 }
00163 }
00164
00165 int JackMessageBuffer::SetInitCallback(JackThreadInitCallback callback, void *arg)
00166 {
00167 if (fInstance && callback && fRunning && fGuard.Lock()) {
00168
00169 fInitArg = arg;
00170 fInit = callback;
00171
00172 #ifndef WIN32
00173
00174 fGuard.Signal();
00175
00176 fGuard.Wait();
00177
00178 fGuard.Unlock();
00179 #else
00180
00181
00182
00183
00184
00185 fGuard.Unlock();
00186 int count = 0;
00187 while (fInit && ++count < 1000) {
00188
00189 fGuard.Signal();
00190 JackSleep(1000);
00191 }
00192 if (count == 1000) goto error;
00193 #endif
00194
00195 return 0;
00196 }
00197
00198 error:
00199 jack_error("JackMessageBuffer::SetInitCallback : callback cannot be executed");
00200 return -1;
00201 }
00202
00203 };
00204