LoginSignup
6
5

More than 5 years have passed since last update.

メンバ関数がpthreadなクラスを作る練習

Posted at

pthread で動かす関数をクラス化する一例として。とりあえず動かしてみるレベルで。
ついでにmutexを使った同期(排他)の動作も簡単なサンプルで動かしてみる。

  • 実行したいメンバ関数を呼び出すためのstatic関数を一枚噛ませてやる必要あり。
MyPThread.h(cpp)
#include <pthread.h>

class MyPThread
{
public:
    MyPThread();
    virtual ~MyPThread();

    void stop();

    // mutex有無の動作確認用
    void clear();   
    void clearWithMutex();

private:
    static void* launchThread(void *pParam) {
        reinterpret_cast<MyPThread*>(pParam)->execute();
        pthread_exit(NULL);
    }

    void execute();

    pthread_t       tid_;
    pthread_mutex_t mutex_;

    int count_;
    int execCount_;
};

MyPThread.cpp
#include <stdio.h>
#include <unistd.h>
#include "MyPThread.h"

const int kSleepSec  = 1;

MyPThread::MyPThread()
    :tid_()
    ,mutex_()
    ,count_(0)
    ,execCount_(0)
{
    pthread_mutex_init(&mutex_, NULL);

    pthread_create(&tid_, NULL, MyPThread::launchThread, this);
}


MyPThread::~MyPThread()
{
    pthread_cancel(tid_);

    pthread_join(tid_, NULL);

    pthread_mutex_destroy(&mutex_);
}

void
MyPThread::stop()
{
    pthread_cancel(tid_);
}

void
MyPThread::clear()
{
    count_ = 0;

    // 呼び出し元が別スレッドであることの確認のためprint
    printf("%x: clear\n", pthread_self());
}

void
MyPThread::clearWithMutex()
{
    pthread_mutex_lock(&mutex_);
    {
        count_ = 0;
        printf("%x: clear\n", pthread_self());
    }
    pthread_mutex_unlock(&mutex_);
}

void
MyPThread::execute()
{
    pthread_mutex_lock(&mutex_);
    {
        while (execCount_ < 5) {
            pthread_testcancel();

            printf("%x:", pthread_self());
            for (int i=0; i<10; i++) {
                printf("%3d:", count_);
                count_++;
            }
            printf("\n");
            sleep(kSleepSec);

            execCount_++;
        }
    }
    pthread_mutex_unlock(&mutex_);

    printf("finish\n");
}

Qt / Qt Creator使ったのでQCoreApplicationとか残ったままだが、Qtとして動かしてないので削除で問題なしのはず。

環境:Qt 4.8.6/clang, OS X 10.9.2

main.cpp
#include <QCoreApplication>
#include <stdio.h>
#include "MyPThread.h"

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    MyPThread thread;

    int execTimes = 0;
    while (true) {
        if (execTimes > 5) {
            break;
        }

//      thread.clear();             // 非同期版
        thread.clearWithMutex();    // 同期版

        execTimes++;
        sleep(3);
    }

    thread.stop();
    printf("exit\n");

//    return a.exec();  
    return 0;
}

実行結果

mainの以下の部分を切替てそれぞれ実行してみる

main.cpp
thread.clear();         // 非同期版
thread.clearWithMutex();    // 同期版

非同期版

$ ./ThreadTest
7a398310: clear
3187000:  0:  1:  2:  3:  4:  5:  6:  7:  8:  9:
3187000: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19:
3187000: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29:
7a398310: clear
3187000:  0:  1:  2:  3:  4:  5:  6:  7:  8:  9:
3187000: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19:
finish
7a398310: clear
7a398310: clear
7a398310: clear
7a398310: clear
exit

同期版

$ ./ThreadTest 
7a398310: clear
2c81000:  0:  1:  2:  3:  4:  5:  6:  7:  8:  9:
2c81000: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19:
2c81000: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29:
2c81000: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39:
2c81000: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49:
finish
7a398310: clear
7a398310: clear
7a398310: clear
7a398310: clear
7a398310: clear
exit

非同期版は途中でclearの割り込みが入って、カウントが途中でリセットされる(期待通りの動作)

6
5
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
5