【cocos2dx】マルチスレッドを利用した非同期処理

【cocos2dx】マルチスレッドを利用した非同期処理
   

時間のかかる処理はユーザーにストレスを与えます。
できれば上手く工夫をして、重さを感じなくさせるよう工夫することが必要です。
今回は、そのような時に利用できる「マルチスレッド処理」についてcocos2dxで実装をしていきたいと思います。

マルチスレッドとは

プログラムの処理は通常「メインスレッド」で行われます。
コードの書かれた順番に処理を行いますので、例えば、凄く重い処理があれば、その処理が終わらないと次の処理へと移れません。
この部分で、オブジェクトの動きが止まったり、音楽が遅れたりする原因となります。

そこで用意されているのが「メインスレッド」とは別の「スレッド」で処理を行う方法です。
これが「マルチスレッド処理」と言われています。

Xcodeでのスレッドの確認方法

プロジェクトをビルドしている時に、[CPU]を調べると どの「スレッド」を利用しているかわかります。
2014-6-12-ookokkoo

通常の「メインスレッド」のみ。
2014-6-12-odokokkoo


「マルチスレッド」利用時。(Thread7がマルチスレッド)
2014-6-12-ookokko

マルチスレッドの注意点

マルチスレッドを使えば、非同期で処理が行えるので、画面の表示に時間がかかることは無くなります。
しかし、処理自体が軽くなることではないのでCPUに負担をかけます。
アプリが落ちたりする原因にもなるので、注意下さい。

マルチスレッドを実装する

今回は「cocos2dxのレシピ本」を参考にしています。
実践で利用する際には、以下の2点を考えて下さい。
  • メインスレッドで利用する変数
  • マルチスレッドでどのような処理を行うか

まずは、マルチスレッドの処理です。
今回は[POSIXスレッド]を利用しています。
#include <semaphore.h>
#include <unistd.h>


#if CC_TARGET_PLATFORM == CC_PLATFORM_IOS

#define MY_USE_NAMED_SEMAPHORE 1

#else

#define MY_USE_NAMED_SEMAPHORE 0


#endif


#if MY_USE_NAMED_SEMAPHORE

#define MY_SEMAPHORE "cocosThreadSample.sem"

#else

static sem_t s_semaphore;

#endif

static sem_t* s_pSemaphore = NULL;
static pthread_mutex_t s_mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_t s_thread;

struct threadData{
    
    //スレッド作業データ格納配列(__String型)
    cocos2d::Vector<cocos2d::__String*> vec;
};

static threadData *s_threadData;


//マルチスレッド処理
void *thread_function(void *arg){
    
    threadData *td = (threadData*)arg;
    
    
    for (int i = 0; i < 20; i++) {
        
        cocos2d::__String *str = new cocos2d::__String();
        str->initWithFormat("%d",i);
        
        //0.5秒に一度データを投入
        pthread_mutex_lock(&s_mutex);
        td->vec.pushBack(str);
        pthread_mutex_unlock(&s_mutex);
        
        usleep(500000); // wait 0.5sec
        
        
        
    }
        
    sem_post(s_pSemaphore);
    return NULL;
    
}



以下が「メインスレッド」で利用する際の処理の一例です。
「マルチスレッド」で格納した数字をラベルで順番に表示をさせています。
void MultiThreadLayer::startMultiThread(){
    
#if MY_USE_NAMED_SEMAPHORE
    
    s_pSemaphore = sem_open(MY_SEMAPHORE, O_CREAT,0644,0);
    if (s_pSemaphore == SEM_FAILED) {
        
        return;
        
    }
    
#else
    
    if (sem_init(&s_semaphore, 0, 0) < 0) {
        
        return;
        
    }
    
    s_pSemaphore = &s_semaphore;
    
#endif
    

    //スレッド用の作業データを作成
    s_threadData = new threadData();
    
    //マルチスレッド起動
    pthread_mutex_init(&s_mutex, NULL);
    pthread_create(&s_thread, NULL,thread_function, (void*)s_threadData);
    pthread_detach(s_thread);
    
    //スレッド表示ルート開始
    //this->schedule(schedule_selector(MultiThreadLayer::update_therad_progress));
    
    
}

/*
 
 メインスレッドのUpdate(ルート)
 
 */

void MultiThreadLayer::update_therad_progress(float delta){
    
    std::string str = "";
    
    //スレッドからデータを取得
    pthread_mutex_lock(&s_mutex);
    Vector<__String*> _ver  = s_threadData->vec;
    
    for (int i =0; i < _ver.size(); i++) {
       
        //マルチスレッドで格納した__Stringを利用
        __String *ccstr = (__String*)_ver.at(i);
        str += ccstr->getCString();
        
    }
    
    pthread_mutex_unlock(&s_mutex);
    
    
    //ラベル表示
    auto _label = (Label*)this->getChildByTag(1);
    const std::string _current = _label->getString();
    
    if (strcmp(_current.c_str(), str.c_str()) != 0) {
        CCLOG("Update : %s",_current.c_str());
        _label->setString(str);
        
    }
    

    //マルチスレッド終了時の処理
    int ret = sem_trywait(s_pSemaphore);
    if (ret == 0) {
        
        //Updateを止める
        this->unschedule(schedule_selector(MultiThreadLayer::update_therad_progress));
        
        s_threadData->vec.clear(); // removeAllObject
        delete s_threadData;
        s_threadData = NULL;
        
#if MY_NAMED_SEMAPHORE
        
        sem_close(s_pSemaphore);
        sem_unlink(MY_SEMAPHORE);
        
#else
        
        sem_destroy(s_pSemaphore);
        
#endif
        
        
    }
    
    
}

最後に

cocos2dx3.xを利用しているのですが、iOS/Android共にマルチスレッドが実装できました。
ただ、実践でどのように利用するかが見えてきません。
よくあるのが「大量の画像を配置する」「大きいサイズの画像を配置する」など画像と連動して利用するのがいいのかもしれませんね。

Related Posts Plugin for WordPress, Blogger...