Cocos2d-x 3.0多线程异步资源载入
3.0 Final版,其引擎驱动核心依然是一个单线程的“死循环”。一旦某一帧遇到了“大活儿”,比方Size非常大的纹理资源载入或网络IO或大量计算,画面将 不可避免出现卡顿以及响应迟缓的现象。从古老的Win32 GUI编程那时起,Guru们就告诉我们:别堵塞主线程(UI线程),让Worker线程去做那些“大活儿”吧。
- // AppDelegate.cpp
- bool AppDelegate::applicationDidFinishLaunching() {
- … …
- FlashScene* scene = FlashScene::create();
- pDirector->runWithScene(scene);
- return true;
- }
- //FlashScene.h
- struct ResourceLoadIndicator {
- pthread_mutex_t mutex;
- bool load_done;
- void *context;
- };
- class FlashScene : public Scene
- {
- public:
- FlashScene(void);
- ~FlashScene(void);
- virtual bool init();
- CREATE_FUNC(FlashScene);
- bool getResourceLoadIndicator();
- void setResourceLoadIndicator(bool flag);
- private:
- void updateScene(float dt);
- private:
- ResourceLoadIndicator rli;
- };
- // FlashScene.cpp
- bool FlashScene::init()
- {
- bool bRet = false;
- do {
- CC_BREAK_IF(!CCScene::init());
- Size winSize = Director::getInstance()->getWinSize();
- //FlashScene自己的资源仅仅能同步载入了
- Sprite *bg = Sprite::create("FlashSceenBg.png");
- CC_BREAK_IF(!bg);
- bg->setPosition(ccp(winSize.width/2, winSize.height/2));
- this->addChild(bg, 0);
- this->schedule(schedule_selector(FlashScene::updateScene)
- , 0.01f);
- //start the resource loading thread
- rli.load_done = false;
- rli.context = (void*)this;
- pthread_mutex_init(&rli.mutex, NULL);
- pthread_attr_t attr;
- pthread_attr_init(&attr);
- pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
- pthread_t thread;
- pthread_create(&thread, &attr,
- resource_load_thread_entry, &rli);
- bRet=true;
- } while(0);
- return bRet;
- }
- static void* resource_load_thread_entry(void* param)
- {
- AppDelegate *app = (AppDelegate*)Application::getInstance();
- ResourceLoadIndicator *rli = (ResourceLoadIndicator*)param;
- FlashScene *scene = (FlashScene*)rli->context;
- //load music effect resource
- … …
- //init from config files
- … …
- //load images data in worker thread
- SpriteFrameCache::getInstance()->addSpriteFramesWithFile(
- "All-Sprites.plist");
- … …
- //set loading done
- scene->setResourceLoadIndicator(true);
- return NULL;
- }
- bool FlashScene::getResourceLoadIndicator()
- {
- bool flag;
- pthread_mutex_lock(&rli.mutex);
- flag = rli.load_done;
- pthread_mutex_unlock(&rli.mutex);
- return flag;
- }
- void FlashScene::setResourceLoadIndicator(bool flag)
- {
- pthread_mutex_lock(&rli.mutex);
- rli.load_done = flag;
- pthread_mutex_unlock(&rli.mutex);
- return;
- }
- void FlashScene::updateScene(float dt)
- {
- if (getResourceLoadIndicator()) {
- Director::getInstance()->replaceScene(
- WelcomeScene::create());
- }
- }
- threadid=24: thread exiting, not yet detached (count=0)
- threadid=24: thread exiting, not yet detached (count=1)
- threadid=24: native thread exited without detaching
- pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
翻看了一下引擎内核的代码TextureCache::addImageAsync。在线程创建以及线程主函数中也没有发现什么特别的设置。为何内核能够创建线程,我自己创建就会崩溃呢。Debug多个来回,问题似乎聚焦在resource_load_thread_entry中运行的任务。
在我的代码里,我利用SimpleAudioEngine载入了音效资源、利用UserDefault读取了一些持久化的数据,把这两个任务去掉。游戏就会进入到下一个环节而不会崩溃。
Android开发人员官网上有这么一段话:
| All threads are Linux threads, scheduled by the kernel. They're usually started from managed code (using Thread.start), but they can also be created elsewhere and then attached to the JavaVM. For example, a thread started with pthread_create can be attached with the JNI AttachCurrentThread or AttachCurrentThreadAsDaemon functions. Until a thread is attached, it has no JNIEnv, and cannot make JNI calls. |
好,我们来尝试一下,Cocos2d-x引擎提供了一些JniHelper方法,能够方便进行Jni相关操作。
- #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
- #include "platform/android/jni/JniHelper.h"
- #include <jni.h>
- #endif
- static void* resource_load_thread_entry(void* param)
- {
- … …
- JavaVM *vm;
- JNIEnv *env;
- vm = JniHelper::getJavaVM();
- JavaVMAttachArgs thread_args;
- thread_args.name = "Resource Load";
- thread_args.version = JNI_VERSION_1_4;
- thread_args.group = NULL;
- vm->AttachCurrentThread(&env, &thread_args);
- … …
- //Your Jni Calls
- … …
- vm->DetachCurrentThread();
- … …
- return NULL;
- }
| The JavaVM provides the "invocation interface" functions, which allow you to create and destroy a JavaVM. In theory you can have multiple JavaVMs per process, but Android only allows one. The JNIEnv provides most of the JNI functions. Your native functions all receive a JNIEnv as the first argument.
The JNIEnv is used for thread-local storage. For this reason, you cannot share a JNIEnv between threads.
|
- SpriteFrameCache::getInstance()->addSpriteFramesWithFile("All-Sprites.plist");
我们的确发现了一些异常日志:
- libEGL: call to OpenGL ES API with no current context (logged once per thread)
要解决问题就 得查看一下TextureCache::addImageAsync是怎样做的了。
- static void* resource_load_thread_entry(void* param)
- {
- … …
- allSpritesImage = new Image();
- allSpritesImage->initWithImageFile("All-Sprites.png");
- … …
- }
- void FlashScene::updateScene(float dt)
- {
- if (getResourceLoadIndicator()) {
- // construct texture with preloaded images
- Texture2D *allSpritesTexture = TextureCache::getInstance()->
- addImage(allSpritesImage, "All-Sprites.png");
- allSpritesImage->release();
- SpriteFrameCache::getInstance()->addSpriteFramesWithFile(
- "All-Sprites.plist", allSpritesTexture);
- Director::getInstance()->replaceScene(WelcomeScene::create());
- }
- }
Cocos2d-x 3.0多线程异步资源载入的更多相关文章
- Cocos2d-x 3.0多线程异步资源载入代码
// AppDelegate.cpp bool AppDelegate::applicationDidFinishLaunching() { - - FlashScene* scene = Flash ...
- [原]unity3d之http多线程异步资源下载
郑重声明:转载请注明出处 U_探索 本文诞生于乐元素面试过程,被面试官问到AssetBundle多线程异步下载时,愣了半天,同样也被深深的鄙视一回(做了3年多u3d 这个都没用过),所以发誓要实现出来 ...
- 最新版本号cocos2d­2.0­x­2.0.2使用新资源载入策略!不再沿用-hd、-
前段时间cocos2dx更新了最新版本号cocos2d2.0x2.0.2.也从这个版本号開始对于资源载入与管理都改变了策略. 在之前的载入方式都是通过沿用与cocos2d-iphone一样 ...
- 关于Cocos2d-x多线程异步载入资源的问题
我们通常使用CCSpriteFrameCache::sharedSpriteFrameCache()->addSpriteFramesWithFile("xxx.plist" ...
- 可扩展多线程异步Socket服务器框架EMTASS 2.0 (转自:http://blog.csdn.net/hulihui)
可扩展多线程异步Socket服务器框架EMTASS 2.0 (转自:http://blog.csdn.net/hulihui) 0 前言 >>[前言].[第1节].[第2节].[第3节]. ...
- C# 实现的多线程异步Socket数据包接收器框架
转载自Csdn : http://blog.csdn.net/jubao_liang/article/details/4005438 几天前在博问中看到一个C# Socket问题,就想到笔者2004年 ...
- Servlet3.0对异步处理的支持
Servlet工作流程 Servlet 3.0 之前,一个普通 Servlet 的主要工作流程大致如下: Servlet 接收到请求之后,可能需要对请求携带的数据进行一些预处理: 调用业务接口的某些方 ...
- Redis 6.0 多线程重磅发布!!!
Redis 6.0在5.2号这个美好的日子里悄无声息的发布了,这次发布在IT圈犹如一颗惊雷一般,因为这是redis最大的一次改版,首次加入了多线程. 作者Antirez在RC1版本发布时在他的博客写下 ...
- javascript异步延时载入及推断是否已载入js/css文件
<html> <head> <script type="text/javascript"> /**======================= ...
随机推荐
- Scapy介绍官方文档翻译
关于Scapy Scapy为何如此特别 高速的报文设计 一次探測多次解释 Scapy解码而不解释 高速展示Quick demo 合理的默认值 学习Python 本人英文水平有限,翻译不当之处,请參考官 ...
- [HTML 5] Styling with ARIA
See if you can do a better job styling this button using ARIA states. One huge benefit to styling wi ...
- 《UML精粹》第三章 -类图的基本概念
第三章 类图:基本概念 类图可用来描写叙述系统中各种对象的类型.也可描绘出对象间各种各样的静态关系.此外.类图中也能够秀出类的性质(property)与操作(operation),以及可应用到对象间连 ...
- HDU 2196 Computer 树形DP经典题
链接:http://acm.hdu.edu.cn/showproblem.php? pid=2196 题意:每一个电脑都用线连接到了还有一台电脑,连接用的线有一定的长度,最后把全部电脑连成了一棵树,问 ...
- jQuery动画animate()的使用
自己定义动画效果: 使用方法:animate(js对象,运行时间.回调函数): js对象:{ }描写叙述动画运行之后元素的样式 运行时间:毫秒数 回调函数:动画运行结束后要运行的函数 html代码: ...
- [BZOJ 3884][欧拉定理]上帝与集合的正确使用方法
看看我们机房某畸形写的题解:http://blog.csdn.net/sinat_27410769/article/details/46754209 此题为popoQQQ神犇所出,在此orz #inc ...
- android AChartEnginee解说之源代码框架解读
从上周把android ACHartEnginee的源代码check out出来后就一直在看这个东西是怎样使用的,以及底层是怎样实现的,把近期一周对这个东西的了解先发上来,即是给自己做一个总结,也希望 ...
- 2015.04.24,外语,读书笔记-《Word Power Made Easy》 12 “如何奉承朋友” SESSION 34
1.no fatigue indefatigable([indi'fætigәb(ә)l] adj. 不知疲倦的)来自faigue,in-是反义词缀:后缀-able表示able to be,因此ind ...
- Ubuntu桌面基础介绍
1. 目录结构和文件系统 ubuntu的文件系统也是一个又层次的树形结构,文件系统的最上层是 / ,表示根目录,所有其他文件和目录都位于跟目录下,在linux中,一切皆为文件,包括硬盘.分区和拔插介质 ...
- WEEX SDK集成到工程(Integrate to Android) #25
WEEX SDK集成到工程(Integrate to Android) #25 https://github.com/weexteam/article/issues/25