21 #ifndef __TBB__flow_graph_item_buffer_impl_H 22 #define __TBB__flow_graph_item_buffer_impl_H 24 #ifndef __TBB_flow_graph_H 25 #error Do not #include this internal file directly; use public TBB headers instead. 28 #include "tbb/internal/_flow_graph_types_impl.h" 43 template <
typename T,
typename A=cache_aligned_allocator<T> >
47 enum buffer_item_state { no_item=0, has_item=1, reserved_item=2 };
49 typedef size_t size_type;
51 typedef typename A::template rebind<buffer_item_type>::other allocator_type;
53 buffer_item_type *my_array;
54 size_type my_array_size;
55 static const size_type initial_buffer_size = 4;
59 bool buffer_empty() {
return my_head == my_tail; }
61 buffer_item_type &item(size_type i) {
64 return my_array[i & (my_array_size - 1) ];
67 bool my_item_valid(size_type i) {
return (i < my_tail) && (i >= my_head) && (item(i).second != no_item); }
68 bool my_item_reserved(size_type i) {
return item(i).second == reserved_item; }
71 const item_type &get_my_item(
size_t i) {
72 __TBB_ASSERT(my_item_valid(i),
"attempt to get invalid item");
73 item_type *itm = (tbb::internal::punned_cast<item_type *>(&(item(i).first)));
74 return *(
const item_type *)itm;
78 void set_my_item(
size_t i,
const item_type &o) {
79 if(item(i).second != no_item) {
82 new(&(item(i).first)) item_type(o);
83 item(i).second = has_item;
87 void fetch_item(
size_t i, item_type &o) {
88 __TBB_ASSERT(my_item_valid(i),
"Trying to fetch an empty slot");
96 void move_item(
size_t to,
size_t from) {
97 __TBB_ASSERT(!my_item_valid(to),
"Trying to move to a non-empty slot");
98 __TBB_ASSERT(my_item_valid(from),
"Trying to move from an empty slot");
99 set_my_item(to, get_my_item(from));
105 bool place_item(
size_t here,
const item_type &me) {
106 #if !TBB_DEPRECATED_SEQUENCER_DUPLICATES 107 if(my_item_valid(here))
return false;
109 set_my_item(here, me);
114 void swap_items(
size_t i,
size_t j) {
115 __TBB_ASSERT(my_item_valid(i) && my_item_valid(j),
"attempt to swap invalid item(s)");
116 item_type temp = get_my_item(i);
117 set_my_item(i, get_my_item(j));
118 set_my_item(j, temp);
121 void destroy_item(size_type i) {
122 __TBB_ASSERT(my_item_valid(i),
"destruction of invalid item");
123 (tbb::internal::punned_cast<item_type *>(&(item(i).first)))->~item_type();
124 item(i).second = no_item;
128 const item_type& front() {
129 __TBB_ASSERT(my_item_valid(my_head),
"attempt to fetch head non-item");
130 return get_my_item(my_head);
134 const item_type& back() {
135 __TBB_ASSERT(my_item_valid(my_tail-1),
"attempt to fetch tail non-item");
136 return get_my_item(my_tail-1);
140 void reserve_item(size_type i) { __TBB_ASSERT(my_item_valid(i) && !my_item_reserved(i),
"item cannot be reserved"); item(i).second = reserved_item; }
141 void release_item(size_type i) { __TBB_ASSERT(my_item_reserved(i),
"item is not reserved"); item(i).second = has_item; }
143 void destroy_front() { destroy_item(my_head); ++my_head; }
144 void destroy_back() { destroy_item(my_tail-1); --my_tail; }
148 size_type size(
size_t new_tail = 0) {
return (new_tail ? new_tail : my_tail) - my_head; }
149 size_type capacity() {
return my_array_size; }
152 bool buffer_full() {
return size() >= capacity(); }
157 __TBB_ASSERT(capacity() >= my_tail - my_head,
"total items exceed capacity");
158 size_type new_size = my_array_size ? 2*my_array_size : initial_buffer_size;
159 while( new_size<minimum_size )
162 buffer_item_type* new_array = allocator_type().allocate(new_size);
165 for( size_type i=0; i<new_size; ++i ) { new_array[i].second = no_item; }
167 for( size_type i=my_head; i<my_tail; ++i) {
168 if(my_item_valid(i)) {
170 char *new_space = (
char *)&(new_array[i&(new_size-1)].first);
171 (void)
new(new_space) item_type(get_my_item(i));
172 new_array[i&(new_size-1)].second = item(i).second;
176 clean_up_buffer(
false);
178 my_array = new_array;
179 my_array_size = new_size;
182 bool push_back(item_type &v) {
186 set_my_item(my_tail, v);
191 bool pop_back(item_type &v) {
192 if (!my_item_valid(my_tail-1)) {
200 bool pop_front(item_type &v) {
201 if(!my_item_valid(my_head)) {
211 void clean_up_buffer(
bool reset_pointers) {
213 for( size_type i=my_head; i<my_tail; ++i ) {
217 allocator_type().deallocate(my_array,my_array_size);
221 my_head = my_tail = my_array_size = 0;
228 my_head(0), my_tail(0) {
233 clean_up_buffer(
true);
236 void reset() { clean_up_buffer(
true);
grow_my_array(initial_buffer_size); }
243 template<
typename T,
typename A=cache_aligned_allocator<T> >
254 bool reserve_front(T &v) {
255 if(my_reserved || !my_item_valid(this->my_head))
return false;
259 this->reserve_item(this->my_head);
263 void consume_front() {
264 __TBB_ASSERT(my_reserved,
"Attempt to consume a non-reserved item");
265 this->destroy_front();
269 void release_front() {
270 __TBB_ASSERT(my_reserved,
"Attempt to release a non-reserved item");
271 this->release_item(this->my_head);
280 #endif // __TBB__flow_graph_item_buffer_impl_H Definition: _flow_graph_types_impl.h:393
item_buffer with reservable front-end. NOTE: if reserving, do not
Definition: _flow_graph_item_buffer_impl.h:244
Definition: _flow_graph_types_impl.h:402
item_buffer()
Constructor.
Definition: _flow_graph_item_buffer_impl.h:227
type mimicking std::pair but with trailing fill to ensure each element of an array ...
Definition: _flow_graph_types_impl.h:381
Definition: _flow_graph_async_msg_impl.h:32
void grow_my_array(size_t minimum_size)
Grows the internal array.
Definition: _flow_graph_item_buffer_impl.h:155
Definition: _flow_graph_item_buffer_impl.h:44