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