00001 /* 00002 * Copyright (C) 2009, Edmundo Albuquerque de Souza e Silva. 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 * Thanks: Jose Renato Santos 00017 * 00018 */ 00019 00020 /////////////////////////////////////////////////////////////////////////////// 00021 // RioQueue.cpp -- singlely linked fifo queue primitives for pthreads 00022 // Get or Put can be called from any thread. 00023 // RioQueueEle is just a single forward link, 00024 // any real use would have more structure after this... 00025 // (Could write a cover class for type safety for a specific element 00026 // (type... 00027 /////////////////////////////////////////////////////////////////////////////// 00028 00029 #ifdef WINDOWS 00030 // Windows implementation 00031 // This was included to use in Visual Studio 6.0 00032 #include "stdafx.h" 00033 #else 00034 // Linux implementation 00035 #endif 00036 00037 #include "RioQueue.h" 00038 00039 #include <stddef.h> // for offsetof macro 00040 00041 #include "td4list.h" 00042 00043 #include <pthread.h> 00044 #include <iostream> 00045 00046 ///////////////////////////////////////////////////////////////////////////// 00047 RioQueue::RioQueue() 00048 { 00049 pthread_mutex_init( &m_mutex, NULL ); 00050 pthread_cond_init( &m_cond, NULL ); 00051 m_waitflag = 0; 00052 m_waitcnt = 0; 00053 m_getcnt = 0; 00054 m_top = NULL; 00055 m_bot = VIRTORG( m_top, RioQueueEle, linkf ); 00056 m_sync = NULL; 00057 } 00058 ///////////////////////////////////////////////////////////////////////////// 00059 RioQueue::~RioQueue() 00060 { 00061 pthread_mutex_destroy( &m_mutex ); 00062 pthread_cond_destroy( &m_cond ); 00063 } 00064 ///////////////////////////////////////////////////////////////////////////// 00065 // Put -- add element to queue 00066 void RioQueue::Put( RioQueueEle *ep ) 00067 { 00068 pthread_mutex_lock( &m_mutex ); 00069 00070 ep->linkf = 0; 00071 m_bot->linkf = ep; 00072 m_bot = ep; 00073 00074 if( m_waitflag ) 00075 { 00076 pthread_cond_broadcast( &m_cond ); 00077 m_waitflag = 0; 00078 } 00079 00080 pthread_mutex_unlock( &m_mutex ); 00081 } 00082 ///////////////////////////////////////////////////////////////////////////// 00083 // Get -- get element from queue (wait until one is available if needed) 00084 RioQueueEle *RioQueue::Get() 00085 { 00086 RioQueueEle *ep; 00087 00088 pthread_mutex_lock( &m_mutex ); 00089 00090 m_getcnt++; 00091 00092 if( m_top == 0 ) 00093 m_waitcnt++; 00094 00095 while( m_top == 0 ) 00096 { 00097 m_waitflag = 1; 00098 pthread_cond_wait( &m_cond, &m_mutex ); 00099 } 00100 00101 m_waitflag = 0; 00102 ep = m_top; 00103 m_top = ep->linkf; 00104 00105 if( m_top == 0 ) 00106 m_bot = VIRTORG( m_top, RioQueueEle, linkf ); 00107 00108 pthread_mutex_unlock( &m_mutex ); 00109 00110 return ep; 00111 } 00112 00113 ///////////////////////////////////////////////////////////////////////////// 00114 // Remove -- remove element from queue 00115 RioQueueEle *RioQueue::Remove() 00116 { 00117 RioQueueEle *ep; 00118 00119 pthread_mutex_lock( &m_mutex ); 00120 00121 if( m_top == 0 ) 00122 ep = NULL; 00123 else 00124 { 00125 ep = m_top; 00126 m_top = ep->linkf; 00127 00128 if( m_top == 0 ) 00129 m_bot = VIRTORG( m_top, RioQueueEle, linkf ); 00130 00131 } 00132 00133 pthread_mutex_unlock( &m_mutex ); 00134 00135 return ep; 00136 }