Jack2 1.9.6
|
00001 /* 00002 * Copyright (C) 2004 Rui Nuno Capela, Steve Harris 00003 * Copyright (C) 2008 Nedko Arnaudov 00004 * Copyright (C) 2008 Grame 00005 * 00006 * This program is free software; you can redistribute it and/or modify 00007 * it under the terms of the GNU Lesser General Public License as published by 00008 * the Free Software Foundation; either version 2.1 of the License, or 00009 * (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU Lesser General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU Lesser General Public License 00017 * along with this program; if not, write to the Free Software 00018 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 00019 * 00020 */ 00021 00022 #include "JackMessageBuffer.h" 00023 #include "JackGlobals.h" 00024 #include "JackError.h" 00025 00026 namespace Jack 00027 { 00028 00029 JackMessageBuffer* JackMessageBuffer::fInstance = NULL; 00030 00031 JackMessageBuffer::JackMessageBuffer() 00032 :fInit(NULL),fInitArg(NULL),fThread(this),fInBuffer(0),fOutBuffer(0),fOverruns(0),fRunning(false) 00033 {} 00034 00035 JackMessageBuffer::~JackMessageBuffer() 00036 {} 00037 00038 void JackMessageBuffer::Start() 00039 { 00040 fRunning = true; 00041 fThread.StartSync(); 00042 } 00043 00044 void JackMessageBuffer::Stop() 00045 { 00046 if (fOverruns > 0) { 00047 jack_error("WARNING: %d message buffer overruns!", fOverruns); 00048 } else { 00049 jack_log("no message buffer overruns"); 00050 } 00051 fGuard.Lock(); 00052 fRunning = false; 00053 fGuard.Signal(); 00054 fGuard.Unlock(); 00055 fThread.Stop(); 00056 Flush(); 00057 } 00058 00059 void JackMessageBuffer::Flush() 00060 { 00061 while (fOutBuffer != fInBuffer) { 00062 jack_log_function(fBuffers[fOutBuffer].level, fBuffers[fOutBuffer].message); 00063 fOutBuffer = MB_NEXT(fOutBuffer); 00064 } 00065 } 00066 00067 void JackMessageBuffer::AddMessage(int level, const char *message) 00068 { 00069 if (fGuard.Trylock()) { 00070 fBuffers[fInBuffer].level = level; 00071 strncpy(fBuffers[fInBuffer].message, message, MB_BUFFERSIZE); 00072 fInBuffer = MB_NEXT(fInBuffer); 00073 fGuard.Signal(); 00074 fGuard.Unlock(); 00075 } else { /* lock collision */ 00076 INC_ATOMIC(&fOverruns); 00077 } 00078 } 00079 00080 bool JackMessageBuffer::Execute() 00081 { 00082 while (fRunning) { 00083 fGuard.Lock(); 00084 fGuard.Wait(); 00085 /* the client asked for all threads to run a thread 00086 initialization callback, which includes us. 00087 */ 00088 if (fInit) { 00089 fInit(fInitArg); 00090 fInit = NULL; 00091 /* and we're done */ 00092 fGuard.Signal(); 00093 } 00094 Flush(); 00095 fGuard.Unlock(); 00096 } 00097 return false; 00098 } 00099 00100 void JackMessageBuffer::Create() 00101 { 00102 if (fInstance == NULL) { 00103 fInstance = new JackMessageBuffer(); 00104 fInstance->Start(); 00105 } 00106 } 00107 00108 void JackMessageBuffer::Destroy() 00109 { 00110 if (fInstance != NULL) { 00111 fInstance->Stop(); 00112 delete fInstance; 00113 fInstance = NULL; 00114 } 00115 } 00116 00117 void JackMessageBufferAdd(int level, const char *message) 00118 { 00119 if (Jack::JackMessageBuffer::fInstance == NULL) { 00120 /* Unable to print message with realtime safety. Complain and print it anyway. */ 00121 jack_log_function(LOG_LEVEL_ERROR, "messagebuffer not initialized, skip message"); 00122 } else { 00123 Jack::JackMessageBuffer::fInstance->AddMessage(level, message); 00124 } 00125 } 00126 00127 void JackMessageBuffer::SetInitCallback(JackThreadInitCallback callback, void *arg) 00128 { 00129 fGuard.Lock(); 00130 /* set up the callback */ 00131 fInitArg = arg; 00132 fInit = callback; 00133 /* wake msg buffer thread */ 00134 fGuard.Signal(); 00135 /* wait for it to be done */ 00136 fGuard.Wait(); 00137 /* and we're done */ 00138 fGuard.Unlock(); 00139 } 00140 00141 00142 }; 00143