#include <iostream>
#include <windows.h>
#include <process.h>
using namespace std;
/*-------------------------------------------------------------------------------
0以上の数値のみを格納するシンプルなリスト
----------------------------------------------------------------------------------*/
class List
{
private:
int size;
int index;
int* buffer;
public:
/*-------------------------------------------------------
リストのサイズを指定して初期化
---------------------------------------------------------*/
List( int size ) {
this->size = size;
this->buffer = new int[ size ];
this->index = -1;
for ( int i = 0; i < this->size; ++i )
this->buffer[ i ] = -1;
}
/*-------------------------------------------------------
バッファを削除する
---------------------------------------------------------*/
~List() {
delete[] buffer;
}
/*-------------------------------------------------------
リストに存在する要素の個数
---------------------------------------------------------*/
int Count() {
return this->index + 1;
}
/*-------------------------------------------------------
データを追加する
戻り値は成功時0・失敗時-1
---------------------------------------------------------*/
int Add( int data ) {
if ( index < size && data >= 0 ) {
this->index++;
this->buffer[ index ] = data;
return 0;
} else {
return -1;
}
}
/*-------------------------------------------------------
指定した位置にある要素を削除する
戻り値は成功時0・失敗時-1
---------------------------------------------------------*/
int Remove( int pos ) {
if ( pos <= index && pos >= 0 ) {
//データを1つ左へ移動して要素を消す
for ( int i = pos; i < index; ++i ) {
this->buffer[ i ] = this->buffer[ i + 1 ];
}
//エラーがわかりやすいように未使用領域の初期化をする
for ( int i = this->index; i < this->size; ++i )
this->buffer[ i ] = -1;
this->index--;
return 0;
} else {
return -1;
}
}
//指定された位置の要素を返す
int& operator[] ( int pos ) {
if ( pos <= index && pos >= 0 ) {
return this->buffer[ pos ];
} else {
cout << "境界エラーが発生しました。" << endl;
exit( 1 );
}
}
};
#define COUNT 10000
List list( COUNT );
/*-------------------------------------------------------------------------------
グローバル変数にしたListに要素を追加する関数
----------------------------------------------------------------------------------*/
DWORD WINAPI Add( PVOID pvParam ) {
for ( int i = 0; i < COUNT; ++i )
list.Add( i );
return 0;
}
/*-------------------------------------------------------------------------------
グローバル変数にしたListから奇数を削除する関数
----------------------------------------------------------------------------------*/
DWORD WINAPI Remove( PVOID pvParam ) {
for ( int i = 1; i <= COUNT / 2; ++i )
list.Remove( i );
return 0;
}
/*-------------------------------------------------------------------------------
メインプログラム
----------------------------------------------------------------------------------*/
int main(void)
{
//スレッドに処理を任せる
cout << "これからリストに" << COUNT << "個の要素を追加し、その後で奇数を消します。" << endl;
cout << "その結果、リスト内には偶数だけが存在する筈です。" << endl;
DWORD dwThreadID;
HANDLE hThreads[ 2 ];
hThreads[ 0 ] = ( HANDLE ) _beginthreadex (
( void * ) NULL,
( unsigned ) 0,
( unsigned (__stdcall *) (void *) ) Add,
( void * ) 0,
( unsigned ) 0,
( unsigned * ) &dwThreadID );
hThreads[ 1 ] = ( HANDLE ) _beginthreadex (
( void * ) NULL,
( unsigned ) 0,
( unsigned (__stdcall *) (void *) ) Remove,
( void * ) 0,
( unsigned ) 0,
( unsigned * ) &dwThreadID );
//全てのスレッドが終了するまで待つ
DWORD dw = WaitForMultipleObjects( 2, hThreads, TRUE, INFINITE );
//全てのスレッドを閉じる
for ( int i = 0; i < 2; ++i )
CloseHandle( hThreads[ i ] );
cout << "処理が終わりましたので結果を表示します。" << endl;
//リスト内の要素を点検
int count = 0;
int errors = 0;
for ( int i = 0; i < list.Count(); ++i ) {
int tmp = list[ i ];
if ( ( tmp % 2 ) != 0 ) {
count++;
}
if ( list[ i ] <= -1 ) {
errors++;
}
}
cout << "奇数が" << count << "個ありました。" << endl;
cout << "破損している要素(値が-1以下のデータ)が" << errors << "個ありました。" << endl;
cout << endl << endl;
return 0;
}
このサンプルは、Add関数でListに数値を追加し、Remove関数でList内から奇数を削除する処理をマルチスレッドで行っています。注目して欲しいところは、「Listの要素が破損する」点です。サンプルのListは非常に単純な作りで、スレッドセーフなものではないので、格納しているデータが整合性のないものになってしまいます。これが並列処理ではスレッドセーフなコンテナを使わなければならない理由です。
インテルTBBのコンテナはスレッドセーフなので、基本的にはデータの整合性は保たれるようになっています。そのため、TBBでプログラミングをする際には必ずインテルTBBのコンテナを使用するべきです。なお、このサンプルはコンテナ以外にも問題がありますが、それは今回の内容と関係がないため解説を省きます。
これで、インテルTBBのコンテナを使用する理由が分かったと思うので、次項からインテルTBBのコンテナを個々に解説します。

