All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines
Public Member Functions | Friends
QGpCoreTools::Cache Class Reference

Cache space with "inteligent" swap mechanism. More...

#include <Cache.h>

List of all members.

Public Member Functions

 Cache ()
bool enlarge (CacheItem *item, double finalSize)
void free (CacheItem *item, bool saveTemp=true)
double freeBytes () const
double freeMegaBytes () const
bool makeAvailable (const CacheItem *item)
void setSize (double nMegaBytes)
void setSwapDir (const QDir &d)
 ~Cache ()

Friends

class CacheItem

Detailed Description

Cache space with "inteligent" swap mechanism.

CacheItem can allocate data vectors into a Cache. Cache controls that the total memory does not exceed a maximum number of bytes. If so, already allocated blocks are automatically deallocated if they are not locked.

Contrary to most of the system swaps, this swap mechanism knows what the item usage will be in the next operations avoiding unefficient deallocation of blocks. This "intelligent" deallocation is performed thanks to CacheProcess. They can be created for any process that use a sequence of items. The order of signal usage is stored in advance and it is used to predict the time of next usage. Items that will be used in a far future are preference for deallocation. Items already processed or not included in a CacheProcess have a predicted time set to almost infinite, hence they are deallocated first.


Constructor & Destructor Documentation

Initializes a cache that manages allocation and deallocation of memory.

The two parameters of a cache are its size in byte and the path of a temporary directory used for swapping if the requested memory for data exceed its size.

References TRACE.

             : _mutex(QMutex::Recursive)
{
  TRACE;
  _loadedBytes=0;
  _maxLoadedBytes=0;
}

It does nothing because the removal of data is the responsability of the CacheItem

{}

Member Function Documentation

bool QGpCoreTools::Cache::enlarge ( CacheItem item,
double  finalSize 
)

In all cases the data must be still allocated with its original size. This is not double checked.

References QGpCoreTools::CacheItem::dataSize(), QGpCoreTools::endl(), free(), freeBytes(), QGpCoreTools::AllocatedCacheItem::humanInfo(), QGpCoreTools::CoreApplication::instance(), QGpCoreTools::CoreApplicationPrivate::reportBug(), QGpCoreTools::App::stream(), QGpCoreTools::tr(), TRACE, and QGpCoreTools::Message::Warning.

{
  TRACE;
  // Process low level allocation of data
  double neededSize=finalSize - (double) item->dataSize();
  QMutexLocker ml(&_mutex);
  if(neededSize>freeBytes()) {
    // Not enough space in cache
    if(!free(neededSize)) {
      QString msg=tr( "Impossible to allocate new data\n"
                        "   current used space: %1 Kb\n"
                        "   current free space: %2 Kb\n"
                        "   current buffer size: %3 Kb\n"
                        "   required space: %4 Kb\n"
                        "Increase buffer size, a good compromize is 80% of you physical memory\n"
                        "This buffer is allocated dynamically upon requests, so it will not overload\n"
                        "your memory usage.\n\n")
                        .arg(_loadedBytes/1024.0).arg(freeBytes()/1024.0)
                        .arg(_maxLoadedBytes/1024.0).arg(neededSize/1024.0)+_allocatedList.humanInfo();
      App::stream() << msg << endl;
      CoreApplication::instance()->reportBug(Message::Warning, msg.toAscii().data());
      return false; // really not lucky, no more space
    }
    // Perfect got memory free
  }
  _loadedBytes+=neededSize;
  return true;
}
void QGpCoreTools::Cache::free ( CacheItem item,
bool  saveTemp = true 
)

Free data used by item. If saveTemp is false and if data is swaped, the corresponding file is removed. It saveTemp is true and if data is allocated, data is saved to file.

References QGpCoreTools::CacheItem::dataSize(), QGpCoreTools::CacheItem::free(), QGpCoreTools::CacheItem::isAllocated(), QGpCoreTools::AllocatedCacheItem::remove(), QGpCoreTools::CacheItem::save(), QGpCoreTools::CacheItem::swapFileName(), and TRACE.

Referenced by enlarge(), GeopsyCore::SignalTemplate< sampleType >::freeSamples(), makeAvailable(), and GeopsyCore::SignalTemplate< sampleType >::~SignalTemplate().

{
  TRACE;
  if( !saveTemp && item->_saved) {
    _swapDir.remove(item->swapFileName());
    item->_saved=false;
  }
  if(item->isAllocated()) {
    if(saveTemp) {
      //printf("Saving item %s\n",item->debugName().toAscii().data());
      item->save(_swapDir);
      item->_saved=true;
    }
    item->free();
    _mutex.lock();
    _loadedBytes -= (double) item->dataSize();
    _allocatedList.remove(item);
    _mutex.unlock();
    //printf("Freeing item, %i are still allocated\n",_allocatedList.count());
    //printf("Freeing %lf Kb from item %s\t\t",(double)item->dataSize()/1024, item->debugName().toAscii().data());
    //printf("Free space=%lf Kb\n",freeBytes()/1024);
  }
}
double QGpCoreTools::Cache::freeBytes ( ) const [inline]

Referenced by enlarge(), and makeAvailable().

{return _maxLoadedBytes -_loadedBytes;}
double QGpCoreTools::Cache::freeMegaBytes ( ) const [inline]

References INV_MEGABYTES.

Referenced by GeopsyMainWindow::showDBStatus().

{return freeBytes() * INV_MEGABYTES;}

In all cases the data must not be allocated. This is not double checked. In a multi-threaded context, this function must be used by only one thread at a time and lock() of item must be called with this object locked.

References QGpCoreTools::AllocatedCacheItem::add(), QGpCoreTools::CacheItem::allocate(), QGpCoreTools::CacheItem::dataSize(), QGpCoreTools::endl(), free(), freeBytes(), QGpCoreTools::AllocatedCacheItem::humanInfo(), QGpCoreTools::CoreApplication::instance(), QGpCoreTools::CacheItem::load(), QGpCoreTools::CoreApplicationPrivate::reportBug(), QGpCoreTools::App::stream(), QGpCoreTools::CacheItem::swapFileName(), QGpCoreTools::tr(), TRACE, and QGpCoreTools::Message::Warning.

Referenced by GeopsyCore::SignalTemplate< sampleType >::constLockSamples(), GeopsyCore::Signal::constLockSamples(), GeopsyCore::SignalTemplate< sampleType >::lockSamples(), and GeopsyCore::Signal::lockSamples().

{
  TRACE;
  // Process low level allocation of data
  double neededSize=(double) item->dataSize();
  QMutexLocker ml(&_mutex);
  if(neededSize > freeBytes()) {
    // Not enough space in cache
    if(!free(neededSize)) {
      QString msg=tr( "Impossible to allocate new data\n"
                        "   current used space: %1 Kb\n"
                        "   current free space: %2 Kb\n"
                        "   current buffer size: %3 Kb\n"
                        "   required space: %4 Kb\n"
                        "Increase buffer size, a good compromize is 80% of you physical memory\n"
                        "This buffer is allocated dynamically upon requests, so it will not overload\n"
                        "your memory usage.\n\n")
                        .arg(_loadedBytes/1024.0).arg(freeBytes()/1024.0)
                        .arg(_maxLoadedBytes/1024.0).arg(neededSize/1024.0)+_allocatedList.humanInfo();
      App::stream() << msg << endl;
      //CoreApplication::instance()->reportBug(Message::Warning, msg.toAscii().data());
      _allocatedList.humanInfo();
      return false; // really not lucky, no more space
    }
    // Perfect got memory free
  }
  if(item->allocate()) {
    _allocatedList.add(item);
    _loadedBytes += neededSize;
    ml.unlock();
    if(item->_saved) {
      //printf("Loading item %s\n",item->debugName().toAscii().data());
      item->load(_swapDir);
      _swapDir.remove(item->swapFileName());
      item->_saved=false;
    }
    //printf("Allocating %lf Kbytes for item %s\t\t",neededSize/1024, item->debugName().toAscii().data());
    //printf("Free space=%lf Kb\n",freeBytes()/1024);
    return true;
  }
  // Impossible to allocate new memory, problem with your computer?
  QString msg=tr( "Impossible to allocate new data of size %1: current used space: %2 Kb.\n\n")
                   .arg(neededSize)
                   .arg(_loadedBytes * sizeof(double)/1024.0)+_allocatedList.humanInfo();
  App::stream() << msg << endl;
  CoreApplication::instance()->reportBug(Message::Warning, msg.toAscii().data());
  return false;
}
QGpCoreTools::Cache::setSize ( double  nMegaBytes) [inline]

Set the maximum number of mega bytes that can be allocated simultaneously. The default is 0.

References MEGABYTES.

Referenced by GeopsyCore::GeopsyCoreEngine::GeopsyCoreEngine().

{_maxLoadedBytes=nMegaBytes * MEGABYTES;}
void QGpCoreTools::Cache::setSwapDir ( const QDir &  d)

Set the path where to swap. The default is the home directory.

References TRACE.

Referenced by GeopsyCore::GeopsyCoreEngine::GeopsyCoreEngine().

{
  TRACE;
  _swapDir=d;
  if(_swapDir.exists()) { // clean file that might be left after a crash
    QStringList filters;
    filters << "cache_data_*";
    QStringList cacheFiles=_swapDir.entryList(filters);
    for(QStringList::iterator it=cacheFiles.begin();it!=cacheFiles.end();it++) {
      _swapDir.remove(*it);
    }
  } else {
    _swapDir.mkpath(_swapDir.absolutePath ());
  }
}

Friends And Related Function Documentation

friend class CacheItem [friend]

The documentation for this class was generated from the following files:
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines