Merge pull request #12002 from WenhaiLin/v3-texturecache-unbindfix

Fixed TextureCache::unbindImageAsync fails to unbind all asynchronous callback for a specified bound image.
This commit is contained in:
minggo 2015-05-25 16:29:43 +08:00
commit 273ac5d00a
2 changed files with 59 additions and 32 deletions

View File

@ -115,8 +115,8 @@ void TextureCache::addImageAsync(const std::string &path, const std::function<vo
// lazy init // lazy init
if (_asyncStructQueue == nullptr) if (_asyncStructQueue == nullptr)
{ {
_asyncStructQueue = new queue<AsyncStruct*>(); _asyncStructQueue = new (std::nothrow) deque<AsyncStruct*>();
_imageInfoQueue = new deque<ImageInfo*>(); _imageInfoQueue = new (std::nothrow) deque<ImageInfo*>();
// create a new thread to load images // create a new thread to load images
_loadingThread = new std::thread(&TextureCache::loadImage, this); _loadingThread = new std::thread(&TextureCache::loadImage, this);
@ -135,36 +135,62 @@ void TextureCache::addImageAsync(const std::string &path, const std::function<vo
AsyncStruct *data = new (std::nothrow) AsyncStruct(fullpath, callback); AsyncStruct *data = new (std::nothrow) AsyncStruct(fullpath, callback);
// add async struct into queue // add async struct into queue
_asyncStructQueueMutex.lock(); _asyncMutex.lock();
_asyncStructQueue->push(data); _asyncStructQueue->push_back(data);
_asyncStructQueueMutex.unlock(); _asyncMutex.unlock();
_sleepCondition.notify_one(); _sleepCondition.notify_one();
} }
void TextureCache::unbindImageAsync(const std::string& filename) void TextureCache::unbindImageAsync(const std::string& filename)
{ {
_imageInfoMutex.lock(); std::string fullpath = FileUtils::getInstance()->fullPathForFilename(filename);
if (_imageInfoQueue && !_imageInfoQueue->empty())
_asyncMutex.lock();
if (_asyncStructQueue && !_asyncStructQueue->empty())
{ {
std::string fullpath = FileUtils::getInstance()->fullPathForFilename(filename); for (auto it = _asyncStructQueue->begin(); it != _asyncStructQueue->end(); ++it)
auto found = std::find_if(_imageInfoQueue->begin(), _imageInfoQueue->end(), [&fullpath](ImageInfo* ptr)->bool{ return ptr->asyncStruct->filename == fullpath; });
if (found != _imageInfoQueue->end())
{ {
(*found)->asyncStruct->callback = nullptr; if ((*it)->filename == fullpath)
{
(*it)->callback = nullptr;
}
} }
} }
_imageInfoMutex.unlock();
if (_imageInfoQueue && !_imageInfoQueue->empty())
{
for (auto it = _imageInfoQueue->begin(); it != _imageInfoQueue->end(); ++it)
{
if ((*it)->asyncStruct->filename == fullpath)
{
(*it)->asyncStruct->callback = nullptr;
}
}
}
_asyncMutex.unlock();
} }
void TextureCache::unbindAllImageAsync() void TextureCache::unbindAllImageAsync()
{ {
_imageInfoMutex.lock(); _asyncMutex.lock();
if (_asyncStructQueue && !_asyncStructQueue->empty())
{
for (auto it = _asyncStructQueue->begin(); it != _asyncStructQueue->end(); ++it)
{
(*it)->callback = nullptr;
}
}
if (_imageInfoQueue && !_imageInfoQueue->empty()) if (_imageInfoQueue && !_imageInfoQueue->empty())
{ {
std::for_each(_imageInfoQueue->begin(), _imageInfoQueue->end(), [](ImageInfo* ptr) { ptr->asyncStruct->callback = nullptr; }); for (auto it = _imageInfoQueue->begin(); it != _imageInfoQueue->end(); ++it)
{
(*it)->asyncStruct->callback = nullptr;
}
} }
_imageInfoMutex.unlock(); _asyncMutex.unlock();
} }
void TextureCache::loadImage() void TextureCache::loadImage()
@ -173,11 +199,10 @@ void TextureCache::loadImage()
while (true) while (true)
{ {
std::queue<AsyncStruct*> *pQueue = _asyncStructQueue; _asyncMutex.lock();
_asyncStructQueueMutex.lock(); if (_asyncStructQueue->empty())
if (pQueue->empty())
{ {
_asyncStructQueueMutex.unlock(); _asyncMutex.unlock();
if (_needQuit) { if (_needQuit) {
break; break;
} }
@ -189,9 +214,8 @@ void TextureCache::loadImage()
} }
else else
{ {
asyncStruct = pQueue->front(); asyncStruct = _asyncStructQueue->front();
pQueue->pop(); _asyncMutex.unlock();
_asyncStructQueueMutex.unlock();
} }
Image *image = nullptr; Image *image = nullptr;
@ -200,9 +224,9 @@ void TextureCache::loadImage()
auto it = _textures.find(asyncStruct->filename); auto it = _textures.find(asyncStruct->filename);
if( it == _textures.end() ) if( it == _textures.end() )
{ {
_imageInfoMutex.lock();
ImageInfo *imageInfo; ImageInfo *imageInfo;
size_t pos = 0; size_t pos = 0;
_asyncMutex.lock();
size_t infoSize = _imageInfoQueue->size(); size_t infoSize = _imageInfoQueue->size();
for (; pos < infoSize; pos++) for (; pos < infoSize; pos++)
{ {
@ -210,7 +234,7 @@ void TextureCache::loadImage()
if(imageInfo->asyncStruct->filename.compare(asyncStruct->filename) == 0) if(imageInfo->asyncStruct->filename.compare(asyncStruct->filename) == 0)
break; break;
} }
_imageInfoMutex.unlock(); _asyncMutex.unlock();
if(infoSize == 0 || pos == infoSize) if(infoSize == 0 || pos == infoSize)
generateImage = true; generateImage = true;
} }
@ -224,6 +248,9 @@ void TextureCache::loadImage()
{ {
CC_SAFE_RELEASE(image); CC_SAFE_RELEASE(image);
CCLOG("can not load %s", filename.c_str()); CCLOG("can not load %s", filename.c_str());
_asyncMutex.lock();
_asyncStructQueue->pop_front();
_asyncMutex.unlock();
continue; continue;
} }
} }
@ -234,9 +261,10 @@ void TextureCache::loadImage()
imageInfo->image = image; imageInfo->image = image;
// put the image info into the queue // put the image info into the queue
_imageInfoMutex.lock(); _asyncMutex.lock();
_asyncStructQueue->pop_front();
_imageInfoQueue->push_back(imageInfo); _imageInfoQueue->push_back(imageInfo);
_imageInfoMutex.unlock(); _asyncMutex.unlock();
} }
if(_asyncStructQueue != nullptr) if(_asyncStructQueue != nullptr)
@ -253,16 +281,16 @@ void TextureCache::addImageAsyncCallBack(float dt)
// the image is generated in loading thread // the image is generated in loading thread
std::deque<ImageInfo*> *imagesQueue = _imageInfoQueue; std::deque<ImageInfo*> *imagesQueue = _imageInfoQueue;
_imageInfoMutex.lock(); _asyncMutex.lock();
if (imagesQueue->empty()) if (imagesQueue->empty())
{ {
_imageInfoMutex.unlock(); _asyncMutex.unlock();
} }
else else
{ {
ImageInfo *imageInfo = imagesQueue->front(); ImageInfo *imageInfo = imagesQueue->front();
imagesQueue->pop_front(); imagesQueue->pop_front();
_imageInfoMutex.unlock(); _asyncMutex.unlock();
AsyncStruct *asyncStruct = imageInfo->asyncStruct; AsyncStruct *asyncStruct = imageInfo->asyncStruct;
Image *image = imageInfo->image; Image *image = imageInfo->image;

View File

@ -227,11 +227,10 @@ protected:
std::thread* _loadingThread; std::thread* _loadingThread;
std::queue<AsyncStruct*>* _asyncStructQueue; std::deque<AsyncStruct*>* _asyncStructQueue;
std::deque<ImageInfo*>* _imageInfoQueue; std::deque<ImageInfo*>* _imageInfoQueue;
std::mutex _asyncStructQueueMutex; std::mutex _asyncMutex;
std::mutex _imageInfoMutex;
std::mutex _sleepMutex; std::mutex _sleepMutex;
std::condition_variable _sleepCondition; std::condition_variable _sleepCondition;