concurrent_vector是一个动态可增长的数字,当其他线程对其中的元素操作时,可安全push元素到concurrent_vector,对于安全并行增加元素,concurrent_vector有3个方法支持动态数组的使用:push_back, grow_by以及grow_to_at_least。
方法push_back(x)安全把x赋给array,方法grow_by(n)安全赋值n个连续的元素,利用T()来初始化,这2个方法返回一个迭代器,指向第一个元素,每个元素使用T()来初始化,例如,下面程序安全的把C风格的字符串赋给一个共享的vector中:
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)增加vector到n,当它较短时。
方法size()返回vector的元素数量,它可能包括仍然同步构建的元素,通过方法push_back, grow_by或者grow_to_at_least。这个例子使用std::copy和iterators,而不是strcpy和pointers,因为concurrent_vector里的元素不可能是连续寻址,当concurrent_vector正在增加时,使用iterators是安全的,只要iterators没有遭遇end()。然而,iterator可能引用一个遭受并行建设的元素,你一定要同步建设和访问。
concurrent_vector从来没有移除元素直到array被clear掉。
注意:当concurrent_vector增加时,对concurrent_vector操作是安全的,clear或者摧毁一个vector不是安全的,如果有其他对concurrent_vector的操作不要调用方法clear()。
有时一个线程一定等待一个元素v[i],这个元素由其他线程同步添加:
一个好的方法实现步骤2是等待这个元素的atomic flag变成non-zero,为了确保flag是zero,需要做:
下面是一个例子,vector元素是一个atomic指针,假设添加到vector的指针是non-NULL:
#include tbb/compat/thread
#include tbb/tbb_allocator.h // zero_allocator defined here
#include tbb/atomic.h
#include tbb/concurrent_vector.h
using namespace tbb;
typedef concurrent_vector, zero_allocator > >
FooVector;
Foo* FetchElement( const FooVector& v, size_t i ) {
// Wait for ith element to be allocated
while( i>=v.size() )
std::this_thread::yield();
// Wait for ith element to be constructed
while( v[i]==NULL )
std::this_thread::yield();
return v[i];
}
通常,这个flag一定是atomic类型,目的确保适当的内容一致性。