< prev index next >

src/hotspot/share/gc/shared/taskqueue.hpp

Print this page
rev 59131 : imported patch assert_empty


 211 private:
 212   DEFINE_PAD_MINUS_SIZE(0, DEFAULT_CACHE_LINE_SIZE, 0);
 213 
 214   // Index of the first free element after the last one pushed (mod N).
 215   volatile uint _bottom;
 216   DEFINE_PAD_MINUS_SIZE(1, DEFAULT_CACHE_LINE_SIZE, sizeof(uint));
 217 
 218   // top() is the index of the oldest pushed element (mod N), and tag()
 219   // is the associated epoch, to distinguish different modifications of
 220   // the age.  There is no available element if top() == _bottom or
 221   // (_bottom - top()) mod N == N-1; the latter indicates underflow
 222   // during concurrent pop_local/pop_global.
 223   volatile Age _age;
 224   DEFINE_PAD_MINUS_SIZE(2, DEFAULT_CACHE_LINE_SIZE, sizeof(Age));
 225 
 226   NONCOPYABLE(TaskQueueSuper);
 227 
 228 public:
 229   TaskQueueSuper() : _bottom(0), _age() {}
 230 
 231   // Return true if the TaskQueue contains any tasks.
 232   // Unreliable if there are concurrent pushes or pops.
 233   bool peek() const {
 234     return bottom_relaxed() != age_top_relaxed();
 235   }
 236 
 237   bool is_empty() const {
 238     return size() == 0;
 239   }
 240 
 241   // Return an estimate of the number of elements in the queue.
 242   // Treats pop_local/pop_global race that underflows as empty.
 243   uint size() const {
 244     return clean_size(bottom_relaxed(), age_top_relaxed());
 245   }
 246 
 247   // Discard the contents of the queue.
 248   void set_empty() {
 249     set_bottom_relaxed(0);
 250     set_age_relaxed(Age());
 251   }
 252 
 253   // Maximum number of elements allowed in the queue.  This is two less
 254   // than the actual queue size, so that a full queue can be distinguished


 409   // Try to push task t onto the queue only. Returns true if successful, false otherwise.
 410   inline bool try_push_to_taskqueue(E t);
 411 
 412   // Attempt to pop from the overflow stack; return true if anything was popped.
 413   inline bool pop_overflow(E& t);
 414 
 415   inline overflow_t* overflow_stack() { return &_overflow_stack; }
 416 
 417   inline bool taskqueue_empty() const { return taskqueue_t::is_empty(); }
 418   inline bool overflow_empty()  const { return _overflow_stack.is_empty(); }
 419   inline bool is_empty()        const {
 420     return taskqueue_empty() && overflow_empty();
 421   }
 422 
 423 private:
 424   overflow_t _overflow_stack;
 425 };
 426 
 427 class TaskQueueSetSuper {
 428 public:
 429   // Returns "true" if some TaskQueue in the set contains a task.
 430   virtual bool peek() = 0;


 431   // Tasks in queue
 432   virtual uint tasks() const = 0;
 433 };
 434 
 435 template <MEMFLAGS F> class TaskQueueSetSuperImpl: public CHeapObj<F>, public TaskQueueSetSuper {
 436 };
 437 
 438 template<class T, MEMFLAGS F>
 439 class GenericTaskQueueSet: public TaskQueueSetSuperImpl<F> {
 440 public:
 441   typedef typename T::element_type E;
 442 
 443 private:
 444   uint _n;
 445   T** _queues;
 446 
 447   bool steal_best_of_2(uint queue_num, E& t);
 448 
 449 public:
 450   GenericTaskQueueSet(uint n);
 451   ~GenericTaskQueueSet();
 452 
 453   void register_queue(uint i, T* q);
 454 
 455   T* queue(uint n);
 456 
 457   // Try to steal a task from some other queue than queue_num. It may perform several attempts at doing so.
 458   // Returns if stealing succeeds, and sets "t" to the stolen task.
 459   bool steal(uint queue_num, E& t);
 460 
 461   bool peek();
 462   uint tasks() const;

 463 
 464   uint size() const { return _n; }
 465 };
 466 
 467 template<class T, MEMFLAGS F> void
 468 GenericTaskQueueSet<T, F>::register_queue(uint i, T* q) {
 469   assert(i < _n, "index out of range.");
 470   _queues[i] = q;
 471 }
 472 
 473 template<class T, MEMFLAGS F> T*
 474 GenericTaskQueueSet<T, F>::queue(uint i) {
 475   return _queues[i];
 476 }
 477 

 478 template<class T, MEMFLAGS F>
 479 bool GenericTaskQueueSet<T, F>::peek() {
 480   // Try all the queues.
 481   for (uint j = 0; j < _n; j++) {
 482     if (_queues[j]->peek())
 483       return true;
 484   }
 485   return false;
 486 }

 487 
 488 template<class T, MEMFLAGS F>
 489 uint GenericTaskQueueSet<T, F>::tasks() const {
 490   uint n = 0;
 491   for (uint j = 0; j < _n; j++) {
 492     n += _queues[j]->size();
 493   }
 494   return n;
 495 }
 496 
 497 // When to terminate from the termination protocol.
 498 class TerminatorTerminator: public CHeapObj<mtInternal> {
 499 public:
 500   virtual bool should_exit_termination() = 0;
 501 };
 502 
 503 // This is a container class for either an oop* or a narrowOop*.
 504 // Both are pushed onto a task queue and the consumer will test is_narrow()
 505 // to determine which should be processed.
 506 class StarTask {




 211 private:
 212   DEFINE_PAD_MINUS_SIZE(0, DEFAULT_CACHE_LINE_SIZE, 0);
 213 
 214   // Index of the first free element after the last one pushed (mod N).
 215   volatile uint _bottom;
 216   DEFINE_PAD_MINUS_SIZE(1, DEFAULT_CACHE_LINE_SIZE, sizeof(uint));
 217 
 218   // top() is the index of the oldest pushed element (mod N), and tag()
 219   // is the associated epoch, to distinguish different modifications of
 220   // the age.  There is no available element if top() == _bottom or
 221   // (_bottom - top()) mod N == N-1; the latter indicates underflow
 222   // during concurrent pop_local/pop_global.
 223   volatile Age _age;
 224   DEFINE_PAD_MINUS_SIZE(2, DEFAULT_CACHE_LINE_SIZE, sizeof(Age));
 225 
 226   NONCOPYABLE(TaskQueueSuper);
 227 
 228 public:
 229   TaskQueueSuper() : _bottom(0), _age() {}
 230 
 231   // Assert the queue is empty.
 232   // Unreliable if there are concurrent pushes or pops.
 233   void assert_empty() const {
 234     assert(bottom_relaxed() == age_top_relaxed(), "not empty");
 235   }
 236 
 237   bool is_empty() const {
 238     return size() == 0;
 239   }
 240 
 241   // Return an estimate of the number of elements in the queue.
 242   // Treats pop_local/pop_global race that underflows as empty.
 243   uint size() const {
 244     return clean_size(bottom_relaxed(), age_top_relaxed());
 245   }
 246 
 247   // Discard the contents of the queue.
 248   void set_empty() {
 249     set_bottom_relaxed(0);
 250     set_age_relaxed(Age());
 251   }
 252 
 253   // Maximum number of elements allowed in the queue.  This is two less
 254   // than the actual queue size, so that a full queue can be distinguished


 409   // Try to push task t onto the queue only. Returns true if successful, false otherwise.
 410   inline bool try_push_to_taskqueue(E t);
 411 
 412   // Attempt to pop from the overflow stack; return true if anything was popped.
 413   inline bool pop_overflow(E& t);
 414 
 415   inline overflow_t* overflow_stack() { return &_overflow_stack; }
 416 
 417   inline bool taskqueue_empty() const { return taskqueue_t::is_empty(); }
 418   inline bool overflow_empty()  const { return _overflow_stack.is_empty(); }
 419   inline bool is_empty()        const {
 420     return taskqueue_empty() && overflow_empty();
 421   }
 422 
 423 private:
 424   overflow_t _overflow_stack;
 425 };
 426 
 427 class TaskQueueSetSuper {
 428 public:
 429   // Assert all queues in the set are empty.
 430   NOT_DEBUG(void assert_empty() const {})
 431   DEBUG_ONLY(virtual void assert_empty() const = 0;)
 432 
 433   // Tasks in queue
 434   virtual uint tasks() const = 0;
 435 };
 436 
 437 template <MEMFLAGS F> class TaskQueueSetSuperImpl: public CHeapObj<F>, public TaskQueueSetSuper {
 438 };
 439 
 440 template<class T, MEMFLAGS F>
 441 class GenericTaskQueueSet: public TaskQueueSetSuperImpl<F> {
 442 public:
 443   typedef typename T::element_type E;
 444 
 445 private:
 446   uint _n;
 447   T** _queues;
 448 
 449   bool steal_best_of_2(uint queue_num, E& t);
 450 
 451 public:
 452   GenericTaskQueueSet(uint n);
 453   ~GenericTaskQueueSet();
 454 
 455   void register_queue(uint i, T* q);
 456 
 457   T* queue(uint n);
 458 
 459   // Try to steal a task from some other queue than queue_num. It may perform several attempts at doing so.
 460   // Returns if stealing succeeds, and sets "t" to the stolen task.
 461   bool steal(uint queue_num, E& t);
 462 
 463   DEBUG_ONLY(virtual void assert_empty() const;)
 464 
 465   virtual uint tasks() const;
 466 
 467   uint size() const { return _n; }
 468 };
 469 
 470 template<class T, MEMFLAGS F> void
 471 GenericTaskQueueSet<T, F>::register_queue(uint i, T* q) {
 472   assert(i < _n, "index out of range.");
 473   _queues[i] = q;
 474 }
 475 
 476 template<class T, MEMFLAGS F> T*
 477 GenericTaskQueueSet<T, F>::queue(uint i) {
 478   return _queues[i];
 479 }
 480 
 481 #ifdef ASSERT
 482 template<class T, MEMFLAGS F>
 483 void GenericTaskQueueSet<T, F>::assert_empty() const {

 484   for (uint j = 0; j < _n; j++) {
 485     _queues[j]->assert_empty();

 486   }

 487 }
 488 #endif // ASSERT
 489 
 490 template<class T, MEMFLAGS F>
 491 uint GenericTaskQueueSet<T, F>::tasks() const {
 492   uint n = 0;
 493   for (uint j = 0; j < _n; j++) {
 494     n += _queues[j]->size();
 495   }
 496   return n;
 497 }
 498 
 499 // When to terminate from the termination protocol.
 500 class TerminatorTerminator: public CHeapObj<mtInternal> {
 501 public:
 502   virtual bool should_exit_termination() = 0;
 503 };
 504 
 505 // This is a container class for either an oop* or a narrowOop*.
 506 // Both are pushed onto a task queue and the consumer will test is_narrow()
 507 // to determine which should be processed.
 508 class StarTask {


< prev index next >