TuttleOFX  1
MemoryCache.cpp
Go to the documentation of this file.
00001 #include "MemoryCache.hpp"
00002 #include <tuttle/host/attribute/Image.hpp> // to know the function getReference()
00003 #include <tuttle/common/utils/global.hpp>
00004 #include <boost/foreach.hpp>
00005 
00006 #include <functional>
00007 
00008 namespace tuttle {
00009 namespace host {
00010 namespace memory {
00011 
00012 MemoryCache& MemoryCache::operator=( const MemoryCache& cache )
00013 {
00014         if( &cache == this )
00015                 return *this;
00016         boost::mutex::scoped_lock lockerMap1( cache._mutexMap );
00017         boost::mutex::scoped_lock lockerMap2( _mutexMap );
00018         _map = cache._map;
00019         return *this;
00020 }
00021 
00022 void MemoryCache::put( const std::string& identifier, const double time, CACHE_ELEMENT pData )
00023 {
00024         boost::mutex::scoped_lock lockerMap( _mutexMap );
00025         _map[Key( identifier, time )] = pData;
00026 }
00027 
00028 CACHE_ELEMENT MemoryCache::get( const std::string& identifier, const double time ) const
00029 {
00030         boost::mutex::scoped_lock lockerMap( _mutexMap );
00031         MAP::const_iterator itr = _map.find( Key( identifier, time ) );
00032 
00033         if( itr == _map.end() )
00034                 return CACHE_ELEMENT();
00035         return itr->second;
00036 }
00037 
00038 CACHE_ELEMENT MemoryCache::get( const std::size_t& i ) const
00039 {
00040         boost::mutex::scoped_lock lockerMap( _mutexMap );
00041         MAP::const_iterator itr = _map.begin();
00042         for( unsigned int j = 0; j < i && itr != _map.end(); ++j )
00043                 ++itr;
00044 
00045         if( itr == _map.end() )
00046                 return CACHE_ELEMENT();
00047         return itr->second;
00048 }
00049 
00050 std::size_t MemoryCache::size() const
00051 {
00052         boost::mutex::scoped_lock lockerMap( _mutexMap );
00053         return _map.size();
00054 }
00055 
00056 bool MemoryCache::empty() const
00057 {
00058         boost::mutex::scoped_lock lockerMap( _mutexMap );
00059         return _map.empty();
00060 }
00061 
00062 bool MemoryCache::inCache( const CACHE_ELEMENT& pData ) const
00063 {
00064         boost::mutex::scoped_lock lockerMap( _mutexMap );
00065         return getIteratorForValue( pData ) != _map.end();
00066 }
00067 
00068 namespace {
00069 
00070 const std::string EMPTY_STRING = "";
00071 
00072 template<typename T>
00073 struct FindValuePredicate : public std::unary_function<typename T::value_type, bool>
00074 {
00075         const typename T::mapped_type & _value;
00076         FindValuePredicate( const typename T::mapped_type& value ) : _value( value ) {}
00077 
00078         bool operator()( const typename T::value_type& pair )
00079         {
00080                 return pair.second == _value;
00081         }
00082 
00083 };
00084 
00085 }
00086 
00087 MemoryCache::MAP::const_iterator MemoryCache::getIteratorForValue( const CACHE_ELEMENT& pData ) const
00088 {
00089         return std::find_if( _map.begin(), _map.end(), FindValuePredicate<MAP>( pData ) );
00090 }
00091 
00092 MemoryCache::MAP::iterator MemoryCache::getIteratorForValue( const CACHE_ELEMENT& pData )
00093 {
00094         return std::find_if( _map.begin(), _map.end(), FindValuePredicate<MAP>( pData ) );
00095 }
00096 
00097 double MemoryCache::getTime( const CACHE_ELEMENT& pData ) const
00098 {
00099         boost::mutex::scoped_lock lockerMap( _mutexMap );
00100         MAP::const_iterator itr = getIteratorForValue( pData );
00101 
00102         if( itr == _map.end() )
00103                 return 0;
00104         return itr->first._time;
00105 }
00106 
00107 const std::string& MemoryCache::getPluginName( const CACHE_ELEMENT& pData ) const
00108 {
00109         boost::mutex::scoped_lock lockerMap( _mutexMap );
00110         MAP::const_iterator itr = getIteratorForValue( pData );
00111 
00112         if( itr == _map.end() )
00113                 return EMPTY_STRING;
00114         return itr->first._identifier;
00115 }
00116 
00117 bool MemoryCache::remove( const CACHE_ELEMENT& pData )
00118 {
00119         boost::mutex::scoped_lock lockerMap( _mutexMap );
00120         const MAP::iterator itr = getIteratorForValue( pData );
00121 
00122         if( itr == _map.end() )
00123                 return false;
00124         _map.erase( itr );
00125         return true;
00126 }
00127 
00128 void MemoryCache::clearUnused()
00129 {
00130         boost::mutex::scoped_lock lockerMap( _mutexMap );
00131         for( MAP::iterator it = _map.begin(); it != _map.end(); )
00132         {
00133                 if( it->second->getReferenceCount( ofx::imageEffect::OfxhImage::eReferenceOwnerHost ) <= 1 )
00134                 {
00135                         _map.erase( it++ ); // post-increment here, increments 'it' and returns a copy of the original 'it' to be used by erase()
00136                 }
00137                 else
00138                 {
00139                         ++it;
00140                 }
00141         }
00142 }
00143 
00144 void MemoryCache::clearAll()
00145 {
00146         TUTTLE_LOG_DEBUG( TUTTLE_TRACE, " - MEMORYCACHE::CLEARALL - " );
00147         boost::mutex::scoped_lock lockerMap( _mutexMap );
00148         _map.clear();
00149 }
00150 
00151 std::ostream& operator<<( std::ostream& os, const MemoryCache& v )
00152 {
00153         os << "size:" << v.size() << std::endl;
00154         BOOST_FOREACH( const MemoryCache::MAP::value_type& i, v._map )
00155         {
00156                 os << i.first
00157                         << " id:" << i.second->getId()
00158                         << " ref host:" << i.second->getReferenceCount( ofx::imageEffect::OfxhImage::eReferenceOwnerHost )
00159                         << " ref plugins:" << i.second->getReferenceCount( ofx::imageEffect::OfxhImage::eReferenceOwnerPlugin ) << std::endl;
00160         }
00161         return os;
00162 }
00163 
00164 }
00165 }
00166 }