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