tbb::internal::concurrent_vector_base_v3 Class Reference
Containers

Base class of concurrent vector implementation. More...

`#include <concurrent_vector.h>`

Inheritance diagram for tbb::internal::concurrent_vector_base_v3:
Collaboration diagram for tbb::internal::concurrent_vector_base_v3:

## Classes

class | helper
struct | internal_segments_table
| Internal structure for compact() More...
struct | segment_allocated
struct | segment_allocation_failed
struct | segment_not_used
class | segment_t
class | segment_value_t

## Protected Types

enum | { default_initial_segments = 1 , pointers_per_short_table = 3 , pointers_per_long_table = sizeof(segment_index_t) * 8 }
typedef size_t | segment_index_t
typedef size_t | size_type
typedef void(__TBB_EXPORTED_FUNC * | internal_array_op1) (void *begin, size_type n)
| An operation on an n-element array starting at begin. More...
typedef void(__TBB_EXPORTED_FUNC * | internal_array_op2) (void *dst, const void *src, size_type n)
| An operation on n-element destination array and n-element source array. More...

## Protected Member Functions

| concurrent_vector_base_v3 ()
__TBB_EXPORTED_METHOD | ~concurrent_vector_base_v3 ()
void __TBB_EXPORTED_METHOD | internal_reserve (size_type n, size_type element_size, size_type max_size)
size_type __TBB_EXPORTED_METHOD | internal_capacity () const
void | internal_grow (size_type start, size_type finish, size_type element_size, internal_array_op2 init, const void *src)
size_type __TBB_EXPORTED_METHOD | internal_grow_by (size_type delta, size_type element_size, internal_array_op2 init, const void *src)
void *__TBB_EXPORTED_METHOD | internal_push_back (size_type element_size, size_type &index)
segment_index_t __TBB_EXPORTED_METHOD | internal_clear (internal_array_op1 destroy)
void *__TBB_EXPORTED_METHOD | internal_compact (size_type element_size, void *table, internal_array_op1 destroy, internal_array_op2 copy)
void __TBB_EXPORTED_METHOD | internal_copy (const concurrent_vector_base_v3 &src, size_type element_size, internal_array_op2 copy)
void __TBB_EXPORTED_METHOD | internal_assign (const concurrent_vector_base_v3 &src, size_type element_size, internal_array_op1 destroy, internal_array_op2 assign, internal_array_op2 copy)
void __TBB_EXPORTED_METHOD | internal_throw_exception (size_type) const
| Obsolete. More...
void __TBB_EXPORTED_METHOD | internal_swap (concurrent_vector_base_v3 &v)
void __TBB_EXPORTED_METHOD | internal_resize (size_type n, size_type element_size, size_type max_size, const void *src, internal_array_op1 destroy, internal_array_op2 init)
size_type __TBB_EXPORTED_METHOD | internal_grow_to_at_least_with_result (size_type new_size, size_type element_size, internal_array_op2 init, const void *src)
void __TBB_EXPORTED_METHOD | internal_grow_to_at_least (size_type new_size, size_type element_size, internal_array_op2 init, const void *src)
| Deprecated entry point for backwards compatibility to TBB 2.1. More...

## Static Protected Member Functions

static segment_index_t | segment_index_of (size_type index)
static segment_index_t | segment_base (segment_index_t k)
static segment_index_t | segment_base_index_of (segment_index_t &index)
static size_type | segment_size (segment_index_t k)
static bool | is_first_element_in_segment (size_type element_index)

## Protected Attributes

void *(* | vector_allocator_ptr )(concurrent_vector_base_v3 &, size_t)
| allocator function pointer More...
atomic< size_type > | my_first_block
| count of segments in the first block More...
atomic< size_type > | my_early_size
| Requested size of vector. More...
atomic< segment_t * > | my_segment
| Pointer to the segments table. More...
segment_t | my_storage [pointers_per_short_table]
| embedded storage of segment pointers More...

## Friends

class | helper
template<typename Container , typename Value >
class | vector_iterator
void | enforce_segment_allocated (segment_value_t const &s, internal::exception_id exception=eid_bad_last_alloc)
void | swap (segment_t &, segment_t &) __TBB_NOEXCEPT(true)

## Detailed Description

Base class of concurrent vector implementation.

Definition at line 83 of file concurrent_vector.h.

## Member Typedef Documentation

## internal_array_op1

typedef void(__TBB_EXPORTED_FUNC * tbb::internal::concurrent_vector_base_v3::internal_array_op1) (void *begin, size_type n)

protected

An operation on an n-element array starting at begin.

Definition at line 243 of file concurrent_vector.h.

## internal_array_op2

typedef void(__TBB_EXPORTED_FUNC * tbb::internal::concurrent_vector_base_v3::internal_array_op2) (void *dst, const void *src, size_type n)

protected

An operation on n-element destination array and n-element source array.

Definition at line 246 of file concurrent_vector.h.

## segment_index_t

typedef size_t tbb::internal::concurrent_vector_base_v3::segment_index_t

protected

Definition at line 87 of file concurrent_vector.h.

## size_type

typedef size_t tbb::internal::concurrent_vector_base_v3::size_type

protected

Definition at line 88 of file concurrent_vector.h.

## Member Enumeration Documentation

## anonymous enum

anonymous enum

protected

Enumerator
default_initial_segments |
pointers_per_short_table | Number of slots for segment pointers inside the class.
pointers_per_long_table |

Definition at line 91 of file concurrent_vector.h.

{
// Size constants
default_initial_segments = 1, // 2 initial items
pointers_per_short_table = 3, // to fit into 8 words of entire structure
pointers_per_long_table = sizeof(segment_index_t) * 8 // one segment per bit
};
tbb::internal::concurrent_vector_base_v3::segment_index_t
size_t segment_index_t
Definition: concurrent_vector.h:87
tbb::internal::concurrent_vector_base_v3::pointers_per_short_table
@ pointers_per_short_table
Number of slots for segment pointers inside the class.
Definition: concurrent_vector.h:95
tbb::internal::concurrent_vector_base_v3::pointers_per_long_table
@ pointers_per_long_table
Definition: concurrent_vector.h:96
tbb::internal::concurrent_vector_base_v3::default_initial_segments
@ default_initial_segments
Definition: concurrent_vector.h:93

## Constructor & Destructor Documentation

## concurrent_vector_base_v3()

tbb::internal::concurrent_vector_base_v3::concurrent_vector_base_v3 | ( |  | ) |

inline protected

Definition at line 194 of file concurrent_vector.h.

{
//Here the semantic is intentionally relaxed.
//The reason this is next:
//Object that is in middle of construction (i.e. its constructor is not yet finished)
//cannot be used concurrently until the construction is finished.
//Thus to flag other threads that construction is finished, some synchronization with
//acquire-release semantic should be done by the (external) code that uses the vector.
//So, no need to do the synchronization inside the vector.
my_early_size.store<relaxed>(0);
my_first_block.store<relaxed>(0); // here is not default_initial_segments
my_segment.store<relaxed>(my_storage);
}
tbb::relaxed
@ relaxed
No ordering.
Definition: atomic.h:61
tbb::internal::concurrent_vector_base_v3::my_early_size
atomic< size_type > my_early_size
Requested size of vector.
Definition: concurrent_vector.h:184
tbb::internal::concurrent_vector_base_v3::my_segment
atomic< segment_t * > my_segment
Pointer to the segments table.
Definition: concurrent_vector.h:187
tbb::internal::concurrent_vector_base_v3::my_first_block
atomic< size_type > my_first_block
count of segments in the first block
Definition: concurrent_vector.h:181
tbb::internal::concurrent_vector_base_v3::my_storage
segment_t my_storage[pointers_per_short_table]
embedded storage of segment pointers
Definition: concurrent_vector.h:190

References my_early_size, my_first_block, my_segment, my_storage, and tbb::relaxed.

## ~concurrent_vector_base_v3()

tbb::internal::concurrent_vector_base_v3::~concurrent_vector_base_v3 | ( |  | ) |

protected

Definition at line 313 of file concurrent_vector.cpp.

{
segment_t* s = my_segment;
if( s != my_storage ) {
#if TBB_USE_ASSERT
//to please assert in segment_t destructor
std::fill_n(my_storage,size_t(pointers_per_short_table),segment_t());
#endif /* TBB_USE_ASSERT */
#if TBB_USE_DEBUG
for( segment_index_t i = 0; i < pointers_per_long_table; i++)
__TBB_ASSERT( my_segment[i].load<relaxed>() != segment_allocated(), "Segment should have been freed. Please recompile with new TBB before using exceptions.");
#endif
my_segment = my_storage;
NFS_Free( s );
}
}
__TBB_ASSERT
#define __TBB_ASSERT(predicate, comment)
No-op version of __TBB_ASSERT.
Definition: tbb_stddef.h:165
s
void const char const char int ITT_FORMAT __itt_group_sync s
Definition: ittnotify_static.h:91
tbb::internal::NFS_Free
void __TBB_EXPORTED_FUNC NFS_Free(void *)
Free memory allocated by NFS_Allocate.
Definition: cache_aligned_allocator.cpp:198

References __TBB_ASSERT, my_segment, my_storage, tbb::internal::NFS_Free(), pointers_per_long_table, pointers_per_short_table, and s.

Here is the call graph for this function:

## Member Function Documentation

## internal_assign()

void tbb::internal::concurrent_vector_base_v3::internal_assign | ( | const concurrent_vector_base_v3 & | src,
|  | size_type | element_size,
|  | internal_array_op1 | destroy,
|  | internal_array_op2 | assign,
|  | internal_array_op2 | copy
| ) |  |

protected

Definition at line 376 of file concurrent_vector.cpp.

{
size_type n = src.my_early_size;
while( my_early_size>n ) { // TODO: improve
segment_index_t k = segment_index_of( my_early_size-1 );
size_type b=segment_base(k);
size_type new_end = b>=n ? b : n;
__TBB_ASSERT( my_early_size>new_end, NULL );
enforce_segment_allocated(my_segment[k].load<relaxed>()); //if vector was broken before
// destructors are supposed to not throw any exceptions
destroy( my_segment[k].load<relaxed>().pointer<char>() + element_size*(new_end-b), my_early_size-new_end );
my_early_size = new_end;
}
size_type dst_initialized_size = my_early_size;
my_early_size = n;
helper::assign_first_segment_if_necessary(*this, segment_index_of(n));
size_type b;
for( segment_index_t k=0; (b=segment_base(k))<n; ++k ) {
if( (src.my_segment.load<acquire>() == src.my_storage && k >= pointers_per_short_table)
|| src.my_segment[k].load<relaxed>() != segment_allocated() ) { // if source is damaged
my_early_size = b; break; // TODO: it may cause undestructed items
}
helper::extend_table_if_necessary(*this, k, 0);
if( my_segment[k].load<relaxed>() == segment_not_used())
helper::enable_segment(*this, k, element_size);
else
enforce_segment_allocated(my_segment[k].load<relaxed>());
size_type m = k? segment_size(k) : 2;
if( m > n-b ) m = n-b;
size_type a = 0;
if( dst_initialized_size>b ) {
a = dst_initialized_size-b;
if( a>m ) a = m;
assign( my_segment[k].load<relaxed>().pointer<void>(), src.my_segment[k].load<relaxed>().pointer<void>(), a );
m -= a;
a *= element_size;
}
if( m>0 )
copy( my_segment[k].load<relaxed>().pointer<char>() + a, src.my_segment[k].load<relaxed>().pointer<char>() + a, m );
}
__TBB_ASSERT( src.my_early_size==n, "detected use of concurrent_vector::operator= with right side that was concurrently modified" );
}
tbb::acquire
@ acquire
Acquire.
Definition: atomic.h:57
tbb::internal::concurrent_vector_base_v3::size_type
size_t size_type
Definition: concurrent_vector.h:88
tbb::internal::concurrent_vector_base_v3::segment_index_of
static segment_index_t segment_index_of(size_type index)
Definition: concurrent_vector.h:214
tbb::internal::concurrent_vector_base_v3::segment_size
static size_type segment_size(segment_index_t k)
Definition: concurrent_vector.h:228
tbb::internal::concurrent_vector_base_v3::segment_base
static segment_index_t segment_base(segment_index_t k)
Definition: concurrent_vector.h:218
tbb::internal::concurrent_vector_base_v3::enforce_segment_allocated
friend void enforce_segment_allocated(segment_value_t const &s, internal::exception_id exception=eid_bad_last_alloc)
Definition: concurrent_vector.h:121
tbb::internal::concurrent_vector_base_v3::helper::extend_table_if_necessary
static void extend_table_if_necessary(concurrent_vector_base_v3 &v, size_type k, size_type start)
Definition: concurrent_vector.cpp:92
tbb::internal::concurrent_vector_base_v3::helper::assign_first_segment_if_necessary
static void assign_first_segment_if_necessary(concurrent_vector_base_v3 &v, segment_index_t k)
assign first segment size. k - is index of last segment to be allocated, not a count of segments
Definition: concurrent_vector.cpp:60
tbb::internal::concurrent_vector_base_v3::helper::enable_segment
static size_type enable_segment(concurrent_vector_base_v3 &v, size_type k, size_type element_size, bool mark_as_not_used_on_failure=false)
Definition: concurrent_vector.cpp:222

References __TBB_ASSERT, tbb::acquire, tbb::internal::concurrent_vector_base_v3::helper::assign_first_segment_if_necessary(), tbb::internal::concurrent_vector_base_v3::helper::enable_segment(), enforce_segment_allocated, tbb::internal::concurrent_vector_base_v3::helper::extend_table_if_necessary(), my_early_size, my_segment, my_storage, pointers_per_short_table, tbb::relaxed, segment_base(), segment_index_of(), and segment_size().

Referenced by tbb::concurrent_vector< T, A >::operator=().

Here is the call graph for this function:
Here is the caller graph for this function:

## internal_capacity()

concurrent_vector_base_v3::size_type tbb::internal::concurrent_vector_base_v3::internal_capacity | ( |  | ) | const

protected

Definition at line 329 of file concurrent_vector.cpp.

{
return segment_base( helper::find_segment_end(*this) );
}
tbb::internal::concurrent_vector_base_v3::helper::find_segment_end
static size_type find_segment_end(const concurrent_vector_base_v3 &v)
Definition: concurrent_vector.cpp:49

References tbb::internal::concurrent_vector_base_v3::helper::find_segment_end(), and segment_base().

Referenced by tbb::concurrent_vector< T, A >::capacity(), internal_grow_to_at_least_with_result(), and tbb::concurrent_vector< T, A >::size().

Here is the call graph for this function:
Here is the caller graph for this function:

## internal_clear()

concurrent_vector_base_v3::segment_index_t tbb::internal::concurrent_vector_base_v3::internal_clear | ( | internal_array_op1 | destroy | ) |

protected

Definition at line 501 of file concurrent_vector.cpp.

{
__TBB_ASSERT( my_segment, NULL );
size_type j = my_early_size;
my_early_size = 0;
helper for_each(my_segment, my_first_block, 0, 0, 0, j); // element_size is safe to be zero if 'start' is zero
j = for_each.apply( helper::destroy_body(destroy) );
size_type i = helper::find_segment_end(*this);
return j < i? i : j+1;
}
tbb::internal::concurrent_vector_base_v3::helper
friend class helper
Definition: concurrent_vector.h:276

References __TBB_ASSERT, tbb::internal::concurrent_vector_base_v3::helper::apply(), tbb::internal::concurrent_vector_base_v3::helper::find_segment_end(), my_early_size, my_first_block, and my_segment.

Referenced by tbb::concurrent_vector< T, A >::clear(), tbb::concurrent_vector< T, A >::concurrent_vector(), tbb::concurrent_vector< T, A >::operator=(), and tbb::concurrent_vector< T, A >::~concurrent_vector().

Here is the call graph for this function:
Here is the caller graph for this function:

## internal_compact()

void * tbb::internal::concurrent_vector_base_v3::internal_compact | ( | size_type | element_size,
|  | void * | table,
|  | internal_array_op1 | destroy,
|  | internal_array_op2 | copy
| ) |  |

protected

Definition at line 511 of file concurrent_vector.cpp.

{
const size_type my_size = my_early_size;
const segment_index_t k_end = helper::find_segment_end(*this); // allocated segments
const segment_index_t k_stop = my_size? segment_index_of(my_size-1) + 1 : 0; // number of segments to store existing items: 0=>0; 1,2=>1; 3,4=>2; [5-8]=>3;..
const segment_index_t first_block = my_first_block; // number of merged segments, getting values from atomics
segment_index_t k = first_block;
if(k_stop < first_block)
k = k_stop;
else
while (k < k_stop && helper::incompact_predicate(segment_size( k ) * element_size) ) k++;
if(k_stop == k_end && k == first_block)
return NULL;
segment_t *const segment_table = my_segment;
internal_segments_table &old = *static_cast<internal_segments_table*>( table );
//this call is left here for sake of backward compatibility, and as a placeholder for table initialization
std::fill_n(old.table,sizeof(old.table)/sizeof(old.table[0]),segment_t());
old.first_block=0;
if ( k != first_block && k ) // first segment optimization
{
// exception can occur here
void *seg = helper::allocate_segment(*this, segment_size(k));
old.table[0].store<relaxed>(seg);
old.first_block = k; // fill info for freeing new segment if exception occurs
// copy items to the new segment
size_type my_segment_size = segment_size( first_block );
for (segment_index_t i = 0, j = 0; i < k && j < my_size; j = my_segment_size) {
__TBB_ASSERT( segment_table[i].load<relaxed>() == segment_allocated(), NULL);
void *s = static_cast<void*>(
static_cast<char*>(seg) + segment_base(i)*element_size );
//TODO: refactor to use std::min
if(j + my_segment_size >= my_size) my_segment_size = my_size - j;
__TBB_TRY { // exception can occur here
copy( s, segment_table[i].load<relaxed>().pointer<void>(), my_segment_size );
} __TBB_CATCH(...) { // destroy all the already copied items
helper for_each(&old.table[0], old.first_block, element_size,
0, 0, segment_base(i)+ my_segment_size);
for_each.apply( helper::destroy_body(destroy) );
__TBB_RETHROW();
}
my_segment_size = i? segment_size( ++i ) : segment_size( i = first_block );
}
// commit the changes
std::copy(segment_table,segment_table + k,old.table);
for (segment_index_t i = 0; i < k; i++) {
segment_table[i].store<relaxed>(static_cast<void*>(
static_cast<char*>(seg) + segment_base(i)*element_size ));
}
old.first_block = first_block; my_first_block = k; // now, first_block != my_first_block
// destroy original copies
my_segment_size = segment_size( first_block ); // old.first_block actually
for (segment_index_t i = 0, j = 0; i < k && j < my_size; j = my_segment_size) {
if(j + my_segment_size >= my_size) my_segment_size = my_size - j;
// destructors are supposed to not throw any exceptions
destroy( old.table[i].load<relaxed>().pointer<void>(), my_segment_size );
my_segment_size = i? segment_size( ++i ) : segment_size( i = first_block );
}
}
// free unnecessary segments allocated by reserve() call
if ( k_stop < k_end ) {
old.first_block = first_block;
std::copy(segment_table+k_stop, segment_table+k_end, old.table+k_stop );
std::fill_n(segment_table+k_stop, (k_end-k_stop), segment_t());
if( !k ) my_first_block = 0;
}
return table;
}
__TBB_CATCH
#define __TBB_CATCH(e)
Definition: tbb_stddef.h:284
__TBB_TRY
#define __TBB_TRY
Definition: tbb_stddef.h:283
__TBB_RETHROW
#define __TBB_RETHROW()
Definition: tbb_stddef.h:286
tbb::internal::concurrent_vector_base_v3::helper::allocate_segment
static void * allocate_segment(concurrent_vector_base_v3 &v, size_type n)
Definition: concurrent_vector.cpp:75
tbb::internal::concurrent_vector_base_v3::helper::incompact_predicate
static bool incompact_predicate(size_type size)
Definition: concurrent_vector.cpp:45

References __TBB_ASSERT, __TBB_CATCH, __TBB_RETHROW, __TBB_TRY, tbb::internal::concurrent_vector_base_v3::helper::allocate_segment(), tbb::internal::concurrent_vector_base_v3::helper::apply(), tbb::internal::concurrent_vector_base_v3::helper::find_segment_end(), tbb::internal::concurrent_vector_base_v3::internal_segments_table::first_block, tbb::internal::concurrent_vector_base_v3::helper::incompact_predicate(), tbb::internal::concurrent_vector_base_v3::segment_t::load(), my_early_size, my_first_block, my_segment, tbb::relaxed, s, segment_base(), segment_index_of(), segment_size(), tbb::internal::concurrent_vector_base_v3::segment_t::store(), and tbb::internal::concurrent_vector_base_v3::internal_segments_table::table.

Here is the call graph for this function:

## internal_copy()

void tbb::internal::concurrent_vector_base_v3::internal_copy | ( | const concurrent_vector_base_v3 & | src,
|  | size_type | element_size,
|  | internal_array_op2 | copy
| ) |  |

protected

Definition at line 356 of file concurrent_vector.cpp.

{
size_type n = src.my_early_size;
__TBB_ASSERT( my_segment == my_storage, NULL);
if( n ) {
helper::assign_first_segment_if_necessary(*this, segment_index_of(n-1));
size_type b;
for( segment_index_t k=0; (b=segment_base(k))<n; ++k ) {
if( (src.my_segment.load<acquire>() == src.my_storage && k >= pointers_per_short_table)
|| (src.my_segment[k].load<relaxed>() != segment_allocated())) {
my_early_size = b; break;
}
helper::extend_table_if_necessary(*this, k, 0);
size_type m = helper::enable_segment(*this, k, element_size);
if( m > n-b ) m = n-b;
my_early_size = b+m;
copy( my_segment[k].load<relaxed>().pointer<void>(), src.my_segment[k].load<relaxed>().pointer<void>(), m );
}
}
}

References __TBB_ASSERT, tbb::acquire, tbb::internal::concurrent_vector_base_v3::helper::assign_first_segment_if_necessary(), tbb::internal::concurrent_vector_base_v3::helper::enable_segment(), tbb::internal::concurrent_vector_base_v3::helper::extend_table_if_necessary(), my_early_size, my_segment, my_storage, pointers_per_short_table, tbb::relaxed, segment_base(), and segment_index_of().

Referenced by tbb::concurrent_vector< T, A >::concurrent_vector().

Here is the call graph for this function:
Here is the caller graph for this function:

## internal_grow()

void tbb::internal::concurrent_vector_base_v3::internal_grow | ( | size_type | start,
|  | size_type | finish,
|  | size_type | element_size,
|  | internal_array_op2 | init,
|  | const void * | src
| ) |  |

protected

Definition at line 473 of file concurrent_vector.cpp.

{
__TBB_ASSERT( start<finish, "start must be less than finish" );
segment_index_t k_start = segment_index_of(start), k_end = segment_index_of(finish-1);
helper::assign_first_segment_if_necessary(*this, k_end);
helper::extend_table_if_necessary(*this, k_end, start);
helper range(my_segment, my_first_block, element_size, k_start, start, finish);
for(; k_end > k_start && k_end >= range.first_block; --k_end ) // allocate segments in reverse order
helper::acquire_segment(*this, k_end, element_size, true/*for k_end>k_start*/);
for(; k_start <= k_end; ++k_start ) // but allocate first block in straight order
helper::acquire_segment(*this, k_start, element_size, segment_base( k_start ) >= start );
range.apply( helper::init_body(init, src) );
}
tbb::internal::concurrent_vector_base_v3::helper::acquire_segment
static segment_t & acquire_segment(concurrent_vector_base_v3 &v, size_type index, size_type element_size, bool owner)
Definition: concurrent_vector.cpp:104

References __TBB_ASSERT, tbb::internal::concurrent_vector_base_v3::helper::acquire_segment(), tbb::internal::concurrent_vector_base_v3::helper::apply(), tbb::internal::concurrent_vector_base_v3::helper::assign_first_segment_if_necessary(), tbb::internal::concurrent_vector_base_v3::helper::extend_table_if_necessary(), tbb::internal::concurrent_vector_base_v3::helper::first_block, my_first_block, my_segment, segment_base(), and segment_index_of().

Referenced by internal_grow_by(), and internal_grow_to_at_least_with_result().

Here is the call graph for this function:
Here is the caller graph for this function:

## internal_grow_by()

concurrent_vector_base_v3::size_type tbb::internal::concurrent_vector_base_v3::internal_grow_by | ( | size_type | delta,
|  | size_type | element_size,
|  | internal_array_op2 | init,
|  | const void * | src
| ) |  |

protected

Definition at line 467 of file concurrent_vector.cpp.

{
size_type result = my_early_size.fetch_and_add(delta);
internal_grow( result, result+delta, element_size, init, src );
return result;
}
tbb::internal::concurrent_vector_base_v3::internal_grow
void internal_grow(size_type start, size_type finish, size_type element_size, internal_array_op2 init, const void *src)
Definition: concurrent_vector.cpp:473

References internal_grow(), and my_early_size.

Referenced by tbb::concurrent_vector< T, A >::grow_by().

Here is the call graph for this function:
Here is the caller graph for this function:

## internal_grow_to_at_least()

void tbb::internal::concurrent_vector_base_v3::internal_grow_to_at_least | ( | size_type | new_size,
|  | size_type | element_size,
|  | internal_array_op2 | init,
|  | const void * | src
| ) |  |

protected

Deprecated entry point for backwards compatibility to TBB 2.1.

Definition at line 430 of file concurrent_vector.cpp.

{
internal_grow_to_at_least_with_result( new_size, element_size, init, src );
}
new_size
void const char const char int ITT_FORMAT __itt_group_sync x void const char ITT_FORMAT __itt_group_sync s void ITT_FORMAT __itt_group_sync p void ITT_FORMAT p void ITT_FORMAT p no args __itt_suppress_mode_t unsigned int void size_t ITT_FORMAT d void ITT_FORMAT p void ITT_FORMAT p __itt_model_site __itt_model_site_instance ITT_FORMAT p __itt_model_task __itt_model_task_instance ITT_FORMAT p void ITT_FORMAT p void ITT_FORMAT p void size_t ITT_FORMAT d void ITT_FORMAT p const wchar_t ITT_FORMAT s const char ITT_FORMAT s const char ITT_FORMAT s const char ITT_FORMAT s no args void ITT_FORMAT p size_t ITT_FORMAT d no args const wchar_t const wchar_t ITT_FORMAT s __itt_heap_function void size_t int ITT_FORMAT d __itt_heap_function void ITT_FORMAT p __itt_heap_function void void size_t new_size
Definition: ittnotify_static.h:163
tbb::internal::concurrent_vector_base_v3::internal_grow_to_at_least_with_result
size_type __TBB_EXPORTED_METHOD internal_grow_to_at_least_with_result(size_type new_size, size_type element_size, internal_array_op2 init, const void *src)
Definition: concurrent_vector.cpp:434

References internal_grow_to_at_least_with_result(), and new_size.

Here is the call graph for this function:

## internal_grow_to_at_least_with_result()

concurrent_vector_base_v3::size_type tbb::internal::concurrent_vector_base_v3::internal_grow_to_at_least_with_result | ( | size_type | new_size,
|  | size_type | element_size,
|  | internal_array_op2 | init,
|  | const void * | src
| ) |  |

protected

Definition at line 434 of file concurrent_vector.cpp.

{
size_type e = my_early_size;
while( e<new_size ) {
size_type f = my_early_size.compare_and_swap(new_size,e);
if( f==e ) {
internal_grow( e, new_size, element_size, init, src );
break;
}
e = f;
}
// Check/wait for segments allocation completes
segment_index_t i, k_old = segment_index_of( new_size-1 );
if( k_old >= pointers_per_short_table && my_segment == my_storage ) {
spin_wait_while_eq( my_segment, my_storage );
}
for( i = 0; i <= k_old; ++i ) {
segment_t &s = my_segment[i];
if(s.load<relaxed>() == segment_not_used()) {
ITT_NOTIFY(sync_prepare, &s);
atomic_backoff backoff(true);
while( my_segment[i].load<acquire>() == segment_not_used() ) // my_segment may change concurrently
backoff.pause();
ITT_NOTIFY(sync_acquired, &s);
}
enforce_segment_allocated(my_segment[i].load<relaxed>());
}
#if TBB_USE_DEBUG
size_type capacity = internal_capacity();
__TBB_ASSERT( capacity >= new_size, NULL);
#endif
return e;
}
ITT_NOTIFY
#define ITT_NOTIFY(name, obj)
Definition: itt_notify.h:112
tbb::internal::spin_wait_while_eq
void spin_wait_while_eq(const volatile T &location, U value)
Spin WHILE the value of the variable is equal to a given value.
Definition: tbb_machine.h:394
tbb::internal::concurrent_vector_base_v3::internal_capacity
size_type __TBB_EXPORTED_METHOD internal_capacity() const
Definition: concurrent_vector.cpp:329

References __TBB_ASSERT, enforce_segment_allocated, internal_capacity(), internal_grow(), ITT_NOTIFY, my_early_size, my_segment, my_storage, new_size, tbb::internal::atomic_backoff::pause(), pointers_per_short_table, tbb::relaxed, s, segment_index_of(), and tbb::internal::spin_wait_while_eq().

Referenced by tbb::concurrent_vector< T, A >::grow_to_at_least(), and internal_grow_to_at_least().

Here is the call graph for this function:
Here is the caller graph for this function:

## internal_push_back()

void * tbb::internal::concurrent_vector_base_v3::internal_push_back | ( | size_type | element_size,
|  | size_type & | index
| ) |  |

protected

Definition at line 418 of file concurrent_vector.cpp.

{
__TBB_ASSERT( sizeof(my_early_size)==sizeof(uintptr_t), NULL );
size_type tmp = my_early_size.fetch_and_increment<acquire>();
index = tmp;
segment_index_t k_old = segment_index_of( tmp );
size_type base = segment_base(k_old);
helper::extend_table_if_necessary(*this, k_old, tmp);
segment_t& s = helper::acquire_segment(*this, k_old, element_size, base==tmp);
size_type j_begin = tmp-base;
return (void*)(s.load<relaxed>().pointer<char>() + element_size*j_begin);
}

References __TBB_ASSERT, tbb::acquire, tbb::internal::concurrent_vector_base_v3::helper::acquire_segment(), tbb::internal::concurrent_vector_base_v3::helper::extend_table_if_necessary(), my_early_size, tbb::relaxed, s, segment_base(), and segment_index_of().

Here is the call graph for this function:

## internal_reserve()

void tbb::internal::concurrent_vector_base_v3::internal_reserve | ( | size_type | n,
|  | size_type | element_size,
|  | size_type | max_size
| ) |  |

protected

Definition at line 339 of file concurrent_vector.cpp.

{
if( n>max_size )
throw_exception(eid_reservation_length_error);
__TBB_ASSERT( n, NULL );
helper::assign_first_segment_if_necessary(*this, segment_index_of(n-1));
segment_index_t k = helper::find_segment_end(*this);
for( ; segment_base(k)<n; ++k ) {
helper::extend_table_if_necessary(*this, k, 0);
if(my_segment[k].load<relaxed>() != segment_allocated())
helper::enable_segment(*this, k, element_size, true ); //in case of failure mark segments as not used
}
}
tbb::internal::throw_exception
void throw_exception(exception_id eid)
Versionless convenience wrapper for throw_exception_v4()
Definition: tbb_exception.h:105
tbb::internal::eid_reservation_length_error
@ eid_reservation_length_error
Definition: tbb_exception.h:83

References __TBB_ASSERT, tbb::internal::concurrent_vector_base_v3::helper::assign_first_segment_if_necessary(), tbb::internal::eid_reservation_length_error, tbb::internal::concurrent_vector_base_v3::helper::enable_segment(), tbb::internal::concurrent_vector_base_v3::helper::extend_table_if_necessary(), tbb::internal::concurrent_vector_base_v3::helper::find_segment_end(), my_segment, segment_base(), segment_index_of(), and tbb::internal::throw_exception().

Referenced by internal_resize(), and tbb::concurrent_vector< T, A >::reserve().

Here is the call graph for this function:
Here is the caller graph for this function:

## internal_resize()

void tbb::internal::concurrent_vector_base_v3::internal_resize | ( | size_type | n,
|  | size_type | element_size,
|  | size_type | max_size,
|  | const void * | src,
|  | internal_array_op1 | destroy,
|  | internal_array_op2 | init
| ) |  |

protected

Definition at line 486 of file concurrent_vector.cpp.

{
size_type j = my_early_size;
if( n > j ) { // construct items
internal_reserve(n, element_size, max_size);
my_early_size = n;
helper for_each(my_segment, my_first_block, element_size, segment_index_of(j), j, n);
for_each.apply( helper::safe_init_body(init, src) );
} else {
my_early_size = n;
helper for_each(my_segment, my_first_block, element_size, segment_index_of(n), n, j);
for_each.apply( helper::destroy_body(destroy) );
}
}
tbb::internal::concurrent_vector_base_v3::internal_reserve
void __TBB_EXPORTED_METHOD internal_reserve(size_type n, size_type element_size, size_type max_size)
Definition: concurrent_vector.cpp:339

References tbb::internal::concurrent_vector_base_v3::helper::apply(), internal_reserve(), my_early_size, my_first_block, my_segment, and segment_index_of().

Referenced by tbb::concurrent_vector< T, A >::assign(), tbb::concurrent_vector< T, A >::concurrent_vector(), tbb::concurrent_vector< T, A >::internal_assign_n(), and tbb::concurrent_vector< T, A >::resize().

Here is the call graph for this function:
Here is the caller graph for this function:

## internal_swap()

void tbb::internal::concurrent_vector_base_v3::internal_swap | ( | concurrent_vector_base_v3 & | v | ) |

protected

Definition at line 582 of file concurrent_vector.cpp.

{
size_type my_sz = my_early_size.load<acquire>();
size_type v_sz = v.my_early_size.load<relaxed>();
if(!my_sz && !v_sz) return;
bool my_was_short = (my_segment.load<relaxed>() == my_storage);
bool v_was_short = (v.my_segment.load<relaxed>() == v.my_storage);
//In C++11, this would be: swap(my_storage, v.my_storage);
for (int i=0; i < pointers_per_short_table; ++i){
swap(my_storage[i], v.my_storage[i]);
}
tbb::internal::swap<relaxed>(my_first_block, v.my_first_block);
tbb::internal::swap<relaxed>(my_segment, v.my_segment);
if (my_was_short){
v.my_segment.store<relaxed>(v.my_storage);
}
if(v_was_short){
my_segment.store<relaxed>(my_storage);
}
my_early_size.store<relaxed>(v_sz);
v.my_early_size.store<release>(my_sz);
}
tbb::release
@ release
Release.
Definition: atomic.h:59
tbb::internal::concurrent_vector_base_v3::swap
friend void swap(segment_t &, segment_t &) __TBB_NOEXCEPT(true)
Definition: concurrent_vector.h:284

References tbb::acquire, my_early_size, my_first_block, my_segment, my_storage, pointers_per_short_table, tbb::relaxed, tbb::release, and swap.

Referenced by tbb::concurrent_vector< T, A >::concurrent_vector(), tbb::concurrent_vector< T, A >::operator=(), and tbb::concurrent_vector< T, A >::swap().

Here is the caller graph for this function:

## internal_throw_exception()

void tbb::internal::concurrent_vector_base_v3::internal_throw_exception | ( | size_type | t | ) | const

protected

Obsolete.

Definition at line 333 of file concurrent_vector.cpp.

{
exception_id ids[] = { eid_out_of_range, eid_segment_range_error, eid_index_range_error };
__TBB_ASSERT(t < sizeof(ids) / sizeof(exception_id), NULL);
throw_exception(ids[t]);
}
tbb::internal::exception_id
exception_id
Definition: tbb_exception.h:67
tbb::internal::eid_segment_range_error
@ eid_segment_range_error
Definition: tbb_exception.h:72
tbb::internal::eid_out_of_range
@ eid_out_of_range
Definition: tbb_exception.h:71
tbb::internal::eid_index_range_error
@ eid_index_range_error
Definition: tbb_exception.h:73

References __TBB_ASSERT, tbb::internal::eid_index_range_error, tbb::internal::eid_out_of_range, tbb::internal::eid_segment_range_error, and tbb::internal::throw_exception().

Here is the call graph for this function:

## is_first_element_in_segment()

static bool tbb::internal::concurrent_vector_base_v3::is_first_element_in_segment | ( | size_type | element_index | ) |

inline static protected

Definition at line 233 of file concurrent_vector.h.

{
//check if element_index is a power of 2 that is at least 2.
//The idea is to detect if the iterator crosses a segment boundary,
//and 2 is the minimal index for which it's true
__TBB_ASSERT(element_index, "there should be no need to call "
"is_first_element_in_segment for 0th element" );
return is_power_of_two_at_least( element_index, 2 );
}
tbb::internal::is_power_of_two_at_least
bool is_power_of_two_at_least(argument_integer_type arg, power2_integer_type power2)
A function to determine if arg is a power of 2 at least as big as another power of 2.
Definition: tbb_stddef.h:392

References __TBB_ASSERT, and tbb::internal::is_power_of_two_at_least().

Referenced by tbb::internal::vector_iterator< Container, Value >::operator++(), and tbb::internal::vector_iterator< Container, Value >::operator--().

Here is the call graph for this function:
Here is the caller graph for this function:

## segment_base()

static segment_index_t tbb::internal::concurrent_vector_base_v3::segment_base | ( | segment_index_t | k | ) |

inline static protected

Definition at line 218 of file concurrent_vector.h.

{
return (segment_index_t(1)<<k & ~segment_index_t(1));
}

Referenced by tbb::internal::concurrent_vector_base_v3::helper::cleanup(), tbb::internal::concurrent_vector_base_v3::helper::enable_segment(), tbb::internal::concurrent_vector_base_v3::helper::extend_segment_table(), tbb::internal::concurrent_vector_base_v3::helper::first_segment(), internal_assign(), internal_capacity(), internal_compact(), internal_copy(), internal_grow(), internal_push_back(), internal_reserve(), and segment_base_index_of().

Here is the caller graph for this function:

## segment_base_index_of()

static segment_index_t tbb::internal::concurrent_vector_base_v3::segment_base_index_of | ( | segment_index_t & | index | ) |

inline static protected

Definition at line 222 of file concurrent_vector.h.

{
segment_index_t k = segment_index_of( index );
index -= segment_base(k);
return k;
}

References segment_base(), and segment_index_of().

Here is the call graph for this function:

## segment_index_of()

static segment_index_t tbb::internal::concurrent_vector_base_v3::segment_index_of | ( | size_type | index | ) |

inline static protected

Definition at line 214 of file concurrent_vector.h.

{
return segment_index_t( __TBB_Log2( index|1 ) );
}
__TBB_Log2
intptr_t __TBB_Log2(uintptr_t x)
Definition: tbb_machine.h:863

References __TBB_Log2().

Referenced by tbb::internal::concurrent_vector_base_v3::helper::cleanup(), internal_assign(), internal_compact(), internal_copy(), internal_grow(), internal_grow_to_at_least_with_result(), internal_push_back(), internal_reserve(), internal_resize(), and segment_base_index_of().

Here is the call graph for this function:
Here is the caller graph for this function:

## segment_size()

static size_type tbb::internal::concurrent_vector_base_v3::segment_size | ( | segment_index_t | k | ) |

inline static protected

Definition at line 228 of file concurrent_vector.h.

{
return segment_index_t(1)<<k; // fake value for k==0
}

Referenced by tbb::internal::concurrent_vector_base_v3::helper::enable_segment(), tbb::internal::concurrent_vector_base_v3::helper::extend_segment_table(), tbb::internal::concurrent_vector_base_v3::helper::first_segment(), internal_assign(), internal_compact(), and tbb::internal::concurrent_vector_base_v3::helper::next_segment().

Here is the caller graph for this function:

## Friends And Related Function Documentation

## enforce_segment_allocated

void enforce_segment_allocated | ( | segment_value_t const & | s,
|  | internal::exception_id | exception = `eid_bad_last_alloc`
| ) |  |

friend

Definition at line 121 of file concurrent_vector.h.

{
if(s != segment_allocated()){
internal::throw_exception(exception);
}
}

Referenced by tbb::internal::concurrent_vector_base_v3::helper::acquire_segment(), tbb::internal::concurrent_vector_base_v3::helper::enable_segment(), internal_assign(), internal_grow_to_at_least_with_result(), and tbb::internal::concurrent_vector_base_v3::helper::safe_init_body::operator()().

## helper

friend class helper

friend

Definition at line 277 of file concurrent_vector.h.

## swap

void swap | ( | concurrent_vector_base_v3::segment_t & | lhs,
|  | concurrent_vector_base_v3::segment_t & | rhs
| ) |  |

friend

Definition at line 284 of file concurrent_vector.h.

{
lhs.swap(rhs);
}

Referenced by internal_swap().

## vector_iterator

template<typename Container , typename Value >

friend class vector_iterator

friend

Definition at line 280 of file concurrent_vector.h.

## Member Data Documentation

## my_early_size

atomic<size_type> tbb::internal::concurrent_vector_base_v3::my_early_size

protected

Requested size of vector.

Definition at line 184 of file concurrent_vector.h.

Referenced by concurrent_vector_base_v3(), tbb::concurrent_vector< T, A >::empty(), tbb::concurrent_vector< T, A >::grow_by(), internal_assign(), internal_clear(), internal_compact(), internal_copy(), internal_grow_by(), internal_grow_to_at_least_with_result(), internal_push_back(), internal_resize(), internal_swap(), and tbb::concurrent_vector< T, A >::size().

## my_first_block

atomic<size_type> tbb::internal::concurrent_vector_base_v3::my_first_block

protected

count of segments in the first block

Definition at line 181 of file concurrent_vector.h.

Referenced by tbb::internal::concurrent_vector_base_v3::helper::assign_first_segment_if_necessary(), tbb::concurrent_vector< T, A >::concurrent_vector(), concurrent_vector_base_v3(), tbb::internal::concurrent_vector_base_v3::helper::enable_segment(), internal_clear(), internal_compact(), internal_grow(), internal_resize(), internal_swap(), and tbb::concurrent_vector< T, A >::~concurrent_vector().

## my_segment

atomic<segment_t*> tbb::internal::concurrent_vector_base_v3::my_segment

protected

Pointer to the segments table.

Definition at line 187 of file concurrent_vector.h.

Referenced by tbb::internal::concurrent_vector_base_v3::helper::acquire_segment(), tbb::concurrent_vector< T, A >::concurrent_vector(), concurrent_vector_base_v3(), tbb::internal::concurrent_vector_base_v3::helper::enable_segment(), tbb::internal::concurrent_vector_base_v3::helper::extend_segment_table(), tbb::internal::concurrent_vector_base_v3::helper::extend_table_if_necessary(), tbb::internal::concurrent_vector_base_v3::helper::find_segment_end(), tbb::concurrent_vector< T, A >::front(), internal_assign(), internal_clear(), internal_compact(), internal_copy(), internal_grow(), internal_grow_to_at_least_with_result(), internal_reserve(), internal_resize(), internal_swap(), tbb::concurrent_vector< T, A >::~concurrent_vector(), and ~concurrent_vector_base_v3().

## my_storage

segment_t tbb::internal::concurrent_vector_base_v3::my_storage[pointers_per_short_table]

protected

embedded storage of segment pointers

Definition at line 190 of file concurrent_vector.h.

Referenced by concurrent_vector_base_v3(), tbb::internal::concurrent_vector_base_v3::helper::extend_segment_table(), tbb::internal::concurrent_vector_base_v3::helper::extend_table_if_necessary(), tbb::internal::concurrent_vector_base_v3::helper::find_segment_end(), internal_assign(), internal_copy(), internal_grow_to_at_least_with_result(), internal_swap(), and ~concurrent_vector_base_v3().

## vector_allocator_ptr

void*(* tbb::internal::concurrent_vector_base_v3::vector_allocator_ptr) (concurrent_vector_base_v3 &, size_t)

protected

allocator function pointer

Definition at line 178 of file concurrent_vector.h.

Referenced by tbb::internal::concurrent_vector_base_v3::helper::allocate_segment(), and tbb::concurrent_vector< T, A >::concurrent_vector().

The documentation for this class was generated from the following files:

- concurrent_vector.h
- concurrent_vector.cpp

Copyright © 2005-2020 Intel Corporation. All Rights Reserved.

Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are registered trademarks or trademarks of Intel Corporation or its subsidiaries in the United States and other countries.

* Other names and brands may be claimed as the property of others.