00001 /* 00002 * Copyright (C) 2006, Jose Renato Santos. 00003 * 00004 * This file may be distributed under the terms of the Q Public License 00005 * as defined by Trolltech AS of Norway and appearing in the file 00006 * LICENSE.QPL included in the packaging of this file. 00007 * 00008 * THIS FILE IS PROVIDED AS IS WITH NO WARRANTY OF ANY KIND, INCLUDING 00009 * THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR 00010 * PURPOSE. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, 00011 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING 00012 * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, 00013 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION 00014 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 00015 * 00016 */ 00017 00018 /////////////////////////////////////////////////////////////////////////////// 00019 // FifoQueue.cpp: implementation of the CFifoQueue class. 00020 /////////////////////////////////////////////////////////////////////////////// 00021 00022 #include "FifoQueue.h" 00023 00024 ////////////////////////////////////////////////////////////////////// 00025 00026 #ifdef __Rio_Win 00027 // Windows implementation 00028 // This was included to use in Visual Studio 6.0 00029 #include "stdafx.h" 00030 #else 00031 // Linux implementation 00032 #endif 00033 00034 /* ----------------------------- */ 00035 00036 #include "RioError.h" 00037 00038 #include <string.h> 00039 #include <errno.h> 00040 00041 ////////////////////////////////////////////////////////////////////// 00042 00043 ////////////////////////////////////////////////////////////////////// 00044 // Construction/Destruction 00045 ////////////////////////////////////////////////////////////////////// 00046 00047 CFifoQueue::CFifoQueue() 00048 { 00049 m_Size = 0; 00050 m_n =0 ; 00051 m_First = 0; 00052 m_End = 0; 00053 m_Request = 0; 00054 m_SemaphoreElement = 0; 00055 m_SemaphorePosition = 0; 00056 m_log = 0; 00057 } 00058 00059 CFifoQueue::~CFifoQueue() 00060 { 00061 if(m_Request != 0) 00062 { 00063 delete[] m_Request; 00064 m_Request = 0; 00065 } 00066 if(m_SemaphorePosition != 0) 00067 { 00068 delete m_SemaphorePosition; 00069 m_SemaphorePosition = 0; 00070 } 00071 } 00072 00073 HRESULT CFifoQueue::Initialize (int Size, 00074 CSemaphore *SemaphoreElement, 00075 ofstream *LogStream) 00076 { 00077 m_log = LogStream; 00078 00079 // check if mutex was successfully created 00080 if(!m_Mutex.IsOpen()){ 00081 *m_log << "CFifoQueue::Initialize(): Failed to create mutex" << endl; 00082 *m_log << " ERROR: " << strerror(errno) << endl; 00083 return ERROR_NETWORKMANAGER + ERROR_CREATE_MUTEX; 00084 } 00085 00086 // Allocate and create position semaphore 00087 m_SemaphorePosition = new CSemaphore (Size,Size); 00088 if(m_SemaphorePosition == 0) 00089 { 00090 *m_log << "CFifoQueue::Initialize(): Failed to allocate memory" << endl; 00091 return ERROR_NETWORKMANAGER + ERROR_MEMORY; 00092 } 00093 00094 m_SemaphoreElement = SemaphoreElement; 00095 00096 // Check if position semaphore was allocated successfully 00097 if(!m_SemaphorePosition->IsOpen()) 00098 { 00099 *m_log << "CFifoQueue::Initialize(): Failed to create semaphore" << endl; 00100 *m_log << " ERROR: " << strerror(errno) << endl; 00101 delete m_SemaphorePosition; 00102 m_SemaphorePosition = 0; 00103 return ERROR_NETWORKMANAGER + ERROR_CREATE_SEMAPHORE; 00104 } 00105 00106 // Allocate space for queued requests 00107 m_Request = new QueueElement[Size]; 00108 if(m_Request == 0) 00109 { 00110 *m_log << "CFifoQueue::Initialize(): Failed to allocate memory" << endl; 00111 delete m_SemaphorePosition; 00112 m_SemaphorePosition = 0; 00113 return ERROR_NETWORKMANAGER + ERROR_MEMORY; 00114 } 00115 00116 m_Size = Size; 00117 m_n = m_First = m_End = 0; 00118 00119 return S_OK; 00120 00121 } 00122 00123 void CFifoQueue::Put(QueueElement *Request) 00124 { 00125 // Wait for avaiable position on queue 00126 m_SemaphorePosition->P(); 00127 00128 // Get exclusive access to queue variables 00129 m_Mutex.Wait(); 00130 00131 // Put Request at end of queue 00132 m_Request[m_End] = *Request; 00133 m_End++; 00134 m_n++; 00135 if(m_End >= m_Size) 00136 m_End = 0; 00137 00138 // Release use of queue 00139 m_Mutex.Release(); 00140 00141 // Signal one more element available on queue 00142 m_SemaphoreElement->V(); 00143 00144 } 00145 00146 bool CFifoQueue::Get(QueueElement *Request) 00147 { 00148 00149 // Get exclusive access to queue variables 00150 m_Mutex.Wait(); 00151 00152 if(m_n == 0) 00153 { 00154 m_Mutex.Release(); 00155 return false; 00156 } 00157 00158 *Request = m_Request[m_First]; 00159 m_n--; 00160 m_First++; 00161 if(m_First >= m_Size) 00162 m_First = 0; 00163 00164 // Release use of queue 00165 m_Mutex.Release(); 00166 00167 // Signal one more position available on queue 00168 m_SemaphorePosition->V(); 00169 00170 return true; 00171 00172 } 00173 00174 int CFifoQueue::nRequests() 00175 { 00176 m_Mutex.Wait(); 00177 int n = m_n; 00178 m_Mutex.Release(); 00179 return n; 00180 }