Jeck - Cache Leakfix. Quads now individually lock/unlock. Demo still crashes PSP.

This commit is contained in:
wagic.jeck
2009-09-14 20:54:49 +00:00
parent 5467fd379f
commit a84ed94954
4 changed files with 218 additions and 65 deletions

View File

@@ -18,24 +18,47 @@ public:
virtual void Nullify()=0; //For when our size is 0, so we don't free anything by mistake.
virtual unsigned long size()=0; //Size of cached item in bytes.
virtual void Refresh(string filename)=0; //Basically calls Attempt(filename) and remaps in situ.
virtual bool isGood()=0; //Return true if this has data.
virtual bool Attempt(string filename, int submode, int & error)=0; //Returns true if we've loaded our data and isGood().
virtual bool isLocked(); //Is the resource locked?
virtual void lock(); //Lock it.
virtual void unlock(bool force = false); //Unlock it. Forcing a lock will also remove "permanent" status.
protected:
bool isLocked(); //Is the resource locked?
bool isPermanent(); //Is the resource permanent?
void lock(); //Lock it.
void deadbolt(); //Make it permanent.
void unlock(bool force = false); //Unlock it. Forcing a lock will also remove "permanent" status.
void hit(); //Update resource's last used time.
protected:
int loadedMode; //What submode settings were we loaded with? (For refresh)
unsigned int lastTime; //When was the last time we were hit?
unsigned char locks; //Remember to unlock when we're done using locked stuff, or else this'll be useless.
};
class WCachedTexture: public WResource{
class WCachedResource: public WResource {
public:
friend class WResourceManager;
template<class cacheItem,class cacheActual> friend class WCache;
virtual void Refresh(string filename)=0; //Basically calls Attempt(filename) and remaps in situ.
virtual bool Attempt(string filename, int submode, int & error)=0; //Returns true if we've loaded our data and isGood().
};
class WTrackedQuad: public WResource {
public:
WTrackedQuad(string _resname);
~WTrackedQuad();
void Nullify();
unsigned long size();
bool isGood();
string resname;
JQuad * quad;
#ifdef DEBUG_CACHE
static int totalTracked;
#endif
};
class WCachedTexture: public WCachedResource{
public:
friend class WResourceManager;
template<class cacheItem,class cacheActual> friend class WCache;
@@ -44,23 +67,28 @@ public:
void Refresh(string filename);
unsigned long size();
bool isGood();
bool isGood();
bool isLocked();
bool Attempt(string filename, int submode, int & error);
bool compare(JTexture * t) {return (t == texture);};
void Nullify();
JTexture * Actual(); //Return this texture as is. Does not make a new one.
JQuad * GetQuad(string resname);
JQuad * GetQuad(float offX=0.0f, float offY=0.0f, float width=0.0f, float height=0.0f,string resname=""); //Get us a new/existing quad.
WTrackedQuad* GetTrackedQuad(float offX=0.0f, float offY=0.0f, float width=0.0f, float height=0.0f,string resname=""); //Get us a new/existing quad.
JQuad * GetQuad(float offX=0.0f, float offY=0.0f, float width=0.0f, float height=0.0f,string resname=""); //Alias to GetTrackedQuad.
JQuad * GetCard(float offX=0.0f, float offY=0.0f, float width=0.0f, float height=0.0f,string resname=""); //Same as above, but centered when new.
bool ReleaseQuad(JQuad* quad); //We're done with this quad, so delete and stop tracking. True if existed.
protected:
JTexture * texture;
bool bVRAM;
map<JQuad*,string> trackedQuads;
vector<WTrackedQuad*> trackedQuads;
};
class WCachedParticles: public WResource{
class WCachedParticles: public WCachedResource{
public:
friend class WResourceManager;
template<class cacheItem,class cacheActual> friend class WCache;
@@ -79,7 +107,7 @@ protected:
hgeParticleSystemInfo * particles;
};
class WCachedSample: public WResource{
class WCachedSample: public WCachedResource{
public:
friend class WResourceManager;
template<class cacheItem,class cacheActual> friend class WCache;

View File

@@ -23,8 +23,8 @@ enum ENUM_WRES_INFO{
enum ENUM_RETRIEVE_STYLE{
RETRIEVE_EXISTING, //Only returns a resource if it already exists. Does not lock or unlock.
RETRIEVE_NORMAL, //Returns or creates a resource. Does not change lock status.
RETRIEVE_LOCK, //As above, locks cached resource. Not for quads.
RETRIEVE_UNLOCK, //As above, unlocks cached resource. Not for quads.
RETRIEVE_LOCK, //As above, locks cached resource.
RETRIEVE_UNLOCK, //As above, unlocks cached resource.
RETRIEVE_RESOURCE, //Only retrieves a managed resource. Does not make a new one.
RETRIEVE_VRAM, //Retrieve it, and use vram if have to we create it. Must still remove it.
RETRIEVE_MANAGE, //Makes resource permanent.
@@ -104,7 +104,9 @@ protected:
#endif
};
struct WManagedQuad {
class WManagedQuad {
public:
WManagedQuad() {texture = NULL;};
WCachedTexture * texture;
string resname;
};
@@ -183,7 +185,7 @@ private:
WCache<WCachedTexture,JTexture> textureWCache;
WCache<WCachedSample,JSample> sampleWCache;
WCache<WCachedParticles,hgeParticleSystemInfo> psiWCache;
vector<WManagedQuad> managedQuads;
vector<WManagedQuad*> managedQuads;
//Statistics of record.
unsigned int lastTime;

View File

@@ -66,12 +66,16 @@ WCachedTexture::~WCachedTexture(){
if(!trackedQuads.size())
return;
map<JQuad*,string>::iterator it, nit;
vector<WTrackedQuad*>::iterator it;
WTrackedQuad * tq = NULL;
for(it=trackedQuads.begin();it!=trackedQuads.end();it=nit){
nit = it;
nit++;
trackedQuads.erase(it);
for(it=trackedQuads.begin();it!=trackedQuads.end();it++){
tq = (*it);
if(!tq)
continue;
SAFE_DELETE(tq->quad);
SAFE_DELETE(tq);
}
trackedQuads.clear();
}
@@ -79,29 +83,52 @@ WCachedTexture::~WCachedTexture(){
JTexture * WCachedTexture::Actual(){
return texture;
}
bool WCachedTexture::isLocked(){
if(locks != WRES_UNLOCKED)
return true;
for(vector<WTrackedQuad*>::iterator it=trackedQuads.begin();it!=trackedQuads.end();it++){
if((*it)->isLocked())
return true;
}
return false;
}
bool WCachedTexture::ReleaseQuad(JQuad* quad){
#ifdef DEBUG_CACHE
OutputDebugString("Quad released.\n");
#endif
if(quad == NULL)
return false;
for(map<JQuad*,string>::iterator i = trackedQuads.begin();i!=trackedQuads.end();i++){
if(i->first == quad ){
unlock();
trackedQuads.erase(i);
return true;
WTrackedQuad * tq = NULL;
for(vector<WTrackedQuad*>::iterator it = trackedQuads.begin();it!=trackedQuads.end();it++){
if((*it) && (*it)->quad == quad ){
tq = (*it);
tq->unlock();
if(!tq->isLocked()){
SAFE_DELETE(tq->quad);
SAFE_DELETE(tq);
trackedQuads.erase(it);
}
return true; //Returns true when found, not released.
}
}
return false;
}
JQuad * WCachedTexture::GetQuad(float offX, float offY, float width, float height,string resname){
WTrackedQuad * WCachedTexture::GetTrackedQuad(float offX, float offY, float width, float height,string resname){
if(texture == NULL)
return NULL;
JQuad * jq = NULL;
bool allocated = false;
WTrackedQuad * tq = NULL;
JQuad * quad = NULL;
map<JQuad*,string>::iterator it;
vector<WTrackedQuad*>::iterator it;
std::transform(resname.begin(),resname.end(),resname.begin(),::tolower);
if(width == 0.0f || width > texture->mWidth)
@@ -109,40 +136,73 @@ JQuad * WCachedTexture::GetQuad(float offX, float offY, float width, float heigh
if(height == 0.0f || height > texture->mHeight)
height = texture->mHeight;
for(it = trackedQuads.begin();it!=trackedQuads.end();it++){
if(it->second == resname){
jq = it->first;
if((*it) && (*it)->resname == resname){
tq = (*it);
break;
}
}
if(jq == NULL){
jq = NEW JQuad(texture,offX,offY,width,height);
if(!jq) {
if(tq == NULL){
allocated = true;
tq = NEW WTrackedQuad(resname);
if(!tq) {
//Probably out of memory. Try again.
resources.Cleanup();
jq = NEW JQuad(texture,offX,offY,width,height);
tq = NEW WTrackedQuad(resname);
}
}
if(tq == NULL)
return NULL;
quad = tq->quad;
if(quad == NULL){
quad = NEW JQuad(texture,offX,offY,width,height);
if(!quad) {
//Probably out of memory. Try again.
resources.Cleanup();
quad = NEW JQuad(texture,offX,offY,width,height);
}
if(!jq)
if(!quad){
if(allocated)
SAFE_DELETE(tq);
return NULL; //Probably a crash.
}
trackedQuads[jq] = resname;
return jq;
}else{
tq->quad = quad;
trackedQuads.push_back(tq);
return tq;
}
else{
//Update JQ's values to what we called this with.
jq->SetTextureRect(offX,offY,width,height);
return jq;
quad->SetTextureRect(offX,offY,width,height);
return tq;
}
return NULL;
}
JQuad * WCachedTexture::GetQuad(float offX, float offY, float width, float height,string resname){
WTrackedQuad * tq = GetTrackedQuad(offX,offY,width,height,resname);
if(tq)
return tq->quad;
return NULL;
}
JQuad * WCachedTexture::GetQuad(string resname){
map<JQuad*,string>::iterator it;
vector<WTrackedQuad*>::iterator it;
std::transform(resname.begin(),resname.end(),resname.begin(),::tolower);
for(it = trackedQuads.begin();it!=trackedQuads.end();it++){
if(it->second == resname){
return it->first;
if((*it) && (*it)->resname == resname){
return (*it)->quad;
}
}
@@ -181,9 +241,9 @@ void WCachedTexture::Refresh(string filename){
else
SAFE_DELETE(old);
for(map<JQuad*,string>::iterator it=trackedQuads.begin();it!=trackedQuads.end();it++){
if(it->first)
it->first->mTex = texture;
for(vector<WTrackedQuad*>::iterator it=trackedQuads.begin();it!=trackedQuads.end();it++){
if((*it) && (*it)->quad)
(*it)->quad->mTex = texture;
}
}
@@ -385,3 +445,35 @@ void WCachedParticles::Nullify(){
if(particles)
particles = NULL;
}
//WTrackedQuad
void WTrackedQuad::Nullify() {
quad = NULL;
}
#if defined DEBUG_CACHE
int WTrackedQuad::totalTracked = 0;
#endif
unsigned long WTrackedQuad::size() {
return sizeof(JQuad);
}
bool WTrackedQuad::isGood(){
return (quad != NULL);
}
WTrackedQuad::WTrackedQuad(string _resname) {
#if defined DEBUG_CACHE
OutputDebugString("Tracked quad created.\n");
totalTracked++;
#endif
quad = NULL; resname = _resname;
}
WTrackedQuad::~WTrackedQuad() {
#if defined DEBUG_CACHE
char buf[512];
totalTracked--;
sprintf(buf,"~WTrackedQuad(). %d left.\n",totalTracked);
OutputDebugString(buf);
#endif
if(quad) SAFE_DELETE(quad);
}

View File

@@ -54,6 +54,7 @@ void WResourceManager::DebugRender(){
#ifdef DEBUG_CACHE
if(debugMessage.size())
font->DrawString(debugMessage.c_str(), SCREEN_WIDTH-10,SCREEN_HEIGHT-25,JGETEXT_RIGHT);
#endif
}
@@ -161,6 +162,11 @@ WResourceManager::WResourceManager(){
WResourceManager::~WResourceManager(){
LOG("==Destroying WResourceManager==");
RemoveAll();
for(vector<WManagedQuad*>::iterator it=managedQuads.begin();it!=managedQuads.end();it++){
WManagedQuad* wm = *it;
SAFE_DELETE(wm);
}
managedQuads.clear();
LOG("==Successfully Destroyed WResourceManager==");
}
@@ -199,10 +205,10 @@ int WResourceManager::CreateQuad(const string &quadName, const string &textureNa
string resname = quadName;
std::transform(resname.begin(),resname.end(),resname.begin(),::tolower);
vector<WManagedQuad>::iterator it;
vector<WManagedQuad*>::iterator it;
int pos = 0;
for(it = managedQuads.begin();it!=managedQuads.end();it++,pos++){
if(it->resname == resname)
if((*it)->resname == resname)
return pos;
}
@@ -216,9 +222,10 @@ int WResourceManager::CreateQuad(const string &quadName, const string &textureNa
JQuad * jq = jtex->GetQuad(x,y,width,height,quadName);
if(jq){
WManagedQuad mq;
mq.resname = resname;
mq.texture = jtex;
WManagedQuad * mq;
mq = NEW WManagedQuad();
mq->resname = resname;
mq->texture = jtex;
managedQuads.push_back(mq);
}
@@ -232,9 +239,9 @@ JQuad * WResourceManager::GetQuad(const string &quadName){
string lookup = quadName;
std::transform(lookup.begin(),lookup.end(),lookup.begin(),::tolower);
for(vector<WManagedQuad>::iterator it=managedQuads.begin();it!=managedQuads.end();it++){
if(it->resname == lookup)
return it->texture->GetQuad(lookup);
for(vector<WManagedQuad*>::iterator it=managedQuads.begin();it!=managedQuads.end();it++){
if((*it)->resname == lookup)
return (*it)->texture->GetQuad(lookup);
}
return NULL;
@@ -244,11 +251,11 @@ JQuad * WResourceManager::GetQuad(int id){
if(id < 0 || id >= (int) managedQuads.size())
return NULL;
WCachedTexture * jtex = managedQuads[id].texture;
WCachedTexture * jtex = managedQuads[id]->texture;
if(!jtex)
return NULL;
return jtex->GetQuad(managedQuads[id].resname);
return jtex->GetQuad(managedQuads[id]->resname);
}
JQuad * WResourceManager::RetrieveTempQuad(string filename){
@@ -265,12 +272,26 @@ JQuad * WResourceManager::RetrieveQuad(string filename, float offX, float offY,
return jq;
}
//Aliases.
if(style == RETRIEVE_VRAM){
submode = submode | TEXTURE_SUB_VRAM;
style = RETRIEVE_LOCK;
}
else if(style == RETRIEVE_THUMB){
submode = submode | TEXTURE_SUB_THUMB;
style = RETRIEVE_NORMAL;
}
//Resname defaults to filename.
if(!resname.size())
resname = filename;
//No quad, but we have a managed texture for this!
WCachedTexture * jtex = textureWCache.Retrieve(filename,style,submode);
WCachedTexture * jtex = NULL;
if(style == RETRIEVE_MANAGE)
jtex = textureWCache.Retrieve(filename,RETRIEVE_MANAGE,submode);
else
jtex = textureWCache.Retrieve(filename,RETRIEVE_NORMAL,submode);
//Somehow, jtex wasn't promoted.
if(style == RETRIEVE_MANAGE && jtex && !jtex->isPermanent())
@@ -278,16 +299,26 @@ JQuad * WResourceManager::RetrieveQuad(string filename, float offX, float offY,
//Make this quad, overwriting any similarly resname'd quads.
if(jtex){
jq = jtex->GetQuad(offX,offY,width,height,resname);
WTrackedQuad * tq = jtex->GetTrackedQuad(offX,offY,width,height,resname);
if(tq == NULL)
return NULL;
if(style == RETRIEVE_MANAGE && resname != ""){
WManagedQuad mq;
mq.resname = resname;
mq.texture = jtex;
WManagedQuad * mq = NEW WManagedQuad();
mq->resname = resname;
mq->texture = jtex;
managedQuads.push_back(mq);
}
return jq;
if(style == RETRIEVE_LOCK)
tq->lock();
else if(style == RETRIEVE_UNLOCK)
tq->unlock();
else if(style == RETRIEVE_MANAGE)
tq->deadbolt();
return tq->quad;
}
//Texture doesn't exist, so no quad.