353 354 // Attempt to pop from the overflow stack; return true if anything was popped. 355 inline bool pop_overflow(E& t); 356 357 inline overflow_t* overflow_stack() { return &_overflow_stack; } 358 359 inline bool taskqueue_empty() const { return taskqueue_t::is_empty(); } 360 inline bool overflow_empty() const { return _overflow_stack.is_empty(); } 361 inline bool is_empty() const { 362 return taskqueue_empty() && overflow_empty(); 363 } 364 365 private: 366 overflow_t _overflow_stack; 367 }; 368 369 class TaskQueueSetSuper { 370 public: 371 // Returns "true" if some TaskQueue in the set contains a task. 372 virtual bool peek() = 0; 373 }; 374 375 template <MEMFLAGS F> class TaskQueueSetSuperImpl: public CHeapObj<F>, public TaskQueueSetSuper { 376 }; 377 378 template<class T, MEMFLAGS F> 379 class GenericTaskQueueSet: public TaskQueueSetSuperImpl<F> { 380 public: 381 typedef typename T::element_type E; 382 383 private: 384 uint _n; 385 T** _queues; 386 387 bool steal_best_of_2(uint queue_num, E& t); 388 389 public: 390 GenericTaskQueueSet(uint n); 391 ~GenericTaskQueueSet(); 392 393 void register_queue(uint i, T* q); 394 395 T* queue(uint n); 396 397 // Try to steal a task from some other queue than queue_num. It may perform several attempts at doing so. 398 // Returns if stealing succeeds, and sets "t" to the stolen task. 399 bool steal(uint queue_num, E& t); 400 401 bool peek(); 402 403 uint size() const { return _n; } 404 }; 405 406 template<class T, MEMFLAGS F> void 407 GenericTaskQueueSet<T, F>::register_queue(uint i, T* q) { 408 assert(i < _n, "index out of range."); 409 _queues[i] = q; 410 } 411 412 template<class T, MEMFLAGS F> T* 413 GenericTaskQueueSet<T, F>::queue(uint i) { 414 return _queues[i]; 415 } 416 417 template<class T, MEMFLAGS F> 418 bool GenericTaskQueueSet<T, F>::peek() { 419 // Try all the queues. 420 for (uint j = 0; j < _n; j++) { 421 if (_queues[j]->peek()) 422 return true; 423 } 424 return false; 425 } 426 427 // When to terminate from the termination protocol. 428 class TerminatorTerminator: public CHeapObj<mtInternal> { 429 public: 430 virtual bool should_exit_termination() = 0; 431 }; 432 433 // A class to aid in the termination of a set of parallel tasks using 434 // TaskQueueSet's for work stealing. 435 436 #undef TRACESPINNING 437 438 class ParallelTaskTerminator: public StackObj { 439 private: 440 uint _n_threads; 441 TaskQueueSetSuper* _queue_set; 442 volatile uint _offered_termination; 443 444 #ifdef TRACESPINNING | 353 354 // Attempt to pop from the overflow stack; return true if anything was popped. 355 inline bool pop_overflow(E& t); 356 357 inline overflow_t* overflow_stack() { return &_overflow_stack; } 358 359 inline bool taskqueue_empty() const { return taskqueue_t::is_empty(); } 360 inline bool overflow_empty() const { return _overflow_stack.is_empty(); } 361 inline bool is_empty() const { 362 return taskqueue_empty() && overflow_empty(); 363 } 364 365 private: 366 overflow_t _overflow_stack; 367 }; 368 369 class TaskQueueSetSuper { 370 public: 371 // Returns "true" if some TaskQueue in the set contains a task. 372 virtual bool peek() = 0; 373 // Tasks in queue 374 virtual uint tasks() const = 0; 375 }; 376 377 template <MEMFLAGS F> class TaskQueueSetSuperImpl: public CHeapObj<F>, public TaskQueueSetSuper { 378 }; 379 380 template<class T, MEMFLAGS F> 381 class GenericTaskQueueSet: public TaskQueueSetSuperImpl<F> { 382 public: 383 typedef typename T::element_type E; 384 385 private: 386 uint _n; 387 T** _queues; 388 389 bool steal_best_of_2(uint queue_num, E& t); 390 391 public: 392 GenericTaskQueueSet(uint n); 393 ~GenericTaskQueueSet(); 394 395 void register_queue(uint i, T* q); 396 397 T* queue(uint n); 398 399 // Try to steal a task from some other queue than queue_num. It may perform several attempts at doing so. 400 // Returns if stealing succeeds, and sets "t" to the stolen task. 401 bool steal(uint queue_num, E& t); 402 403 bool peek(); 404 uint tasks() const; 405 406 uint size() const { return _n; } 407 }; 408 409 template<class T, MEMFLAGS F> void 410 GenericTaskQueueSet<T, F>::register_queue(uint i, T* q) { 411 assert(i < _n, "index out of range."); 412 _queues[i] = q; 413 } 414 415 template<class T, MEMFLAGS F> T* 416 GenericTaskQueueSet<T, F>::queue(uint i) { 417 return _queues[i]; 418 } 419 420 template<class T, MEMFLAGS F> 421 bool GenericTaskQueueSet<T, F>::peek() { 422 // Try all the queues. 423 for (uint j = 0; j < _n; j++) { 424 if (_queues[j]->peek()) 425 return true; 426 } 427 return false; 428 } 429 430 template<class T, MEMFLAGS F> 431 uint GenericTaskQueueSet<T, F>::tasks() const { 432 uint n = 0; 433 for (uint j = 0; j < _n; j++) { 434 n += _queues[j]->size(); 435 } 436 return n; 437 } 438 439 // When to terminate from the termination protocol. 440 class TerminatorTerminator: public CHeapObj<mtInternal> { 441 public: 442 virtual bool should_exit_termination() = 0; 443 }; 444 445 // A class to aid in the termination of a set of parallel tasks using 446 // TaskQueueSet's for work stealing. 447 448 #undef TRACESPINNING 449 450 class ParallelTaskTerminator: public StackObj { 451 private: 452 uint _n_threads; 453 TaskQueueSetSuper* _queue_set; 454 volatile uint _offered_termination; 455 456 #ifdef TRACESPINNING |