21 #ifndef _TBB_task_stream_extended_H 22 #define _TBB_task_stream_extended_H 32 #if _TBB_task_stream_H 33 #error Either task_stream.h or this file can be included at the same time. 37 #error This code bears a preview status until it proves its usefulness/peformance suitability. 55 template<
typename T,
typename mutex_t >
56 struct queue_and_mutex {
67 const population_t
one = 1;
69 inline void set_one_bit( population_t& dest,
int pos ) {
71 __TBB_ASSERT( pos<
int(
sizeof(population_t)*CHAR_BIT), NULL );
77 __TBB_ASSERT( pos<
int(
sizeof(population_t)*CHAR_BIT), NULL );
81 inline bool is_bit_set( population_t val,
int pos ) {
83 __TBB_ASSERT( pos<
int(
sizeof(population_t)*CHAR_BIT), NULL );
84 return (val & (one<<pos)) != 0;
88 #if __INTEL_COMPILER == 1110 || __INTEL_COMPILER == 1500 96 __TBB_ASSERT( ((out_of-1) & out_of) == 0,
"number of lanes is not power of two." );
97 return my_random.get() & (out_of-1);
104 #if __INTEL_COMPILER == 1110 || __INTEL_COMPILER == 1500 117 __TBB_ASSERT( ((out_of-1) & out_of) == 0,
"number of lanes is not power of two." );
118 return (++my_previous &= out_of-1);
125 __TBB_ASSERT( ((out_of-1) & out_of) == 0,
"number of lanes is not power of two." );
126 return (--my_previous &= (out_of-1));
139 template<task_stream_accessor_type accessor>
144 task* result = queue.front();
156 result = queue.back();
158 }
while( !result && !queue.empty() );
164 template<
int Levels, task_stream_accessor_type accessor>
167 population_t population[Levels];
173 for(
int level = 0; level < Levels; level++) {
174 population[level] = 0;
180 const unsigned max_lanes =
sizeof(
population_t) * CHAR_BIT;
182 N = n_lanes>=max_lanes ? max_lanes : n_lanes>2 ? 1<<(
__TBB_Log2(n_lanes-1)+1) : 2;
183 __TBB_ASSERT( N==max_lanes || N>=n_lanes && ((N-1)&N)==0,
"number of lanes miscalculated");
184 __TBB_ASSERT( N <=
sizeof(population_t) * CHAR_BIT, NULL );
185 for(
int level = 0; level < Levels; level++) {
192 for(
int level = 0; level < Levels; level++)
193 if (lanes[level])
delete[] lanes[level];
198 __TBB_ASSERT( 0 <= level && level < Levels,
"Incorrect lane level specified." );
200 if( lock.
try_acquire( lanes[level][lane_idx].my_mutex ) ) {
201 lanes[level][lane_idx].my_queue.push_back( source );
209 template<
typename lane_selector_t>
210 void push(
task* source,
int level,
const lane_selector_t& next_lane ) {
211 bool succeed =
false;
214 lane = next_lane( N );
216 }
while( ! (succeed = try_push( source, level, lane )) );
221 __TBB_ASSERT( 0 <= level && level < Levels,
"Incorrect lane level specified." );
222 if( !
is_bit_set( population[level], lane_idx ) )
225 lane_t& lane = lanes[level][lane_idx];
228 result = this->get_item( lane.
my_queue );
237 template<
typename lane_selector_t>
238 task*
pop(
int level,
const lane_selector_t& next_lane ) {
242 lane = next_lane( N );
244 }
while( !empty( level ) && !(popped = try_pop( level, lane )) );
253 typename lane_t::queue_base_t::iterator curr = queue.end();
256 task* result = *--curr;
258 if( queue.end() - curr == 1 )
265 }
while( curr != queue.begin() );
273 unsigned idx = last_used_lane & (N-1);
276 lane_t& lane = lanes[level][idx];
287 }
while( !empty(level) && idx != last_used_lane );
288 last_used_lane = idx;
294 return !population[level];
302 for(
int level = 0; level < Levels; level++)
303 for(
unsigned i=0; i<N; ++i) {
304 lane_t& lane = lanes[level][i];
306 for(
typename lane_t::queue_base_t::iterator it=lane.
my_queue.begin();
307 it!=lane.
my_queue.end(); ++it, ++result)
311 tbb::task::destroy(*t);
void set_one_bit(population_t &dest, int pos)
#define __TBB_ASSERT(predicate, comment)
No-op version of __TBB_ASSERT.
void push(task *source, int level, const lane_selector_t &next_lane)
Push a task into a lane. Lane selection is performed by passed functor.
#define __TBB_ISOLATION_EXPR(isolation)
unsigned operator()(unsigned out_of) const
Base class for types that should not be assigned.
bool try_push(task *source, int level, unsigned lane_idx)
Returns true on successful push, otherwise - false.
random_lane_selector(FastRandom &random)
void initialize(unsigned n_lanes)
preceding_lane_selector(unsigned &previous)
bool empty(int level)
Checks existence of a task.
task * get_item(lane_t::queue_base_t &queue)
Represents acquisition of a mutex.
The container for "fairness-oriented" aka "enqueued" tasks.
void __TBB_AtomicAND(volatile void *operand, uintptr_t addend)
intptr_t isolation_tag
A tag for task isolation.
intptr_t drain()
Destroys all remaining tasks in every lane. Returns the number of destroyed tasks.
task * pop(int level, const lane_selector_t &next_lane)
task * get_item(lane_t::queue_base_t &queue)
internal::task_prefix & prefix(internal::version_tag *=NULL) const
Get reference to corresponding task_prefix.
subsequent_lane_selector(unsigned &previous)
bool try_acquire(spin_mutex &m)
Try acquiring lock (non-blocking)
#define __TBB_ISOLATION_ARG(arg1, isolation)
intptr_t __TBB_Log2(uintptr_t x)
bool is_bit_set(population_t val, int pos)
task * try_pop(int level, unsigned lane_idx)
Returns pointer to task on successful pop, otherwise - NULL.
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 * lock
unsigned operator()(unsigned out_of) const
void clear_one_bit(population_t &dest, int pos)
queue_and_mutex< task *, spin_mutex > lane_t
task * look_specific(__TBB_ISOLATION_ARG(task_stream_base::lane_t::queue_base_t &queue, isolation_tag isolation))
unsigned operator()(unsigned out_of) const
std::deque< T, tbb_allocator< T > > queue_base_t
Pads type T to fill out to a multiple of cache line size.
Base class for user-defined tasks.
Essentially, this is just a pair of a queue and a mutex to protect the queue.
lane_selector_base(unsigned &previous)
Base class for types that should not be copied or assigned.
void __TBB_AtomicOR(volatile void *operand, uintptr_t addend)
A fast random number generator.
task_stream_accessor_type
task * pop_specific(int level, __TBB_ISOLATION_ARG(unsigned &last_used_lane, isolation_tag isolation))
Try finding and popping a related task.
task_stream_accessor< accessor >::lane_t lane_t