同時に拡張してアクセスできるベクトル用のテンプレート・クラス。
template<typename T, class Alloc=cache_aligned_allocator<T> > class concurrent_vector;
#include "tbb/concurrent_vector.h"
concurrent_vector は、次の機能を備えたコンテナーです。
インデックスによるランダムアクセス。最初の要素のインデックスは 0 です。
複数のスレッドが同時にコンテナーを拡張し、新しい要素を追加できます。
コンテナーの拡張は、既存のイテレーターまたはインデックスを無効にしません。
concurrent_vector は、ISO C++ 標準のコンテナーおよび可逆コンテナーのすべての要件を満たしています。insert() メソッドと erase() メソッドがないため、シーケンス要件は満たしていません。
namespace tbb { template<typename T, typename Alloc=cache_aligned_allocator<T> > class concurrent_vector { public: typedef size_t size_type; typedef allocator-A-rebound-for-T allocator_type; typedef T value_type; typedef ptrdiff_t difference_type; typedef T& reference; typedef const T& const_reference; typedef T* pointer; typedef const T* const_pointer; typedef implementation-defined iterator; typedef implementation-defined const_iterator; typedef implementation-defined reverse_iterator; typedef implementation-defined const_reverse_iterator; // 並列範囲 typedef implementation-defined range_type; typedef implementation-defined const_range_type; range_type range( size_t grainsize ); const_range_type range( size_t grainsize ) const; // コンストラクター explicit concurrent_vector( const allocator_type& a = allocator_type() ); concurrent_vector( const concurrent_vector& x ); template<typename M> concurrent_vector( const concurrent_vector<T, M>& x ); explicit concurrent_vector( size_type n, const T& t = T(), const allocator_type& a = allocator_type() ); template<typename InputIterator> concurrent_vector( InputIterator first, InputIterator last, const allocator_type& a = allocator_type()); // C++11 仕様 concurrent_vector( concurrent_vector&& x); concurrent_vector( concurrent_vector&& x, const allocator_type& a); concurrent_vector( std::initializer_list<T> il, const allocator_type& a = allocator_type() ); // 代入 concurrent_vector& operator=( const concurrent_vector& x ); template<class M> concurrent_vector& operator=( const concurrent_vector<T, M>& x ); void assign( size_type n, const T& t ); template<class InputIterator > void assign( InputIterator first, InputIterator last ); // C++11 仕様 concurrent_vector& operator=( concurrent_vector&& x ); concurrent_vector& operator=( std::initializer_list<T> il ); void assign( std::initializer_list<T> il ); // 同時拡張操作 iterator grow_by( size_type delta ); iterator grow_by( size_type delta, const T& t ); template<typename ForwardIterator> iterator grow_by( ForwardIterator first, ForwardIterator last ); // C++11 仕様 iterator grow_by( std::initializer_list<T>& il ) iterator grow_to_at_least( size_type n ); iterator grow_to_at_least( size_type n, const T& t ); iterator push_back( const T& item ); // C++11 仕様 iterator push_back( T&& item ); template<typename... Args> iterator emplace_back( Args&&... args); // アクセスするアイテム reference operator[]( size_type index ); const_reference operator[]( size_type index ) const; reference at( size_type index ); const_reference at( size_type index ) const; reference front(); const_reference front() const; reference back(); const_reference back() const; // 記憶域 bool empty() const; size_type capacity() const; size_type max_size() const; size_type size() const; allocator_type get_allocator() const; // コンテナー全体で並列でない操作 void reserve( size_type n ); void compact(); void swap( concurrent_vector& vector ); void clear(); ~concurrent_vector(); // イテレーター iterator begin(); iterator end(); const_iterator begin() const; const_iterator end() const; reverse_iterator rbegin(); reverse_iterator rend(); const_reverse_iterator rbegin() const; const_reverse_iterator rend() const; // C++11 拡張 const_iterator cbegin() const; const_iterator cend() const; const_reverse_iterator crbegin() const; const_reverse_iterator crend() const; }; // グローバル関数 template<typename T, class A1, class A2> bool operator==( const concurrent_vector<T, A1>& a, const concurrent_vector<T, A2>& b ); template<typename T, class A1, class A2> bool operator!=( const concurrent_vector<T, A1>& a, const concurrent_vector<T, A2>& b ); template<typename T, class A1, class A2> bool operator<( const concurrent_vector<T, A1>& a, const concurrent_vector<T, A2>& b ); template<typename T, class A1, class A2> bool operator>( const concurrent_vector<T, A1>& a, const concurrent_vector<T, A2>& b ); template<typename T, class A1, class A2> bool operator<=( const concurrent_vector<T, A1>& a, const concurrent_vector<T, A2>& b ); template<typename T, class A1, class A2> bool operator>=( const concurrent_vector<T, A1>& a, const concurrent_vector<T, A2>& b ); template<typename T, class A> void swap( concurrent_vector<T, A>& a, concurrent_vector<T, A>& b); }
allocator_type の再結合は、std::vector の Microsoft® 実装および GNU* 実装に似ています。
同時拡張と理想的な例外の安全性は、根本的に両立しません。しかし、concurrent_vector は、実用レベルでの例外の安全性を提供します。
要素型 T は、次の要件を満たしていなければなりません。
デストラクターは例外をスローしてはなりません。
デフォルト・コンストラクターが例外をスローできる場合、デストラクターは非仮想で、ゼロに設定されたメモリーで正しく動作できなければなりません。
その他の場合のプログラムの動作は不定です。
拡張およびベクトル代入操作は、ベクトルに要素のシーケンスを追加します。例外が発生した場合、ベクトルへの影響はその原因に依存します。
要素のコンストラクターによって例外がスローされた場合、追加されるシーケンスの残りの要素はすべてゼロに設定されます。
その他の場合は、ベクトルのアロケーターによって例外がスローされ、ベクトルが壊れます。追加されるシーケンスの各要素は、次の 3 つの状態のいずれかになります。
ベクトルが壊れた場合、要素のアクセスには注意が必要です。
メソッド at で未割り当ての要素にアクセスすると、std::range_error 例外が発生します。その他のメソッドを使用して未割り当ての要素にアクセスした場合の動作は不定です。
capacity() および size() の値が、予測される値よりも小さくなることがあります。
back() を使用して壊れたベクトルにアクセスした場合の動作は不定です。
ただし、次のことは、ベクトルが壊れていてもいなくても保証されます。
未割り当て要素のインデックスを k とした場合、size()<= capacity()<=k。
拡張操作により size() または capacity() の値が減ることはありません。
同時拡張操作が完了すると、後続の拡張操作が失敗した場合であっても、追加されたシーケンスは有効なままとなり、アクセスできます。
std::vector とは異なり、concurrent_vector は拡張する際に既存の要素を移動しません。コンテナーは、一連の連続した配列を割り当てます。最初の予約、拡張、または代入操作により、最初の配列のサイズが決定します。小さな要素数を初期サイズとして使用すると、キャッシュラインをまたぐフラグメンテーションが生じ、要素へのアクセス時間が増えることがあります。shrink_to_fit() メソッドは、複数の小さな配列を 1 つの連続する配列にマージします。これにより、アクセス時間が向上することがあります。