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"> /**======================= ...
随机推荐
- [Tailwind] Get started with Tailwindcss
In this lesson, we learn how to generate CSS utility classes from Tailwind's JavaScript config file. ...
- 淘宝数据库OceanBase SQL编译器部分 源代码阅读--生成逻辑计划
淘宝数据库OceanBase SQL编译器部分 源代码阅读--生成逻辑计划 SQL编译解析三部曲分为:构建语法树.生成逻辑计划.指定物理运行计划. 第一步骤,在我的上一篇博客淘宝数据库OceanBas ...
- centos 下 KVM虚拟机的创建、管理与迁移
kvm虚拟机管理 一.环境 role hostname ip OS kvm_server target 192.168.32.40 ...
- oracle 11gR2 如何修改 private ip
1.1 修改 private ip1.1.1 确保crs集群是打开的可以用olsnodes –s 检查集群的状态./olsnodes -sP570a ActiveP570b Active1.1 ...
- notepad++ 查找引用(Find Reference)(适用于c c++及各类脚本比如lua、python等)
在程序开发过程中,程序员经常用到的一个功能就是查找引用(Find Reference),Visual Studio里面的对应功能是“查找所有引用”(Find All References). 我在使用 ...
- js如何计算浮点数
js中浮点型是如何运算的呢? 例如:var a=0.69; 我想得到6.9 直接这样写 var c=a*10; alert(c); 得到结果是:6.8999999999999995 到网上一搜,有 ...
- CentOS7开启网络配置
虚拟机在安装时可以开启网络 如果没有开启的话 可以通过以下操作 ip addr 查看是否开启网络 没有开启的话 cd /etc/sysconfig/network-scripts/ 然后 执行 ls ...
- springboot的常见配置
1.Springboot热部署 热部署的意思就是当任何类发生改变时,通过JVM类加载的方式加载到虚拟机上,这样就不需要我们重启Application类了 做法: 1)添加一个依赖到pom.xml上: ...
- Api接口服务的设计和安全解决方案
这个涉及到两个方面问题:一个是接口访问认证问题,主要解决谁可以使用接口(用户登录验证.来路验证)一个是数据数据传输安全,主要解决接口数据被监听(HTTPS安全传输.敏感内容加密.数字签名) 普通网站应 ...
- JavaScript中数组的迭代方法:forEach、map、filter、reduce、every、some、for in、for of
JavaScript中有非常多数组迭代方法,这里基本上吧所有的都介绍全了,我项目中比较喜欢的是forEach. 7.for in (for-in循环实际是为循环对象而设计的,for in也可以循环数组 ...