ITAUPFilterPool.cpp 6.44 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
#include <ITAUPFilterPool.h>
#include <ITAUPFilter.h>

#include <ITAFunctors.h>

#include <algorithm>
#include <cassert>
#include <cstdio>


// Debug-Meldung ausgeben
#define VERBOSE 0

ITAUPFilterPool::ITAUPFilterPool( const int iBlocklength, const int iMaxFilterLength, const int iInitialSize )
	: m_iBlocklength( iBlocklength )
	, m_iMaxFilterLength( iMaxFilterLength )
{
	for( int i = 0; i < iInitialSize; i++ )
	{
		ITAUPFilter* pFilter = new ITAUPFilter( m_iBlocklength, m_iMaxFilterLength );
		pFilter->m_pParent = this;
		m_lpFreeFilters.push_back( pFilter );
	}
}

ITAUPFilterPool::~ITAUPFilterPool()
{
	m_csFilters.enter();

	std::for_each( m_lpFreeFilters.begin(), m_lpFreeFilters.end(), deleteFunctor<ITAUPFilter> );
	std::for_each( m_lpUsedFilters.begin(), m_lpUsedFilters.end(), deleteFunctor<ITAUPFilter> );
	std::for_each( m_lpAutoFilters.begin(), m_lpAutoFilters.end(), deleteFunctor<ITAUPFilter> );

	m_csFilters.leave();
}

37
int ITAUPFilterPool::GetBlocklength() const
38 39 40 41
{
	return m_iBlocklength;
}

42
int ITAUPFilterPool::GetMaxFilterlength() const
43 44 45 46
{
	return m_iMaxFilterLength;
}

47
int ITAUPFilterPool::GetNumFreeFilters() const
48 49 50 51 52 53 54
{
	m_csFilters.enter();
	int iResult = ( int ) m_lpFreeFilters.size();
	m_csFilters.leave();
	return iResult;
}

55
int ITAUPFilterPool::GetNumUsedFilters() const
56 57 58 59 60 61 62
{
	m_csFilters.enter();
	int iResult = ( int ) m_lpUsedFilters.size() + ( int ) m_lpAutoFilters.size();
	m_csFilters.leave();
	return iResult;
}

63
int ITAUPFilterPool::GetNumTotalFilters() const
64 65 66 67 68 69 70
{
	m_csFilters.enter();
	int iResult = ( int ) m_lpFreeFilters.size() + ( int ) m_lpUsedFilters.size() + ( int ) m_lpAutoFilters.size();
	m_csFilters.leave();
	return iResult;
}

71
ITAUPFilter* ITAUPFilterPool::RequestFilter()
72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
{
	m_csFilters.enter();

	ITAUPFilter* pFilter = nullptr;

	if( m_lpFreeFilters.empty() )
	{
		// Fall: Keine Filter in der Frei-Liste -> Zunchst schauen ob freie Filter in der Auto-Liste
		if( !m_lpAutoFilters.empty() )
		{
			for( std::list<ITAUPFilter*>::iterator it = m_lpAutoFilters.begin(); it != m_lpAutoFilters.end(); ++it )
			{
				/*
				 *  Wichtig: Wenn der Filter bereits in der Auto-Liste ist,
				 *           hat der Benutzer fr dieses Filter release() aufgerufen.
				 *           Er braucht den Filter also nicht mehr und darf den
				 *           ihm zuvor genannten Zeiger nicht mehr weiterbenutzen.
				 *           Deshalb kann auch den Filter auch nicht zwischenzeitlich
				 *           in einen anderen Falter einsetzen.
				 *
				 *           Fazit: Es ist sicher hier nur-lesend zu testen!
				 */

				assert( ( *it ) != 0 );

97
				if( !( *it )->IsInUse() )
98 99 100 101 102 103 104 105
				{
					pFilter = ( *it );

					// Filter wieder vergeben
					m_lpAutoFilters.erase( it );
#if VERBOSE==1
					{
						DEBUG_PRINTF("[DSMBCFilterPool] Reusing auto filter 0x%08Xh [Used %d, Auto %d, Free %d, Total %d]\n",
106
							pFilter, m_lpUsedFilters.size(), m_lpAutoFilters.size(), m_lpFreeFilters.size(), GetNumTotalFilters());
107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
					}
#endif
					break;
				}
				//				} else {
				//					// Nur Meldung machen
				//					DSMBCFilter::State::StateStruct ss;
				//					ss.iPrepRefCount = 0;
				//					ss.iUseRefCount = 0;
				//					if (pFilter) atomic_read32( &pFilter->m_oState.m_oState, &ss );
				//#if VERBOSE==1
				//					DEBUG_PRINTF("[DSMBCFilterPool] Cannot reusing auto filter 0x%08Xh (preps=%d, uses=%d) [Used %d, Auto %d, Free %d, Total %d]\n",
				//						pFilter, ss.iPrepRefCount, ss.iUseRefCount, m_lpUsedFilters.size(), m_lpAutoFilters.size(), m_lpFreeFilters.size(), getNumTotalFilters());
				//#endif
				//				}
			}
		}

		if( pFilter == nullptr )
		{
			// Fall: Auch kein freies Filter in der Auto-Liste -> Neues Filter erzeugen
			pFilter = new ITAUPFilter( m_iBlocklength, m_iMaxFilterLength );
			pFilter->m_pParent = this;

#if VERBOSE==1
			DEBUG_PRINTF("[DSMBCFilterPool] Created new filter 0x%08Xh [Used %d, Auto %d, Free %d, Total %d]\n",
133
				pFilter, m_lpUsedFilters.size(), m_lpAutoFilters.size(), m_lpFreeFilters.size(), GetNumTotalFilters());
134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164
#endif
		}

		m_lpUsedFilters.push_back( pFilter );

	}
	else
	{
		// Fall: Freie Filter verfgbar
		pFilter = m_lpFreeFilters.back();
		m_lpFreeFilters.pop_back();
		m_lpUsedFilters.push_back( pFilter );

		//#if VERBOSE==1
		//		{
		//			// Nur Meldung machen
		//			DSMBCFilter::State::StateStruct ss;
		//			ss.iPrepRefCount = 0;
		//			ss.iUseRefCount = 0;
		//			if (pFilter) atomic_read32( &pFilter->m_oState.m_oState, &ss );
		//		DEBUG_PRINTF("[DSMBCFilterPool] Freed filter 0x%08Xh [Used %d, Auto %d, Free %d, Total %d]\n",
		//			   pFilter, m_lpUsedFilters.size(), m_lpAutoFilters.size(), m_lpFreeFilters.size(), getNumTotalFilters());
		//		}
		//#endif
	}

	m_csFilters.leave();


#if VERBOSE==1
	DEBUG_PRINTF("[DSMBCFilterPool] Request returns filter 0x%08Xh [Used %d, Auto %d, Free %d, Total %d]\n",
165
		pFilter, m_lpUsedFilters.size(), m_lpAutoFilters.size(), m_lpFreeFilters.size(), GetNumTotalFilters());
166 167 168 169 170
#endif

	return pFilter;
}

171
void ITAUPFilterPool::ReleaseFilter( ITAUPFilter* pFilter )
172 173 174 175 176 177 178 179 180 181 182
{
	m_csFilters.enter();

	// Nonsens einfach ignoieren
	if( !pFilter ) {
		m_csFilters.leave();
		return;
	}

#if VERBOSE==1
	DEBUG_PRINTF("[DSMBCFilterPool] Release filter 0x%08Xh [Used %d, Auto %d, Free %d, Total %d]\n",
183
		pFilter, m_lpUsedFilters.size(), m_lpAutoFilters.size(), m_lpFreeFilters.size(), GetNumTotalFilters());
184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202
#endif

	// Zunchst die eigene Zust?ndigkeit sicherstellen
	std::list<ITAUPFilter*>::iterator it = std::find( m_lpUsedFilters.begin(), m_lpUsedFilters.end(), pFilter );
	if( it == m_lpUsedFilters.end() )
	{
		// Filter garnicht aus diesem Pool. Ignorieren ...
		m_csFilters.leave();
		return;
	}

	/*
	// Schneller und einfacher Test auf Zustndigkeit
	if (pFilter->m_pParent != this) {
	m_csFilters.leave();
	return;
	}
	*/

203
	if( pFilter->IsInUse() )
204 205 206 207 208 209 210 211
	{
		// Ist der Filter noch in Faltern in Benutzung -> Zur Freigabe vormerken (Auto-Liste)
		m_lpUsedFilters.erase( it );
		m_lpAutoFilters.push_back( pFilter );
		m_csFilters.leave();

#if VERBOSE==1
		DEBUG_PRINTF("[DSMBCFilterPool] Auto-release filter 0x%08Xh [Used %d, Auto %d, Free %d, Total %d]\n",
212
			pFilter, m_lpUsedFilters.size(), m_lpAutoFilters.size(), m_lpFreeFilters.size(), GetNumTotalFilters());
213 214 215 216 217 218 219 220 221 222
#endif
		return;
	}

	// Filter wieder in die Frei-Liste
	m_lpUsedFilters.erase( it );
	m_lpFreeFilters.push_back( pFilter );

#if VERBOSE==1
	DEBUG_PRINTF("[DSMBCFilterPool] Instant-release filter 0x%08Xh [Used %d, Auto %d, Free %d, Total %d]\n",
223
		pFilter, m_lpUsedFilters.size(), m_lpAutoFilters.size(), m_lpFreeFilters.size(), GetNumTotalFilters());
224 225 226 227
#endif

	m_csFilters.leave();
}