< prev index next >

src/share/vm/utilities/taskqueue.hpp

Print this page




 484 }
 485 
 486 template <class E, MEMFLAGS F, unsigned int N>
 487 bool OverflowTaskQueue<E, F, N>::pop_overflow(E& t)
 488 {
 489   if (overflow_empty()) return false;
 490   t = overflow_stack()->pop();
 491   return true;
 492 }
 493 
 494 template <class E, MEMFLAGS F, unsigned int N>
 495 bool OverflowTaskQueue<E, F, N>::try_push_to_taskqueue(E t) {
 496   return taskqueue_t::push(t);
 497 }
 498 class TaskQueueSetSuper {
 499 protected:
 500   static int randomParkAndMiller(int* seed0);
 501 public:
 502   // Returns "true" if some TaskQueue in the set contains a task.
 503   virtual bool peek() = 0;

 504 };
 505 
 506 template <MEMFLAGS F> class TaskQueueSetSuperImpl: public CHeapObj<F>, public TaskQueueSetSuper {
 507 };
 508 
 509 template<class T, MEMFLAGS F>
 510 class GenericTaskQueueSet: public TaskQueueSetSuperImpl<F> {
 511 private:
 512   uint _n;
 513   T** _queues;
 514 
 515 public:
 516   typedef typename T::element_type E;
 517 
 518   GenericTaskQueueSet(int n) : _n(n) {
 519     typedef T* GenericTaskQueuePtr;
 520     _queues = NEW_C_HEAP_ARRAY(GenericTaskQueuePtr, n, F);
 521     for (int i = 0; i < n; i++) {
 522       _queues[i] = NULL;
 523     }
 524   }
 525 
 526   bool steal_best_of_2(uint queue_num, int* seed, E& t);
 527 
 528   void register_queue(uint i, T* q);
 529 
 530   T* queue(uint n);
 531 
 532   // The thread with queue number "queue_num" (and whose random number seed is
 533   // at "seed") is trying to steal a task from some other queue.  (It may try
 534   // several queues, according to some configuration parameter.)  If some steal
 535   // succeeds, returns "true" and sets "t" to the stolen task, otherwise returns
 536   // false.
 537   bool steal(uint queue_num, int* seed, E& t);
 538 
 539   bool peek();



 540 };
 541 
 542 template<class T, MEMFLAGS F> void
 543 GenericTaskQueueSet<T, F>::register_queue(uint i, T* q) {
 544   assert(i < _n, "index out of range.");
 545   _queues[i] = q;
 546 }
 547 
 548 template<class T, MEMFLAGS F> T*
 549 GenericTaskQueueSet<T, F>::queue(uint i) {
 550   return _queues[i];
 551 }
 552 
 553 template<class T, MEMFLAGS F> bool
 554 GenericTaskQueueSet<T, F>::steal(uint queue_num, int* seed, E& t) {
 555   for (uint i = 0; i < 2 * _n; i++) {
 556     if (steal_best_of_2(queue_num, seed, t)) {
 557       TASKQUEUE_STATS_ONLY(queue(queue_num)->stats.record_steal(true));
 558       return true;
 559     }


 577   } else if (_n == 2) {
 578     // Just try the other one.
 579     uint k = (queue_num + 1) % 2;
 580     return _queues[k]->pop_global(t);
 581   } else {
 582     assert(_n == 1, "can't be zero.");
 583     return false;
 584   }
 585 }
 586 
 587 template<class T, MEMFLAGS F>
 588 bool GenericTaskQueueSet<T, F>::peek() {
 589   // Try all the queues.
 590   for (uint j = 0; j < _n; j++) {
 591     if (_queues[j]->peek())
 592       return true;
 593   }
 594   return false;
 595 }
 596 









 597 // When to terminate from the termination protocol.
 598 class TerminatorTerminator: public CHeapObj<mtInternal> {
 599 public:
 600   virtual bool should_exit_termination() = 0;
 601 };
 602 
 603 // A class to aid in the termination of a set of parallel tasks using
 604 // TaskQueueSet's for work stealing.
 605 
 606 #undef TRACESPINNING
 607 
 608 class ParallelTaskTerminator: public StackObj {
 609 private:
 610   int _n_threads;
 611   TaskQueueSetSuper* _queue_set;
 612   char _pad_before[DEFAULT_CACHE_LINE_SIZE];
 613   int _offered_termination;
 614   char _pad_after[DEFAULT_CACHE_LINE_SIZE];
 615 
 616 #ifdef TRACESPINNING
 617   static uint _total_yields;
 618   static uint _total_spins;
 619   static uint _total_peeks;
 620 #endif
 621 
 622   bool peek_in_queue_set();
 623 protected:
 624   virtual void yield();
 625   void sleep(uint millis);
 626 
 627 public:
 628 
 629   // "n_threads" is the number of threads to be terminated.  "queue_set" is a
 630   // queue sets of work queues of other threads.
 631   ParallelTaskTerminator(int n_threads, TaskQueueSetSuper* queue_set);
 632 
 633   // The current thread has no work, and is ready to terminate if everyone
 634   // else is.  If returns "true", all threads are terminated.  If returns
 635   // "false", available work has been observed in one of the task queues,
 636   // so the global task is not complete.
 637   bool offer_termination() {
 638     return offer_termination(NULL);
 639   }
 640 
 641   // As above, but it also terminates if the should_exit_termination()
 642   // method of the terminator parameter returns true. If terminator is
 643   // NULL, then it is ignored.
 644   bool offer_termination(TerminatorTerminator* terminator);
 645 
 646   // Reset the terminator, so that it may be reused again.
 647   // The caller is responsible for ensuring that this is done
 648   // in an MT-safe manner, once the previous round of use of
 649   // the terminator is finished.
 650   void reset_for_reuse();
 651   // Same as above but the number of parallel threads is set to the
 652   // given number.
 653   void reset_for_reuse(int n_threads);
 654 
 655 #ifdef TRACESPINNING
 656   static uint total_yields() { return _total_yields; }
 657   static uint total_spins() { return _total_spins; }




 484 }
 485 
 486 template <class E, MEMFLAGS F, unsigned int N>
 487 bool OverflowTaskQueue<E, F, N>::pop_overflow(E& t)
 488 {
 489   if (overflow_empty()) return false;
 490   t = overflow_stack()->pop();
 491   return true;
 492 }
 493 
 494 template <class E, MEMFLAGS F, unsigned int N>
 495 bool OverflowTaskQueue<E, F, N>::try_push_to_taskqueue(E t) {
 496   return taskqueue_t::push(t);
 497 }
 498 class TaskQueueSetSuper {
 499 protected:
 500   static int randomParkAndMiller(int* seed0);
 501 public:
 502   // Returns "true" if some TaskQueue in the set contains a task.
 503   virtual bool peek() = 0;
 504   virtual size_t tasks() = 0;
 505 };
 506 
 507 template <MEMFLAGS F> class TaskQueueSetSuperImpl: public CHeapObj<F>, public TaskQueueSetSuper {
 508 };
 509 
 510 template<class T, MEMFLAGS F>
 511 class GenericTaskQueueSet: public TaskQueueSetSuperImpl<F> {
 512 private:
 513   uint _n;
 514   T** _queues;
 515 
 516 public:
 517   typedef typename T::element_type E;
 518 
 519   GenericTaskQueueSet(int n) : _n(n) {
 520     typedef T* GenericTaskQueuePtr;
 521     _queues = NEW_C_HEAP_ARRAY(GenericTaskQueuePtr, n, F);
 522     for (int i = 0; i < n; i++) {
 523       _queues[i] = NULL;
 524     }
 525   }
 526 
 527   bool steal_best_of_2(uint queue_num, int* seed, E& t);
 528 
 529   void register_queue(uint i, T* q);
 530 
 531   T* queue(uint n);
 532 
 533   // The thread with queue number "queue_num" (and whose random number seed is
 534   // at "seed") is trying to steal a task from some other queue.  (It may try
 535   // several queues, according to some configuration parameter.)  If some steal
 536   // succeeds, returns "true" and sets "t" to the stolen task, otherwise returns
 537   // false.
 538   bool steal(uint queue_num, int* seed, E& t);
 539 
 540   bool peek();
 541   size_t tasks();
 542 
 543   uint size() const { return _n; }
 544 };
 545 
 546 template<class T, MEMFLAGS F> void
 547 GenericTaskQueueSet<T, F>::register_queue(uint i, T* q) {
 548   assert(i < _n, "index out of range.");
 549   _queues[i] = q;
 550 }
 551 
 552 template<class T, MEMFLAGS F> T*
 553 GenericTaskQueueSet<T, F>::queue(uint i) {
 554   return _queues[i];
 555 }
 556 
 557 template<class T, MEMFLAGS F> bool
 558 GenericTaskQueueSet<T, F>::steal(uint queue_num, int* seed, E& t) {
 559   for (uint i = 0; i < 2 * _n; i++) {
 560     if (steal_best_of_2(queue_num, seed, t)) {
 561       TASKQUEUE_STATS_ONLY(queue(queue_num)->stats.record_steal(true));
 562       return true;
 563     }


 581   } else if (_n == 2) {
 582     // Just try the other one.
 583     uint k = (queue_num + 1) % 2;
 584     return _queues[k]->pop_global(t);
 585   } else {
 586     assert(_n == 1, "can't be zero.");
 587     return false;
 588   }
 589 }
 590 
 591 template<class T, MEMFLAGS F>
 592 bool GenericTaskQueueSet<T, F>::peek() {
 593   // Try all the queues.
 594   for (uint j = 0; j < _n; j++) {
 595     if (_queues[j]->peek())
 596       return true;
 597   }
 598   return false;
 599 }
 600 
 601 template<class T, MEMFLAGS F>
 602 size_t GenericTaskQueueSet<T, F>::tasks() {
 603   size_t n = 0;
 604   for (uint j = 0; j < _n; j++) {
 605     n += _queues[j]->size();
 606   }
 607   return n;
 608 }
 609 
 610 // When to terminate from the termination protocol.
 611 class TerminatorTerminator: public CHeapObj<mtInternal> {
 612 public:
 613   virtual bool should_exit_termination() = 0;
 614 };
 615 
 616 // A class to aid in the termination of a set of parallel tasks using
 617 // TaskQueueSet's for work stealing.
 618 
 619 #undef TRACESPINNING
 620 
 621 class ParallelTaskTerminator: public StackObj {
 622 protected:
 623   int _n_threads;
 624   TaskQueueSetSuper* _queue_set;
 625   char _pad_before[DEFAULT_CACHE_LINE_SIZE];
 626   int _offered_termination;
 627   char _pad_after[DEFAULT_CACHE_LINE_SIZE];
 628 
 629 #ifdef TRACESPINNING
 630   static uint _total_yields;
 631   static uint _total_spins;
 632   static uint _total_peeks;
 633 #endif
 634 
 635   bool peek_in_queue_set();
 636 protected:
 637   virtual void yield();
 638   void sleep(uint millis);
 639 
 640 public:
 641 
 642   // "n_threads" is the number of threads to be terminated.  "queue_set" is a
 643   // queue sets of work queues of other threads.
 644   ParallelTaskTerminator(int n_threads, TaskQueueSetSuper* queue_set);
 645 
 646   // The current thread has no work, and is ready to terminate if everyone
 647   // else is.  If returns "true", all threads are terminated.  If returns
 648   // "false", available work has been observed in one of the task queues,
 649   // so the global task is not complete.
 650   virtual bool offer_termination() {
 651     return offer_termination(NULL);
 652   }
 653 
 654   // As above, but it also terminates if the should_exit_termination()
 655   // method of the terminator parameter returns true. If terminator is
 656   // NULL, then it is ignored.
 657   bool offer_termination(TerminatorTerminator* terminator);
 658 
 659   // Reset the terminator, so that it may be reused again.
 660   // The caller is responsible for ensuring that this is done
 661   // in an MT-safe manner, once the previous round of use of
 662   // the terminator is finished.
 663   void reset_for_reuse();
 664   // Same as above but the number of parallel threads is set to the
 665   // given number.
 666   void reset_for_reuse(int n_threads);
 667 
 668 #ifdef TRACESPINNING
 669   static uint total_yields() { return _total_yields; }
 670   static uint total_spins() { return _total_spins; }


< prev index next >