00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #ifndef __TBB_item_buffer_H
00022 #define __TBB_item_buffer_H
00023
00025
00026 template <typename T>
00027 class item_buffer {
00028 public:
00029 typedef T input_type;
00030 typedef T output_type;
00031 protected:
00032 typedef size_t size_type;
00033 typedef std::pair< T, bool > item_type;
00034
00035 item_type *my_array;
00036 size_type my_array_size;
00037 static const size_type initial_buffer_size = 4;
00038 size_type my_head;
00039 size_type my_tail;
00040
00041 bool buffer_empty() { return my_head == my_tail; }
00042
00043 item_type &item(size_type i) { return my_array[i & (my_array_size - 1) ]; }
00044
00045 bool item_valid(size_type i) { return item(i).second; }
00046
00047 void fetch_front(T &v) { __TBB_ASSERT(item_valid(my_head), "front not valid"); v = item(my_head).first; }
00048 void fetch_back(T &v) { __TBB_ASSERT(item_valid(my_tail-1), "back not valid"); v = item(my_tail-1).first; }
00049
00050 void invalidate(size_type i) { __TBB_ASSERT(item_valid(i), "Item not valid"); item(i).second = false; }
00051 void validate(size_type i) { __TBB_ASSERT(!item_valid(i), "Item already valid"); item(i).second = true; }
00052
00053 void invalidate_front() { invalidate(my_head); }
00054 void validate_front() { validate(my_head); }
00055 void invalidate_back() { invalidate(my_tail-1); }
00056
00057 size_type size() { return my_tail - my_head; }
00058 size_type capacity() { return my_array_size; }
00059 bool buffer_full() { return size() == capacity(); }
00060
00062 void grow_my_array( size_t minimum_size ) {
00063 size_type old_size = my_array_size;
00064 size_type new_size = old_size ? 2*old_size : initial_buffer_size;
00065 while( new_size<minimum_size )
00066 new_size*=2;
00067
00068 item_type* new_array = cache_aligned_allocator<item_type>().allocate(new_size);
00069 item_type* old_array = my_array;
00070
00071 for( size_type i=0; i<new_size; ++i )
00072 new_array[i].second = false;
00073
00074 size_t t=my_head;
00075 for( size_type i=0; i<old_size; ++i, ++t )
00076 new_array[t&(new_size-1)] = old_array[t&(old_size-1)];
00077 my_array = new_array;
00078 my_array_size = new_size;
00079 if( old_array )
00080 cache_aligned_allocator<item_type>().deallocate(old_array,old_size);
00081 }
00082
00083 bool push_back(T &v) {
00084 if(buffer_full()) {
00085 grow_my_array(size() + 1);
00086 }
00087 item(my_tail) = std::make_pair( v, true );
00088 ++my_tail;
00089 return true;
00090 }
00091
00092 bool pop_back(T &v) {
00093 if (!item_valid(my_tail-1)) {
00094 return false;
00095 }
00096 fetch_back(v);
00097 invalidate_back();
00098 --my_tail;
00099 return true;
00100 }
00101
00102 bool pop_front(T &v) {
00103 if(!item_valid(my_head)) {
00104 return false;
00105 }
00106 fetch_front(v);
00107 invalidate_front();
00108 ++my_head;
00109 return true;
00110 }
00111
00112 public:
00114 item_buffer( ) : my_array(NULL), my_array_size(0),
00115 my_head(0), my_tail(0) {
00116 grow_my_array(initial_buffer_size);
00117 }
00118
00119 ~item_buffer() {if(my_array) cache_aligned_allocator<item_type>().deallocate(my_array,my_array_size); }
00120
00121 };
00122
00124
00125
00126 template<typename T>
00127 class reservable_item_buffer : public item_buffer<T> {
00128 protected:
00129 using item_buffer<T>::buffer_empty;
00130 using item_buffer<T>::fetch_front;
00131 using item_buffer<T>::invalidate_front;
00132 using item_buffer<T>::validate_front;
00133 using item_buffer<T>::item_valid;
00134 using item_buffer<T>::my_head;
00135
00136 public:
00137 reservable_item_buffer() : item_buffer<T>(), my_reserved(false) {}
00138 protected:
00139
00140 bool reserve_front(T &v) {
00141 if(my_reserved || !item_valid(my_head)) return false;
00142 my_reserved = true;
00143
00144 fetch_front(v);
00145
00146 invalidate_front();
00147 return true;
00148 }
00149
00150 void consume_front() {
00151 __TBB_ASSERT(my_reserved, "Attempt to consume a non-reserved item");
00152 ++my_head;
00153 my_reserved = false;
00154 }
00155
00156 void release_front() {
00157 __TBB_ASSERT(my_reserved, "Attempt to release a non-reserved item");
00158 validate_front();
00159 my_reserved = false;
00160 }
00161
00162 bool my_reserved;
00163 };
00164
00165 #endif // __TBB_item_buffer_H