Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "traster.h"
Toshihiro Shimizu 890ddd
#include "tbigmemorymanager.h"
Toshihiro Shimizu 890ddd
#include "timagecache.h"
Toshihiro Shimizu 890ddd
#include "tsystem.h"
Toshihiro Shimizu 890ddd
#include "tconvert.h"
Toshihiro Shimizu 890ddd
#include <set></set>
Toshihiro Shimizu 890ddd
#include "tfilepath_io.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifdef _DEBUG
Toshihiro Shimizu 890ddd
std::set<traster *=""> Rasters;</traster>
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifdef TNZCORE_LIGHT
Toshihiro Shimizu 890ddd
#ifdef MessageBox
Toshihiro Shimizu 890ddd
#undef MessageBox
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#define MessageBox MessageBoxA
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
class Chunkinfo {
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  TUINT32 m_size;
Shinya Kitaoka 120a6e
  // int m_locks;
Shinya Kitaoka 120a6e
  std::vector<traster *=""> m_rasters;</traster>
Shinya Kitaoka 120a6e
  // bool m_putInNormalMemory;
Shinya Kitaoka 120a6e
  Chunkinfo(TUINT32 size, TRaster *ras)  //, bool putInNormalMemory=false)
Shinya Kitaoka 120a6e
      : m_size(size)
Shinya Kitaoka 120a6e
        //, m_locks(0)
Shinya Kitaoka 120a6e
        ,
Shinya Kitaoka 120a6e
        m_rasters()
Shinya Kitaoka 120a6e
  //, m_putInNormalMemory(putInNormalMemory)
Shinya Kitaoka 120a6e
  {
Shinya Kitaoka 120a6e
    if (ras) m_rasters.push_back(ras);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  Chunkinfo()
Shinya Kitaoka 120a6e
      : m_size(0)
Shinya Kitaoka 120a6e
      //, m_locks(0)
Shinya Kitaoka 120a6e
      , m_rasters()
Shinya Kitaoka 120a6e
  /*, m_putInNormalMemory(false)*/ {}
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
//! Sets the global callback handler for the 'Run out of contiguous memory'
Shinya Kitaoka 120a6e
//! event
Shinya Kitaoka 120a6e
//! The callback receives the size (in bytes) of the raster which caused the
Shinya Kitaoka 120a6e
//! problem.
Shinya Kitaoka 120a6e
void TBigMemoryManager::setRunOutOfContiguousMemoryHandler(
Shinya Kitaoka 120a6e
    void (*callback)(unsigned long)) {
Shinya Kitaoka 120a6e
  m_runOutCallback = callback;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
namespace {
Shinya Kitaoka 120a6e
int allocationPeakKB               = 0;
Toshihiro Shimizu 890ddd
unsigned long long allocationSumKB = 0;
Shinya Kitaoka 120a6e
unsigned long allocationCount      = 0;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
//! Returns the \b peak size, in KB, of the allocated rasters in current Toonz
Shinya Kitaoka 120a6e
//! session.
Shinya Kitaoka 120a6e
int TBigMemoryManager::getAllocationPeak() { return allocationPeakKB; }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
//! Returns the \b mean size, in KB, of the allocated rasters in current Toonz
Shinya Kitaoka 120a6e
//! session.
Shinya Kitaoka 120a6e
int TBigMemoryManager::getAllocationMean() {
Shinya Kitaoka 120a6e
  return allocationSumKB / allocationCount;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TBigMemoryManager *TBigMemoryManager::instance() {
Shinya Kitaoka 120a6e
  static TBigMemoryManager *theManager = 0;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (theManager) return theManager;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return theManager = new TBigMemoryManager();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
/*
Toshihiro Shimizu 890ddd
TBigMemoryManager::~TBigMemoryManager()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
if (m_theMemory==0) return;
Toshihiro Shimizu 890ddd
QMutexLocker sl(m_mutex);
Toshihiro Shimizu 890ddd
assert(m_chunks.empty());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
free(m_theMemory);
Toshihiro Shimizu 890ddd
theManager = 0;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
UCHAR *TBigMemoryManager::allocate(UINT &size) {
Shinya Kitaoka 120a6e
  TThread::MutexLocker sl(&m_mutex);
Shinya Kitaoka 120a6e
  UCHAR *chunk = (UCHAR *)calloc(size, 1);
Shinya Kitaoka 120a6e
  while (chunk == 0 && size > 128 * 1024 * 1024) {
Shinya Kitaoka 120a6e
    size -= 128 * 1024 * 1024;
Shinya Kitaoka 120a6e
    chunk = (UCHAR *)calloc(size, 1);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  return chunk;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TBigMemoryManager::TBigMemoryManager()
Shinya Kitaoka 120a6e
    : m_chunks()
Shinya Kitaoka 120a6e
    , m_theMemory(0)
Shinya Kitaoka 120a6e
    , m_availableMemory(0)
Shinya Kitaoka 120a6e
    , m_allocatedMemory(0)
Toshihiro Shimizu 890ddd
#ifdef _DEBUG
Shinya Kitaoka 120a6e
    , m_totRasterMemInKb(0)
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool TBigMemoryManager::init(TUINT32 sizeinKb) {
Shinya Kitaoka 120a6e
  TThread::MutexLocker sl(&m_mutex);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (sizeinKb == 0) return true;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (sizeinKb >= 2 * 1024 * 1024) {
Shinya Kitaoka 120a6e
    //  MessageBox( NULL, "TRONCO!!!", "Warning", MB_OK);
Shinya Kitaoka 120a6e
    sizeinKb = (TUINT32)(1.8 * 1024 * 1024);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_availableMemory = sizeinKb * 1024;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_theMemory       = allocate(m_availableMemory);
Shinya Kitaoka 120a6e
  m_allocatedMemory = m_availableMemory;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (!m_theMemory) {
Shinya Kitaoka 120a6e
    //  MessageBox( NULL, "Ouch!can't allocate Big Chunk!", "Warning", MB_OK);
Shinya Kitaoka 120a6e
    m_theMemory       = 0;
Shinya Kitaoka 120a6e
    m_availableMemory = 0;
Shinya Kitaoka 120a6e
    return false;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  // char str[1024];
Shinya Kitaoka 120a6e
  // sprintf_s(str, "chiesto %d MB, allocato un big chunk di %d MB",
Shinya Kitaoka 120a6e
  // sizeinKb/1024, m_availableMemory/(1024*1024));
Shinya Kitaoka 120a6e
  // MessageBox( NULL, str, "Warning", MB_OK);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_chunks[m_theMemory + m_availableMemory] = Chunkinfo(0, 0);
Shinya Kitaoka 120a6e
  return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
/*
Toshihiro Shimizu 890ddd
void TBigMemoryManager::lock(UCHAR *buffer)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
QMutexLocker sl(m_mutex);
Toshihiro Shimizu 890ddd
if (m_theMemory==0) return;
Toshihiro Shimizu 890ddd
assert(buffer);
Toshihiro Shimizu 890ddd
map<uchar*, chunkinfo="">::iterator it = m_chunks.find(buffer);</uchar*,>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
if (it==m_chunks.end()) return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
++it->second.m_locks;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*
Toshihiro Shimizu 890ddd
void TBigMemoryManager::unlock(UCHAR *buffer)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
QMutexLocker sl(m_mutex);
Toshihiro Shimizu 890ddd
if (m_theMemory==0) return;
Toshihiro Shimizu 890ddd
assert(buffer);
Toshihiro Shimizu 890ddd
map<uchar*, chunkinfo="">::iterator it = m_chunks.find(buffer);</uchar*,>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
if (it==m_chunks.end()) return;
Toshihiro Shimizu 890ddd
int locks = it->second.m_locks;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
assert(locks>0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
--it->second.m_locks;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
UCHAR *TBigMemoryManager::getBuffer(UINT size) {
Shinya Kitaoka 120a6e
  if (m_theMemory == 0) return (UCHAR *)calloc(size, 1);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  std::map<uchar *,="" chunkinfo="">::iterator it = m_chunks.begin();</uchar>
Shinya Kitaoka 120a6e
  UCHAR *buffer     = m_theMemory;
Shinya Kitaoka 120a6e
  TUINT32 chunkSize = 0;
Shinya Kitaoka 120a6e
  UCHAR *address    = 0;
Shinya Kitaoka 120a6e
  while (it != m_chunks.end()) {
Shinya Kitaoka 120a6e
    /*if (it->second.m_putInNormalMemory)
Shinya Kitaoka 120a6e
{it++; continue;}*/
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if ((TUINT32)((it->first) - (buffer + chunkSize)) >= size) {
Shinya Kitaoka 120a6e
      address = buffer + chunkSize;
Shinya Kitaoka 120a6e
      break;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    buffer    = it->first;
Shinya Kitaoka 120a6e
    chunkSize = it->second.m_size;
Shinya Kitaoka 120a6e
    it++;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  if (address) memset(address, 0x00, size);
Shinya Kitaoka 120a6e
  return address;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifdef _DEBUG
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TBigMemoryManager::getRasterInfo(int &rasterCount,
Shinya Kitaoka 120a6e
                                      TUINT32 &totRasterMemInKb,
Shinya Kitaoka 120a6e
                                      int ¬CachedRasterCount,
Shinya Kitaoka 120a6e
                                      TUINT32 ¬CachedRasterMemInKb) {
Shinya Kitaoka 120a6e
  totRasterMemInKb       = 0;
Shinya Kitaoka 120a6e
  notCachedRasterMemInKb = 0;
Shinya Kitaoka 120a6e
  notCachedRasterCount   = 0;
Shinya Kitaoka 120a6e
  rasterCount            = Rasters.size();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  std::set<traster *="">::iterator it = Rasters.begin();</traster>
Shinya Kitaoka 120a6e
  while (it != Rasters.end()) {
Shinya Kitaoka 120a6e
    TRaster *r = *it;
Shinya Kitaoka 120a6e
    assert(r->m_parent == 0);
Shinya Kitaoka 120a6e
    totRasterMemInKb += r->getLx() * r->getLy() * r->getPixelSize() >> 10;
Shinya Kitaoka 120a6e
    if (!(*it)->m_cashed && r->getLy() > 1) {
Shinya Kitaoka 120a6e
      notCachedRasterCount++;
Shinya Kitaoka 120a6e
      notCachedRasterMemInKb +=
Shinya Kitaoka 120a6e
          r->getLx() * r->getLy() * r->getPixelSize() >> 10;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    ++it;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool TBigMemoryManager::putRaster(TRaster *ras, bool canPutOnDisk) {
Shinya Kitaoka 120a6e
  if (!ras->m_parent && ras->m_buffer) {
Toshihiro Shimizu 890ddd
#ifdef _DEBUG
Shinya Kitaoka 120a6e
    if (ras->m_bufferOwner) Rasters.insert(ras);
Toshihiro Shimizu 890ddd
#endif
Shinya Kitaoka 120a6e
    return true;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifdef _DEBUG
Shinya Kitaoka 120a6e
  checkConsistency();
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TUINT32 size = ras->getLx() * ras->getLy() * ras->getPixelSize();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (size == 0) {
Shinya Kitaoka 120a6e
    ras->m_buffer = 0;
Shinya Kitaoka 120a6e
    return true;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (m_theMemory == 0)  // il bigmemorymanager e' inattivo
Shinya Kitaoka 120a6e
  {
Shinya Kitaoka 120a6e
    if (!ras->m_parent) {
Shinya Kitaoka 120a6e
      int sizeKB       = size >> 10;
Shinya Kitaoka 120a6e
      allocationPeakKB = std::max(allocationPeakKB, sizeKB);
Shinya Kitaoka 120a6e
      allocationSumKB += sizeKB;
Shinya Kitaoka 120a6e
      allocationCount++;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (!ras->m_parent && !(ras->m_buffer = (UCHAR *)calloc(size, 1))) {
Shinya Kitaoka 120a6e
      // MessageBox( NULL, "Ouch!can't allocate!", "Warning", MB_OK);
Shinya Kitaoka 120a6e
      // non c'e' memoria; provo a comprimere
Shinya Kitaoka 120a6e
      /*TImageCache::instance()->doCompress(); 
Shinya Kitaoka 120a6e
    if (!(ras->m_buffer = (UCHAR *)malloc(size)))*/  // andata male pure cosi';
Shinya Kitaoka 120a6e
                                                     // metto tutto su disco
Shinya Kitaoka 120a6e
      // TImageCache::instance()->outputMap(size, "C:\\logCacheFailure");
Shinya Kitaoka 120a6e
      TINT64 availMemInKb = TSystem::getFreeMemorySize(true);
Shinya Kitaoka 120a6e
      if (availMemInKb > (size >> 10)) {
Shinya Kitaoka 120a6e
        // char str[1024];
Shinya Kitaoka 120a6e
        // sprintf_s(str, "Non alloco, ma : memoria (KB) richiesta : %d -
Shinya Kitaoka 120a6e
        // memoria disponibile : %d", size>>10, availMemInKb);
Shinya Kitaoka 120a6e
        // MessageBox( NULL, (LPCSTR)str, (LPCSTR)"Segmentation!", MB_OK);
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      ras->m_buffer = TImageCache::instance()->compressAndMalloc(size);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      if (!ras->m_buffer) {
Shinya Kitaoka 120a6e
        // char str[1024];
Shinya Kitaoka 120a6e
        // sprintf_s(str, "E' andata male: faccio il log della cache.");
Shinya Kitaoka 120a6e
        // MessageBox( NULL, (LPCSTR)str, (LPCSTR)"Segmentation!", MB_OK);
Shinya Kitaoka 120a6e
        TImageCache::instance()->outputMap(size, "C:\\logCacheTotalFailure");
Shinya Kitaoka 120a6e
      } else {
Toshihiro Shimizu 890ddd
#ifdef _DEBUG
Shinya Kitaoka 120a6e
        m_totRasterMemInKb += size >> 10;
Shinya Kitaoka 120a6e
        Rasters.insert(ras);
Toshihiro Shimizu 890ddd
#endif
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      return ras->m_buffer != 0;
Shinya Kitaoka 120a6e
    } else {
Shinya Kitaoka 120a6e
      if (!ras->m_parent) {
Toshihiro Shimizu 890ddd
#ifdef _DEBUG
Shinya Kitaoka 120a6e
        m_totRasterMemInKb += size >> 10;
Shinya Kitaoka 120a6e
        Rasters.insert(ras);
Toshihiro Shimizu 890ddd
#endif
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      return true;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // il bigmemorymanager e' attivo
Shinya Kitaoka 120a6e
  TThread::MutexLocker sl(&m_mutex);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  /*
Toshihiro Shimizu 890ddd
if (m_availableMemory<size !ras-="" &&="">m_parent)</size>
Shinya Kitaoka 120a6e
{
Shinya Kitaoka 120a6e
TImageCache::instance()->compressAndMalloc(size);
Shinya Kitaoka 120a6e
if (m_availableMemory>=size)
Shinya Kitaoka 120a6e
return TBigMemoryManager::instance()->putRaster(ras);
Shinya Kitaoka 120a6e
else
Shinya Kitaoka 120a6e
return (ras->m_buffer = (UCHAR *)malloc(size))!=0;
Shinya Kitaoka 120a6e
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
}*/
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (ras->m_parent) {
Shinya Kitaoka 120a6e
    std::map<uchar *,="" chunkinfo="">::iterator it =</uchar>
Shinya Kitaoka 120a6e
        m_chunks.find(ras->m_parent->m_buffer);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    if (it != m_chunks.end()) {
Toshihiro Shimizu 890ddd
#ifdef _DEBUG
Shinya Kitaoka 120a6e
// assert(!it->second.m_rasters.empty());
Shinya Kitaoka 120a6e
// for (UINT i=0; i<it->second.m_rasters.size(); i++)</it->
Toshihiro Shimizu 890ddd
//  assert (it->second.m_rasters[i]!=ras);
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      it->second.m_rasters.push_back(ras);
Shinya Kitaoka 120a6e
    }
Toshihiro Shimizu 890ddd
#ifdef _DEBUG
Shinya Kitaoka 120a6e
    checkConsistency();
Toshihiro Shimizu 890ddd
#endif
Shinya Kitaoka 120a6e
    return true;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  UCHAR *address = 0;
Shinya Kitaoka 120a6e
  bool remapped  = false;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  assert(m_chunks.size() > 0);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  /*if (m_chunks.size()==1) //c'e' solo l'elemento che marca la fine del
Shinya Kitaoka 120a6e
bufferone
Shinya Kitaoka 120a6e
{
Shinya Kitaoka 120a6e
if ((TUINT32)(m_chunks.begin()->first-m_theMemory)>=size)
Shinya Kitaoka 120a6e
address = m_theMemory;
Shinya Kitaoka 120a6e
}
Toshihiro Shimizu 890ddd
else
Shinya Kitaoka 120a6e
{*/
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  address = getBuffer(size);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifdef _DEBUG
Shinya Kitaoka 120a6e
  checkConsistency();
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (address == 0 && m_availableMemory >= size) {
Shinya Kitaoka 120a6e
    address  = remap(size);
Shinya Kitaoka 120a6e
    remapped = true;
Toshihiro Shimizu 890ddd
#ifdef _DEBUG
Shinya Kitaoka 120a6e
    checkConsistency();
Toshihiro Shimizu 890ddd
#endif
Shinya Kitaoka 120a6e
  } else if (address == 0) {
Shinya Kitaoka 120a6e
    printLog(size);
Shinya Kitaoka 120a6e
    // assert(!"la bigmemory e' piena...scritto log");
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  //}
Shinya Kitaoka 120a6e
  if (address == 0) {
Shinya Kitaoka 120a6e
    if (canPutOnDisk)
Shinya Kitaoka 120a6e
      address = TImageCache::instance()->compressAndMalloc(size);
Shinya Kitaoka 120a6e
    if (address == 0) return (ras->m_buffer = (UCHAR *)calloc(size, 1)) != 0;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // assert(address);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  ras->m_buffer     = address;
Shinya Kitaoka 120a6e
  m_chunks[address] = Chunkinfo(size, ras);
Shinya Kitaoka 120a6e
  assert(m_availableMemory >= size);
Shinya Kitaoka 120a6e
  m_availableMemory -= size;
Toshihiro Shimizu 890ddd
#ifdef _DEBUG
Shinya Kitaoka 120a6e
  checkConsistency();
Toshihiro Shimizu 890ddd
#endif
Shinya Kitaoka 120a6e
  return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TRaster *TBigMemoryManager::findRaster(TRaster *ras) {
Shinya Kitaoka 120a6e
  // return 0;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  std::map<uchar *,="" chunkinfo="">::iterator it = m_chunks.begin();</uchar>
Shinya Kitaoka 120a6e
  while (it != m_chunks.end()) {
Shinya Kitaoka 120a6e
    for (UINT i = 0; i < it->second.m_rasters.size(); i++)
Shinya Kitaoka 120a6e
      if (it->second.m_rasters[i] == ras) return ras;
Shinya Kitaoka 120a6e
    it++;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  return 0;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
#ifdef _DEBUG
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TBigMemoryManager::printMap() {
Shinya Kitaoka 120a6e
  std::map<uchar *,="" chunkinfo="">::iterator it = m_chunks.begin();</uchar>
Shinya Kitaoka 120a6e
  TSystem::outputDebug("BIGMEMORY chunks totali: " +
Shinya Kitaoka 120a6e
                       std::to_string((int)m_chunks.size()) + "\n");
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int count = 0;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  while (it != m_chunks.end()) {
Shinya Kitaoka 120a6e
    TSystem::outputDebug(
Shinya Kitaoka 120a6e
        "chunk #" + std::to_string((int)count++) + "dimensione(kb):" +
Shinya Kitaoka 120a6e
        std::to_string((int)(it->second.m_size >> 10)) + "num raster:" +
Shinya Kitaoka 120a6e
        std::to_string((int)(it->second.m_rasters.size())) + "\n");
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    it++;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool TBigMemoryManager::releaseRaster(TRaster *ras) {
Shinya Kitaoka 120a6e
  TThread::MutexLocker sl(&m_mutex);
Shinya Kitaoka 120a6e
  UCHAR *buffer = (ras->m_parent) ? (ras->m_parent->m_buffer) : (ras->m_buffer);
Shinya Kitaoka 120a6e
  std::map<uchar *,="" chunkinfo="">::iterator it = m_chunks.find(buffer);</uchar>
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (m_theMemory == 0 || it == m_chunks.end()) {
Shinya Kitaoka 120a6e
    assert(buffer);
Shinya Kitaoka 120a6e
    if (!ras->m_parent && ras->m_bufferOwner) {
Shinya Kitaoka 120a6e
      free(buffer);
Toshihiro Shimizu 890ddd
#ifdef _DEBUG
Shinya Kitaoka 120a6e
      m_totRasterMemInKb -=
Shinya Kitaoka 120a6e
          (ras->getPixelSize() * ras->getLx() * ras->getLy()) >> 10;
Shinya Kitaoka 120a6e
      Rasters.erase(ras);
Toshihiro Shimizu 890ddd
#endif
Shinya Kitaoka 120a6e
    }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    // assert(findRaster(ras)==0);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    return false;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  assert(ras->m_lockCount == 0);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (it->second.m_rasters.size() >
Shinya Kitaoka 120a6e
      1)  // non e' il solo raster ad usare il buffer; non libero
Shinya Kitaoka 120a6e
  {
Shinya Kitaoka 120a6e
    std::vector<traster *="">::iterator it2 = it->second.m_rasters.begin();</traster>
Shinya Kitaoka 120a6e
    for (; it2 != it->second.m_rasters.end(); ++it2) {
Shinya Kitaoka 120a6e
      if (ras == *it2) {
Shinya Kitaoka 120a6e
        it->second.m_rasters.erase(it2);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifdef _DEBUG
Shinya Kitaoka 120a6e
// assert(!it->second.m_rasters.empty());
Shinya Kitaoka 120a6e
// assert(findRaster(ras)==0);
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
        return true;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    assert(false);
Shinya Kitaoka 120a6e
    return false;
Shinya Kitaoka 120a6e
  } else if (ras->m_bufferOwner)  // libero!
Shinya Kitaoka 120a6e
  {
Toshihiro Shimizu 890ddd
#ifdef _DEBUG
Shinya Kitaoka 120a6e
    checkConsistency();
Toshihiro Shimizu 890ddd
#endif
Shinya Kitaoka 120a6e
    /*if (it->second.m_putInNormalMemory && ras->m_bufferOwner)
Shinya Kitaoka 120a6e
    free(it->first);
Shinya Kitaoka 120a6e
else */
Shinya Kitaoka 120a6e
    m_availableMemory += it->second.m_size;
Shinya Kitaoka 120a6e
    m_chunks.erase(it);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifdef _DEBUG
Shinya Kitaoka 120a6e
  // assert(findRaster(ras)==0);
Shinya Kitaoka 120a6e
  checkConsistency();
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TBigMemoryManager::checkConsistency() {
Shinya Kitaoka 120a6e
  return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // QMutexLocker sl(m_mutex);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int count = 0;
Shinya Kitaoka 120a6e
  // int size = m_chunks.size();
Shinya Kitaoka 120a6e
  std::map<uchar *,="" chunkinfo="">::iterator it = m_chunks.begin();</uchar>
Shinya Kitaoka 120a6e
  UCHAR *endAddress = m_theMemory;
Shinya Kitaoka 120a6e
  TUINT32 freeMem = 0, allocMem = 0;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  while (it != m_chunks.end()) {
Shinya Kitaoka 120a6e
    count++;
Shinya Kitaoka 120a6e
    // assert(it->second.m_rasters.size()==0 || it->second.m_rasters.size()>0);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (endAddress != 0 /*&& !it->second.m_putInNormalMemory*/) {
Shinya Kitaoka 120a6e
      freeMem += (TUINT32)(it->first - endAddress);
Shinya Kitaoka 120a6e
      allocMem += it->second.m_size;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    assert(endAddress <= it->first);
Shinya Kitaoka 120a6e
    endAddress = it->first + it->second.m_size;
Shinya Kitaoka 120a6e
    for (UINT i = 0; i < it->second.m_rasters.size(); i++) {
Shinya Kitaoka 120a6e
      TRaster *ras            = it->second.m_rasters[i];
Shinya Kitaoka 120a6e
      it->second.m_rasters[i] = 0;  // ogni raster deve apparire una sola volta
Shinya Kitaoka 120a6e
      assert(findRaster(ras) == 0);
Shinya Kitaoka 120a6e
      it->second.m_rasters[i] = ras;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      UCHAR *buf1 = (ras->m_parent) ? ras->m_parent->m_buffer : ras->m_buffer;
Shinya Kitaoka 120a6e
      UCHAR *buf2 = it->first;
Shinya Kitaoka 120a6e
      assert(buf1 == buf2);
Shinya Kitaoka 120a6e
      UINT size;
Shinya Kitaoka 120a6e
      if (ras->m_parent)
Shinya Kitaoka 120a6e
        size = ras->m_parent->getLx() * ras->m_parent->getLy() *
Shinya Kitaoka 120a6e
               ras->m_parent->getPixelSize();
Shinya Kitaoka 120a6e
      else
Shinya Kitaoka 120a6e
        size = ras->getLx() * ras->getLy() * ras->getPixelSize();
Shinya Kitaoka 120a6e
      assert(size == it->second.m_size);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    it++;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (m_theMemory) {
Shinya Kitaoka 120a6e
    assert(allocMem + m_availableMemory == m_allocatedMemory);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    assert(freeMem == m_availableMemory);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
std::map<uchar *,="" chunkinfo="">::iterator TBigMemoryManager::shiftBlock(</uchar>
Shinya Kitaoka 120a6e
    const std::map<uchar *,="" chunkinfo="">::iterator &it, TUINT32 offset) {</uchar>
Shinya Kitaoka 120a6e
  UCHAR *newAddress = it->first - offset;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (offset > it->second.m_size)
Shinya Kitaoka 120a6e
    memcpy(newAddress, it->first, it->second.m_size);  // se NON overlappano.
Shinya Kitaoka 120a6e
  else
Shinya Kitaoka 120a6e
    memmove(newAddress, it->first, it->second.m_size);  // se overlappano.
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  m_chunks[newAddress] = Chunkinfo(it->second.m_size, it->second.m_rasters[0]);
Shinya Kitaoka 120a6e
  std::map<uchar *,="" chunkinfo="">::iterator it1 = m_chunks.find(newAddress);</uchar>
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  assert(it1->first < it1->second.m_rasters[0]->m_buffer);
Shinya Kitaoka 120a6e
  UINT i = 0;
Shinya Kitaoka 120a6e
  for (i = 0; i < it->second.m_rasters.size();
Shinya Kitaoka 120a6e
       i++)  // prima rimappo i subraster, senza toccare il buffer del parent...
Shinya Kitaoka 120a6e
  {
Shinya Kitaoka 120a6e
    TRaster *ras = it->second.m_rasters[i];
Shinya Kitaoka 120a6e
    assert(i > 0 || !ras->m_parent);
Shinya Kitaoka 120a6e
    if (!ras->m_parent) continue;
Shinya Kitaoka 120a6e
    assert(ras->m_parent->m_buffer == it->first);
Shinya Kitaoka 120a6e
    ras->remap(newAddress);
Shinya Kitaoka 120a6e
    if (i > 0) it1->second.m_rasters.push_back(ras);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  it->second.m_rasters[0]->remap(newAddress);  // ORA rimappo il parent
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifdef _DEBUG
Shinya Kitaoka 120a6e
  for (i = 1; i < it->second.m_rasters.size(); i++)  //..poi i raster padri
Shinya Kitaoka 120a6e
  {
Shinya Kitaoka 120a6e
    // TRaster*ras = it->second.m_rasters[i];
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    assert(it->second.m_rasters[i]->m_parent);
Shinya Kitaoka 120a6e
    // ras->remap(newAddress);
Shinya Kitaoka 120a6e
    // if (i>0)
Shinya Kitaoka 120a6e
    //  it1->second.m_rasters.push_back(ras);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  assert(it1->second.m_rasters.size() == it->second.m_rasters.size());
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_chunks.erase(it);
Shinya Kitaoka 120a6e
  it1 = m_chunks.find(newAddress);  // non dovrebbe servire, ma per prudenza...
Shinya Kitaoka 120a6e
  assert(it1->first == it1->second.m_rasters[0]->m_buffer);
Shinya Kitaoka 120a6e
  return it1;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
UCHAR *TBigMemoryManager::remap(TUINT32 size)  // size==0 -> remappo tutto
Toshihiro Shimizu 890ddd
{
Shinya Kitaoka 120a6e
  bool locked = false;
Shinya Kitaoka 120a6e
// QMutexLocker sl(m_mutex); //gia' scopata
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifdef _DEBUG
Shinya Kitaoka 120a6e
  checkConsistency();
Toshihiro Shimizu 890ddd
#endif
Shinya Kitaoka 120a6e
  UINT i;
Shinya Kitaoka 120a6e
  std::map<uchar *,="" chunkinfo="">::iterator it = m_chunks.begin();</uchar>
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  try {
Shinya Kitaoka 120a6e
    UCHAR *buffer     = m_theMemory;
Shinya Kitaoka 120a6e
    TUINT32 chunkSize = 0;
Shinya Kitaoka 120a6e
    while (it != m_chunks.end()) {
Shinya Kitaoka 120a6e
      /*if (it->second.m_putInNormalMemory)
Shinya Kitaoka 120a6e
{it++; continue;}*/
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      TUINT32 gap = (TUINT32)((it->first) - (buffer + chunkSize));
Shinya Kitaoka 120a6e
      if (size > 0 && gap >= size)  // trovato chunk sufficiente
Shinya Kitaoka 120a6e
        return buffer + chunkSize;
Shinya Kitaoka 120a6e
      else if (gap > 0 && it->second.m_size > 0)  // c'e' un frammento di
Shinya Kitaoka 120a6e
                                                  // memoria, accorpo; ma solo
Shinya Kitaoka 120a6e
                                                  // se non sto in fondo
Shinya Kitaoka 120a6e
      {
Shinya Kitaoka 120a6e
        std::vector<traster *=""> &rasters = it->second.m_rasters;</traster>
Shinya Kitaoka 120a6e
        assert(rasters[0]->m_parent == 0);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        // devo controllare il lockCount solo sul parent, la funzione lock()
Shinya Kitaoka 120a6e
        // locka solo il parent;
Shinya Kitaoka 120a6e
        for (i = 0; i < rasters.size(); i++) rasters[i]->beginRemapping();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        if (rasters[0]->m_lockCount == 0)
Shinya Kitaoka 120a6e
          it = shiftBlock(it, gap);
Shinya Kitaoka 120a6e
        else
Shinya Kitaoka 120a6e
          locked = true;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        for (i = 0; i < rasters.size(); i++) rasters[i]->endRemapping();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        // rasters.clear();
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      buffer    = it->first;
Shinya Kitaoka 120a6e
      chunkSize = it->second.m_size;
Shinya Kitaoka 120a6e
      it++;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  } catch (...) {
Shinya Kitaoka 120a6e
    for (i = 0; i < it->second.m_rasters.size(); i++)
Shinya Kitaoka 120a6e
      it->second.m_rasters[i]->endRemapping();
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (size >
Shinya Kitaoka 120a6e
      0)  // e' andata male...non liberato un blocco di grandezza sufficiente
Shinya Kitaoka 120a6e
  {
Shinya Kitaoka 120a6e
    printLog(size);
Shinya Kitaoka 120a6e
    assert(!"Niente memoria! scritto log");
Shinya Kitaoka 120a6e
    if (!locked)
Shinya Kitaoka 120a6e
      assert(false);  // se entro nella remap, di sicuro c'e' 'size'  memoria
Shinya Kitaoka 120a6e
                      // disponibile; basta deframmentarla
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  return 0;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TBigMemoryManager::printLog(TUINT32 size) {
Shinya Kitaoka 120a6e
  TFilePath fp("C:\\memorymaplog.txt");
Shinya Kitaoka 120a6e
  Tofstream os(fp);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  os << "memoria totale: " << m_allocatedMemory / 1024 << " KB\n";
Shinya Kitaoka 120a6e
  os << "memoria richiesta: " << size / 1024 << " KB\n";
Shinya Kitaoka 120a6e
  os << "memoria libera: " << m_availableMemory / 1024 << " KB\n\n\n";
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  std::map<uchar *,="" chunkinfo="">::iterator it = m_chunks.begin();</uchar>
Shinya Kitaoka 120a6e
  UCHAR *buffer  = m_theMemory;
Shinya Kitaoka 120a6e
  UINT chunkSize = 0;
Shinya Kitaoka 120a6e
  for (; it != m_chunks.end(); it++) {
Shinya Kitaoka 120a6e
    TUINT32 gap = (TUINT32)((it->first) - (buffer + chunkSize));
Shinya Kitaoka 120a6e
    if (gap > 0) os << "- gap di " << gap / 1024 << " KB\n";
Shinya Kitaoka 120a6e
    if (it->second.m_size > 0)
Shinya Kitaoka 120a6e
      os << "- raster di " << it->second.m_size / 1024 << " KB"
Shinya Kitaoka 120a6e
         << ((it->second.m_rasters[0]->m_lockCount > 0) ? " LOCCATO!\n" : "\n");
Shinya Kitaoka 120a6e
    buffer    = it->first;
Shinya Kitaoka 120a6e
    chunkSize = it->second.m_size;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}