Jack2 1.9.6

JackMessageBuffer.cpp

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