Intel(R) Threading Building Blocks Doxygen Documentation version 4.2.3
Loading...
Searching...
No Matches
_flow_graph_item_buffer_impl.h
Go to the documentation of this file.
1/*
2 Copyright (c) 2005-2020 Intel Corporation
3
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15*/
16
17#ifndef __TBB__flow_graph_item_buffer_impl_H
18#define __TBB__flow_graph_item_buffer_impl_H
19
20#ifndef __TBB_flow_graph_H
21#error Do not #include this internal file directly; use public TBB headers instead.
22#endif
23
24#include "tbb/internal/_flow_graph_types_impl.h" // for aligned_pair
25
26// in namespace tbb::flow::interfaceX (included in _flow_graph_node_impl.h)
27
29 //* tests for empty and so forth. No mutual exclusion is built in.
30 //* objects are constructed into and explicitly-destroyed. get_my_item gives
31 // a read-only reference to the item in the buffer. set_my_item may be called
32 // with either an empty or occupied slot.
33
36
37namespace internal {
38
39 template <typename T, typename A=cache_aligned_allocator<T> >
41 public:
42 typedef T item_type;
44 protected:
45 typedef size_t size_type;
53
54 bool buffer_empty() const { return my_head == my_tail; }
55
59 return my_array[i & (my_array_size - 1) ];
60 }
61
65 return my_array[i & (my_array_size-1)];
66 }
67
68 bool my_item_valid(size_type i) const { return (i < my_tail) && (i >= my_head) && (item(i).second != no_item); }
69 bool my_item_reserved(size_type i) const { return item(i).second == reserved_item; }
70
71 // object management in buffer
72 const item_type &get_my_item(size_t i) const {
73 __TBB_ASSERT(my_item_valid(i),"attempt to get invalid item");
74 item_type *itm = (tbb::internal::punned_cast<item_type *>(&(item(i).first)));
75 return *(const item_type *)itm;
76 }
77
78 // may be called with an empty slot or a slot that has already been constructed into.
79 void set_my_item(size_t i, const item_type &o) {
80 if(item(i).second != no_item) {
81 destroy_item(i);
82 }
83 new(&(item(i).first)) item_type(o);
84 item(i).second = has_item;
85 }
86
87 // destructively-fetch an object from the buffer
88 void fetch_item(size_t i, item_type &o) {
89 __TBB_ASSERT(my_item_valid(i), "Trying to fetch an empty slot");
90 o = get_my_item(i); // could have std::move assign semantics
91 destroy_item(i);
92 }
93
94 // move an existing item from one slot to another. The moved-to slot must be unoccupied,
95 // the moved-from slot must exist and not be reserved. The after, from will be empty,
96 // to will be occupied but not reserved
97 void move_item(size_t to, size_t from) {
98 __TBB_ASSERT(!my_item_valid(to), "Trying to move to a non-empty slot");
99 __TBB_ASSERT(my_item_valid(from), "Trying to move from an empty slot");
100 set_my_item(to, get_my_item(from)); // could have std::move semantics
101 destroy_item(from);
102
103 }
104
105 // put an item in an empty slot. Return true if successful, else false
106 bool place_item(size_t here, const item_type &me) {
107#if !TBB_DEPRECATED_SEQUENCER_DUPLICATES
108 if(my_item_valid(here)) return false;
109#endif
110 set_my_item(here, me);
111 return true;
112 }
113
114 // could be implemented with std::move semantics
115 void swap_items(size_t i, size_t j) {
116 __TBB_ASSERT(my_item_valid(i) && my_item_valid(j), "attempt to swap invalid item(s)");
117 item_type temp = get_my_item(i);
119 set_my_item(j, temp);
120 }
121
123 __TBB_ASSERT(my_item_valid(i), "destruction of invalid item");
124 (tbb::internal::punned_cast<item_type *>(&(item(i).first)))->~item_type();
125 item(i).second = no_item;
126 }
127
128 // returns the front element
129 const item_type& front() const
130 {
131 __TBB_ASSERT(my_item_valid(my_head), "attempt to fetch head non-item");
132 return get_my_item(my_head);
133 }
134
135 // returns the back element
136 const item_type& back() const
137 {
138 __TBB_ASSERT(my_item_valid(my_tail - 1), "attempt to fetch head non-item");
139 return get_my_item(my_tail - 1);
140 }
141
142 // following methods are for reservation of the front of a buffer.
143 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; }
144 void release_item(size_type i) { __TBB_ASSERT(my_item_reserved(i), "item is not reserved"); item(i).second = has_item; }
145
148
149 // we have to be able to test against a new tail value without changing my_tail
150 // grow_array doesn't work if we change my_tail when the old array is too small
151 size_type size(size_t new_tail = 0) { return (new_tail ? new_tail : my_tail) - my_head; }
153 // sequencer_node does not use this method, so we don't
154 // need a version that passes in the new_tail value.
155 bool buffer_full() { return size() >= capacity(); }
156
158 void grow_my_array( size_t minimum_size ) {
159 // test that we haven't made the structure inconsistent.
160 __TBB_ASSERT(capacity() >= my_tail - my_head, "total items exceed capacity");
162 while( new_size<minimum_size )
163 new_size*=2;
164
165 buffer_item_type* new_array = allocator_type().allocate(new_size);
166
167 // initialize validity to "no"
168 for( size_type i=0; i<new_size; ++i ) { new_array[i].second = no_item; }
169
170 for( size_type i=my_head; i<my_tail; ++i) {
171 if(my_item_valid(i)) { // sequencer_node may have empty slots
172 // placement-new copy-construct; could be std::move
173 char *new_space = (char *)&(new_array[i&(new_size-1)].first);
174 (void)new(new_space) item_type(get_my_item(i));
175 new_array[i&(new_size-1)].second = item(i).second;
176 }
177 }
178
179 clean_up_buffer(/*reset_pointers*/false);
180
181 my_array = new_array;
183 }
184
186 if(buffer_full()) {
187 grow_my_array(size() + 1);
188 }
190 ++my_tail;
191 return true;
192 }
193
195 if (!my_item_valid(my_tail-1)) {
196 return false;
197 }
198 v = this->back();
199 destroy_back();
200 return true;
201 }
202
203 bool pop_front(item_type &v) {
204 if(!my_item_valid(my_head)) {
205 return false;
206 }
207 v = this->front();
209 return true;
210 }
211
212 // This is used both for reset and for grow_my_array. In the case of grow_my_array
213 // we want to retain the values of the head and tail.
214 void clean_up_buffer(bool reset_pointers) {
215 if (my_array) {
216 for( size_type i=my_head; i<my_tail; ++i ) {
217 if(my_item_valid(i))
218 destroy_item(i);
219 }
221 }
222 my_array = NULL;
223 if(reset_pointers) {
225 }
226 }
227
228 public:
231 my_head(0), my_tail(0) {
233 }
234
236 clean_up_buffer(/*reset_pointers*/true);
237 }
238
239 void reset() { clean_up_buffer(/*reset_pointers*/true); grow_my_array(initial_buffer_size); }
240
241 };
242
244 //* complete operation with pop_front(); use consume_front().
245 //* No synchronization built-in.
246 template<typename T, typename A=cache_aligned_allocator<T> >
247 class reservable_item_buffer : public item_buffer<T, A> {
248 protected:
249 using item_buffer<T, A>::my_item_valid;
250 using item_buffer<T, A>::my_head;
251
252 public:
255 protected:
256
257 bool reserve_front(T &v) {
258 if(my_reserved || !my_item_valid(this->my_head)) return false;
259 my_reserved = true;
260 // reserving the head
261 v = this->front();
262 this->reserve_item(this->my_head);
263 return true;
264 }
265
267 __TBB_ASSERT(my_reserved, "Attempt to consume a non-reserved item");
268 this->destroy_front();
269 my_reserved = false;
270 }
271
273 __TBB_ASSERT(my_reserved, "Attempt to release a non-reserved item");
274 this->release_item(this->my_head);
275 my_reserved = false;
276 }
277
279 };
280
281} // namespace internal
282
283#endif // __TBB__flow_graph_item_buffer_impl_H
#define __TBB_ASSERT(predicate, comment)
No-op version of __TBB_ASSERT.
Definition tbb_stddef.h:165
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
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 size
allocator_traits< Alloc >::template rebind_alloc< T >::other type
aligned_pair< item_type, buffer_item_state >::type buffer_item_type
void move_item(size_t to, size_t from)
void clean_up_buffer(bool reset_pointers)
const item_type & get_my_item(size_t i) const
bool my_item_reserved(size_type i) const
static const size_type initial_buffer_size
bool place_item(size_t here, const item_type &me)
void grow_my_array(size_t minimum_size)
Grows the internal array.
buffer_item_type & item(size_type i)
const item_type & front() const
size_type size(size_t new_tail=0)
void fetch_item(size_t i, item_type &o)
bool my_item_valid(size_type i) const
void set_my_item(size_t i, const item_type &o)
const buffer_item_type & item(size_type i) const
void swap_items(size_t i, size_t j)
const item_type & back() const
tbb::internal::allocator_rebind< A, buffer_item_type >::type allocator_type
item_buffer with reservable front-end. NOTE: if reserving, do not
type mimicking std::pair but with trailing fill to ensure each element of an array

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.