concurrent_vector

concurrent_vector<T> は、動的に拡張可能な T 型の配列です。ほかのスレッドをその要素上で操作しているか、自身が拡張しているときに concurrent_vector を安全に拡張できます。安全な同時拡張のため、concurrent_vector には、動的配列の共通使用をサポートするサイズ変更用に、push_backgrow_bygrow_to_at_least の 3 つのメソッドが用意されています。

push_back(x) メソッドは、x を配列に安全に追加します。grow_by(n) メソッドは、T() で初期化した n 個の連続する要素を安全に追加します。どちらのメソッドも、最初に追加した要素を指すイテレーターを返します。各要素は T() で初期化されます。例えば、次のルーチンは C の文字列を共有ベクトルに安全に追加します。

void Append( concurrent_vector<char>& vector, const char* string ) {
    size_t n = strlen(string)+1;
    std::copy( string, string+n, vector.grow_by(n) );
}

関連する grow_to_at_least(n) メソッドは、ベクトルがサイズ n よりも短い場合、ベクトルをそのサイズまで拡張します。これらのメソッドの同時呼び出しは、ベクトルに追加された順に要素を返す必要はありません。

size() メソッドは、push_backgrow_by または grow_to_at_least メソッドによって同時構築中の要素を含む、ベクトル要素の数を返します。concurrent_vector の要素は連続するアドレスにならないため、サンプルでは strcpy とポインターではなく、std::copy とイテレーターを使用しています。イテレーターが end() の値を超えて移動しない限り、concurrent_vector が拡張する間も、安全にイテレーターを使用できます。しかし、イテレーターは同時構築されている要素を参照することがあります。そのため、構築とアクセスを同期させる必要があります。

concurrent_vector<T> は、配列が消去されるまで要素を移動しません。これは、シングルスレッド・コードであっても STL std::vector より利点があります。しかし、concurrent_vectorstd::vector よりもオーバーヘッドが大きくなります。ほかのアクセスを処理する際に動的にサイズを変更する必要がある場合、または要素を移動してはならない場合のみ、concurrent_vector を使用してください。

警告

concurrent_vector の操作は、ベクトルの消去や破棄ではなく、拡張 に関しても並列化セーフです。concurrent_vector で処理を行っているほかの操作がある場合、clear() メソッドを呼び出さないでください。