From f7a448814ccb009ffb71e483836c948a6b7a0f22 Mon Sep 17 00:00:00 2001 From: Dhilan007 Date: Mon, 16 Dec 2013 17:12:53 +0800 Subject: [PATCH 1/2] issue #3341:fix Incorrect at TextureCache::addImageAsync for repeatedly execute for the same image --- cocos/2d/CCTextureCache.cpp | 83 ++++++++++++++++++++++++++----------- cocos/2d/CCTextureCache.h | 2 +- 2 files changed, 60 insertions(+), 25 deletions(-) diff --git a/cocos/2d/CCTextureCache.cpp b/cocos/2d/CCTextureCache.cpp index 0557ee9057..1dcf63d684 100644 --- a/cocos/2d/CCTextureCache.cpp +++ b/cocos/2d/CCTextureCache.cpp @@ -112,7 +112,7 @@ void TextureCache::addImageAsync(const std::string &path, Object *target, SEL_Ca if (_asyncStructQueue == NULL) { _asyncStructQueue = new queue(); - _imageInfoQueue = new queue(); + _imageInfoQueue = new deque(); // create a new thread to load images _loadingThread = new std::thread(&TextureCache::loadImage, this); @@ -170,17 +170,40 @@ void TextureCache::loadImage() _asyncStructQueueMutex.unlock(); } - const char *filename = asyncStruct->filename.c_str(); - - // generate image - Image *image = new Image(); - if (image && !image->initWithImageFileThreadSafe(filename)) + Image *image = nullptr; + bool generateImage = false; + + auto it = _textures.find(asyncStruct->filename); + if( it == _textures.end() ) { - CC_SAFE_RELEASE(image); - CCLOG("can not load %s", filename); - continue; + _imageInfoMutex.lock(); + ImageInfo *imageInfo; + unsigned int pos = 0; + unsigned int infoSize = _imageInfoQueue->size(); + for (; pos < infoSize; pos++) + { + imageInfo = (*_imageInfoQueue)[pos]; + if(imageInfo->asyncStruct->filename.compare(asyncStruct->filename)) + break; + } + _imageInfoMutex.unlock(); + if(infoSize > 0 && pos < infoSize) + generateImage = true; } + if (generateImage) + { + const char *filename = asyncStruct->filename.c_str(); + // generate image + image = new Image(); + if (image && !image->initWithImageFileThreadSafe(filename)) + { + CC_SAFE_RELEASE(image); + CCLOG("can not load %s", filename); + continue; + } + } + // generate image info ImageInfo *imageInfo = new ImageInfo(); imageInfo->asyncStruct = asyncStruct; @@ -188,7 +211,7 @@ void TextureCache::loadImage() // put the image info into the queue _imageInfoMutex.lock(); - _imageInfoQueue->push(imageInfo); + _imageInfoQueue->push_back(imageInfo); _imageInfoMutex.unlock(); } @@ -204,7 +227,7 @@ void TextureCache::loadImage() void TextureCache::addImageAsyncCallBack(float dt) { // the image is generated in loading thread - std::queue *imagesQueue = _imageInfoQueue; + std::deque *imagesQueue = _imageInfoQueue; _imageInfoMutex.lock(); if (imagesQueue->empty()) @@ -214,7 +237,7 @@ void TextureCache::addImageAsyncCallBack(float dt) else { ImageInfo *imageInfo = imagesQueue->front(); - imagesQueue->pop(); + imagesQueue->pop_front(); _imageInfoMutex.unlock(); AsyncStruct *asyncStruct = imageInfo->asyncStruct; @@ -224,28 +247,40 @@ void TextureCache::addImageAsyncCallBack(float dt) SEL_CallFuncO selector = asyncStruct->selector; const char* filename = asyncStruct->filename.c_str(); - // generate texture in render thread - Texture2D *texture = new Texture2D(); + Texture2D *texture = nullptr; + if (image) + { + // generate texture in render thread + texture = new Texture2D(); - texture->initWithImage(image); + texture->initWithImage(image); #if CC_ENABLE_CACHE_TEXTURE_DATA - // cache the texture file name - VolatileTextureMgr::addImageTexture(texture, filename); + // cache the texture file name + VolatileTextureMgr::addImageTexture(texture, filename); #endif - // cache the texture. retain it, since it is added in the map - _textures.insert( std::make_pair(filename, texture) ); - texture->retain(); - - texture->autorelease(); + // cache the texture. retain it, since it is added in the map + _textures.insert( std::make_pair(filename, texture) ); + texture->retain(); + texture->autorelease(); + } + else + { + auto it = _textures.find(asyncStruct->filename); + if(it != _textures.end()) + texture = it->second; + } + if (target && selector) { (target->*selector)(texture); target->release(); } - - image->release(); + if(image) + { + image->release(); + } delete asyncStruct; delete imageInfo; diff --git a/cocos/2d/CCTextureCache.h b/cocos/2d/CCTextureCache.h index 3e63a9f8c3..40aaf7be9a 100644 --- a/cocos/2d/CCTextureCache.h +++ b/cocos/2d/CCTextureCache.h @@ -192,7 +192,7 @@ protected: std::thread* _loadingThread; std::queue* _asyncStructQueue; - std::queue* _imageInfoQueue; + std::deque* _imageInfoQueue; std::mutex _asyncStructQueueMutex; std::mutex _imageInfoMutex; From 649e6b8065f6f63f1e0d158901b12c60ea001ecd Mon Sep 17 00:00:00 2001 From: LinWenhai Date: Tue, 17 Dec 2013 16:04:48 +0800 Subject: [PATCH 2/2] use size_t replace unsigned int for record redeque::size returned value. --- cocos/2d/CCTextureCache.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cocos/2d/CCTextureCache.cpp b/cocos/2d/CCTextureCache.cpp index 1dcf63d684..3ea86701ee 100644 --- a/cocos/2d/CCTextureCache.cpp +++ b/cocos/2d/CCTextureCache.cpp @@ -178,8 +178,8 @@ void TextureCache::loadImage() { _imageInfoMutex.lock(); ImageInfo *imageInfo; - unsigned int pos = 0; - unsigned int infoSize = _imageInfoQueue->size(); + size_t pos = 0; + size_t infoSize = _imageInfoQueue->size(); for (; pos < infoSize; pos++) { imageInfo = (*_imageInfoQueue)[pos];