使用cocos2d-x的人应该都知道CCTextureCache类中有个异步加载图片的方法addImageAsync,也都知道其背后的实现原理肯定是基于多线程实现的,那么其背后的具体实现逻辑具体是怎样的,所以就带着好奇心的去把它研究了下:
先看addImageAsync的实现:
void CCTextureCache::addImageAsync(const char *path, CCObject *target, SEL_CallFuncO selector)
{
#ifdef EMSCRIPTEN//在2.2.2的版本中,不能通过脚本语言(lua和js)异步加载图片(听说qiuck-cocos2d-x实现了用脚本来异步加载图片)
CCLOGWARN("Cannot load image %s asynchronously in Emscripten builds.", path);
return;
#endif // EMSCRIPTEN
CCAssert(path != NULL, "TextureCache: fileimage MUST not be NULL");//要加载的图片的路径不能为空
CCTexture2D *texture = NULL;
// optimization
std::string pathKey = path;//创建字符串pathKey做为字典查询关键字。
pathKey = CCFileUtils::sharedFileUtils()->fullPathForFilename(pathKey.c_str());//取得图片所在位置的全路径名 ,充当字典中的key
texture = (CCTexture2D*)m_pTextures->objectForKey(pathKey.c_str());//先查询一下是否字典里已经有了此纹理。
std::string fullpath = pathKey;//图片所在位置的全路径名
if (texture != NULL)//如果字典存在该纹理图片,则不需要异步加载,直接执行回调函数
{
if (target && selector)
{
(target->*selector)(texture);//执行回调,将纹理作为参数传入
}
return;
}
// lazy init
if (s_pAsyncStructQueue == NULL)//如果是第一次调用多线程载入,创建信号量并进行相应初始化。
{
s_pAsyncStructQueue = new queue<AsyncStruct*>();//创建一个存储异步信息队列
s_pImageQueue = new queue<ImageInfo*>(); //创建一个存储图片信息队列
//线程锁初始化
pthread_mutex_init(&s_asyncStructQueueMutex, NULL);
pthread_mutex_init(&s_ImageInfoMutex, NULL);
pthread_mutex_init(&s_SleepMutex, NULL);
pthread_cond_init(&s_SleepCondition, NULL);
#if (CC_TARGET_PLATFORM != CC_PLATFORM_WINRT) && (CC_TARGET_PLATFORM != CC_PLATFORM_WP8)
pthread_create(&s_loadingThread, NULL, loadImage, NULL); //创建加载线程。
#endif
need_quit = false; //将退出指令设为false。
}
if (0 == s_nAsyncRefCount)//多线程加载图片的引用计数器如果为0,
{//用定时器处理异步加载图片(注意:其中的第三个参数为0,也就意味着这个定时器每帧都会被调用,也就是每帧都会调用一次addImageAsy