以前は、Windowsでは _beginthreadex() 、Linuxでは pthread_create() を利用していました。
共通化出来ない上、C++のクラス内でスレッドを起こす場合は、staticのラッパー関数からスレッド本体の関数を呼ぶ必要があり面倒でした。
その後、C++11で追加されたstd::threadを使えば、これらが解決出来ることを知り、以降はもっぱらこちらを利用しています。
使い方
使い方はシンプルです。 thread をインクルードして、スレッド関数のポインターを引数にしてstd::threadクラスのインスタンスを作成するだけでスレッドを起こすことが出来ます。
終了時はjoin()でスレッド関数の終了待ちをします。
実装例
具体的には以下のように活用しています。WindowsでもLinuxでもビルド可能です。
CTestクラス内でスレッドを起こして一定間隔で変数をインクリメントします。
範囲内で最大の素数を求めるテスト用関数を実行後、結果と共に、その間にスレッドでインクリメントした数を表示します。
test.cpp
//#include <windows.h> // for windows
#include <stdio.h>
#include <unistd.h> // for linux
#include <string.h>
#include <thread>
//------------------------------------------------ Thread class
class CTest1
{
public:
CTest1();
virtual ~CTest1();
typedef struct {
std::thread th;
int nReqQuit;
int nCnt;
} tagClassParameter;
tagClassParameter *CP;
private:
void ThreadFunc(void);
};
CTest1::CTest1()
{
CP = new tagClassParameter;
memset(CP, 0, sizeof(tagClassParameter));
printf("start thread\n");
(CP->th) = std::thread(&CTest1::ThreadFunc, this);
}
CTest1::~CTest1()
{
(CP->nReqQuit) = 1;
(CP->th.join)();
printf("stop thread\n");
}
void CTest1::ThreadFunc(void)
{
while((CP->nReqQuit)==0) {
(CP->nCnt) ++;
usleep(1000); // for linux
//Sleep(1); // for windows
}
(CP->nReqQuit) = 0;
}
//------------------------------------------------ test calculation
int CalcPrime(int nMax)
{
int nNum = 3;
int nRet = 1;
while(nNum<=nMax) {
for(int nLoop=2; nLoop<nNum; nLoop++) {
int nAcm = nNum / nLoop;
nAcm *= nLoop;
if(nAcm==nNum) {
break;
}
if(nNum<=(nLoop+1)) {
nRet = nNum;
}
}
nNum ++;
}
return(nRet);
}
//------------------------------------------------ main function
int main(int argc, char *argv[])
{
CTest1 *ctp = new CTest1;
int nAns = CalcPrime(100000);
printf("nAns=%d nCnt=%d\n", nAns, (ctp->CP->nCnt));
delete ctp;
return(0);
}
実行例
筆者の年代物のポンコツPCにて、最適化を指定しないビルドと実行結果はこちらです。
$ g++ -o test test.cpp
$ ./test
start thread
nAns=99991 nCnt=1351
stop thread
最適化を指定すると多少速くなります。
$ g++ -O2 -o test test.cpp
$ ./test
start thread
nAns=99991 nCnt=983
stop thread