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


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の割り込みが入って、カウントが途中でリセットされる（期待通りの動作）