1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/share/vm/gc_implementation/parallelScavenge/gcTaskManager.hpp Sat Dec 01 00:00:00 2007 +0000 1.3 @@ -0,0 +1,638 @@ 1.4 +/* 1.5 + * Copyright 2002-2007 Sun Microsystems, Inc. All Rights Reserved. 1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.7 + * 1.8 + * This code is free software; you can redistribute it and/or modify it 1.9 + * under the terms of the GNU General Public License version 2 only, as 1.10 + * published by the Free Software Foundation. 1.11 + * 1.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 1.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1.15 + * version 2 for more details (a copy is included in the LICENSE file that 1.16 + * accompanied this code). 1.17 + * 1.18 + * You should have received a copy of the GNU General Public License version 1.19 + * 2 along with this work; if not, write to the Free Software Foundation, 1.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1.21 + * 1.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 1.23 + * CA 95054 USA or visit www.sun.com if you need additional information or 1.24 + * have any questions. 1.25 + * 1.26 + */ 1.27 + 1.28 +// 1.29 +// The GCTaskManager is a queue of GCTasks, and accessors 1.30 +// to allow the queue to be accessed from many threads. 1.31 +// 1.32 + 1.33 +// Forward declarations of types defined in this file. 1.34 +class GCTask; 1.35 +class GCTaskQueue; 1.36 +class SynchronizedGCTaskQueue; 1.37 +class GCTaskManager; 1.38 +class NotifyDoneClosure; 1.39 +// Some useful subclasses of GCTask. You can also make up your own. 1.40 +class NoopGCTask; 1.41 +class BarrierGCTask; 1.42 +class ReleasingBarrierGCTask; 1.43 +class NotifyingBarrierGCTask; 1.44 +class WaitForBarrierGCTask; 1.45 +// A free list of Monitor*'s. 1.46 +class MonitorSupply; 1.47 + 1.48 +// Forward declarations of classes referenced in this file via pointer. 1.49 +class GCTaskThread; 1.50 +class Mutex; 1.51 +class Monitor; 1.52 +class ThreadClosure; 1.53 + 1.54 +// The abstract base GCTask. 1.55 +class GCTask : public ResourceObj { 1.56 +public: 1.57 + // Known kinds of GCTasks, for predicates. 1.58 + class Kind : AllStatic { 1.59 + public: 1.60 + enum kind { 1.61 + unknown_task, 1.62 + ordinary_task, 1.63 + barrier_task, 1.64 + noop_task 1.65 + }; 1.66 + static const char* to_string(kind value); 1.67 + }; 1.68 +private: 1.69 + // Instance state. 1.70 + const Kind::kind _kind; // For runtime type checking. 1.71 + const uint _affinity; // Which worker should run task. 1.72 + GCTask* _newer; // Tasks are on doubly-linked ... 1.73 + GCTask* _older; // ... lists. 1.74 +public: 1.75 + virtual char* name() { return (char *)"task"; } 1.76 + 1.77 + // Abstract do_it method 1.78 + virtual void do_it(GCTaskManager* manager, uint which) = 0; 1.79 + // Accessors 1.80 + Kind::kind kind() const { 1.81 + return _kind; 1.82 + } 1.83 + uint affinity() const { 1.84 + return _affinity; 1.85 + } 1.86 + GCTask* newer() const { 1.87 + return _newer; 1.88 + } 1.89 + void set_newer(GCTask* n) { 1.90 + _newer = n; 1.91 + } 1.92 + GCTask* older() const { 1.93 + return _older; 1.94 + } 1.95 + void set_older(GCTask* p) { 1.96 + _older = p; 1.97 + } 1.98 + // Predicates. 1.99 + bool is_ordinary_task() const { 1.100 + return kind()==Kind::ordinary_task; 1.101 + } 1.102 + bool is_barrier_task() const { 1.103 + return kind()==Kind::barrier_task; 1.104 + } 1.105 + bool is_noop_task() const { 1.106 + return kind()==Kind::noop_task; 1.107 + } 1.108 + void print(const char* message) const PRODUCT_RETURN; 1.109 +protected: 1.110 + // Constructors: Only create subclasses. 1.111 + // An ordinary GCTask. 1.112 + GCTask(); 1.113 + // A GCTask of a particular kind, usually barrier or noop. 1.114 + GCTask(Kind::kind kind); 1.115 + // An ordinary GCTask with an affinity. 1.116 + GCTask(uint affinity); 1.117 + // A GCTask of a particular kind, with and affinity. 1.118 + GCTask(Kind::kind kind, uint affinity); 1.119 + // We want a virtual destructor because virtual methods, 1.120 + // but since ResourceObj's don't have their destructors 1.121 + // called, we don't have one at all. Instead we have 1.122 + // this method, which gets called by subclasses to clean up. 1.123 + virtual void destruct(); 1.124 + // Methods. 1.125 + void initialize(); 1.126 +}; 1.127 + 1.128 +// A doubly-linked list of GCTasks. 1.129 +// The list is not synchronized, because sometimes we want to 1.130 +// build up a list and then make it available to other threads. 1.131 +// See also: SynchronizedGCTaskQueue. 1.132 +class GCTaskQueue : public ResourceObj { 1.133 +private: 1.134 + // Instance state. 1.135 + GCTask* _insert_end; // Tasks are enqueued at this end. 1.136 + GCTask* _remove_end; // Tasks are dequeued from this end. 1.137 + uint _length; // The current length of the queue. 1.138 + const bool _is_c_heap_obj; // Is this a CHeapObj? 1.139 +public: 1.140 + // Factory create and destroy methods. 1.141 + // Create as ResourceObj. 1.142 + static GCTaskQueue* create(); 1.143 + // Create as CHeapObj. 1.144 + static GCTaskQueue* create_on_c_heap(); 1.145 + // Destroyer. 1.146 + static void destroy(GCTaskQueue* that); 1.147 + // Accessors. 1.148 + // These just examine the state of the queue. 1.149 + bool is_empty() const { 1.150 + assert(((insert_end() == NULL && remove_end() == NULL) || 1.151 + (insert_end() != NULL && remove_end() != NULL)), 1.152 + "insert_end and remove_end don't match"); 1.153 + return insert_end() == NULL; 1.154 + } 1.155 + uint length() const { 1.156 + return _length; 1.157 + } 1.158 + // Methods. 1.159 + // Enqueue one task. 1.160 + void enqueue(GCTask* task); 1.161 + // Enqueue a list of tasks. Empties the argument list. 1.162 + void enqueue(GCTaskQueue* list); 1.163 + // Dequeue one task. 1.164 + GCTask* dequeue(); 1.165 + // Dequeue one task, preferring one with affinity. 1.166 + GCTask* dequeue(uint affinity); 1.167 +protected: 1.168 + // Constructor. Clients use factory, but there might be subclasses. 1.169 + GCTaskQueue(bool on_c_heap); 1.170 + // Destructor-like method. 1.171 + // Because ResourceMark doesn't call destructors. 1.172 + // This method cleans up like one. 1.173 + virtual void destruct(); 1.174 + // Accessors. 1.175 + GCTask* insert_end() const { 1.176 + return _insert_end; 1.177 + } 1.178 + void set_insert_end(GCTask* value) { 1.179 + _insert_end = value; 1.180 + } 1.181 + GCTask* remove_end() const { 1.182 + return _remove_end; 1.183 + } 1.184 + void set_remove_end(GCTask* value) { 1.185 + _remove_end = value; 1.186 + } 1.187 + void increment_length() { 1.188 + _length += 1; 1.189 + } 1.190 + void decrement_length() { 1.191 + _length -= 1; 1.192 + } 1.193 + void set_length(uint value) { 1.194 + _length = value; 1.195 + } 1.196 + bool is_c_heap_obj() const { 1.197 + return _is_c_heap_obj; 1.198 + } 1.199 + // Methods. 1.200 + void initialize(); 1.201 + GCTask* remove(); // Remove from remove end. 1.202 + GCTask* remove(GCTask* task); // Remove from the middle. 1.203 + void print(const char* message) const PRODUCT_RETURN; 1.204 +}; 1.205 + 1.206 +// A GCTaskQueue that can be synchronized. 1.207 +// This "has-a" GCTaskQueue and a mutex to do the exclusion. 1.208 +class SynchronizedGCTaskQueue : public CHeapObj { 1.209 +private: 1.210 + // Instance state. 1.211 + GCTaskQueue* _unsynchronized_queue; // Has-a unsynchronized queue. 1.212 + Monitor * _lock; // Lock to control access. 1.213 +public: 1.214 + // Factory create and destroy methods. 1.215 + static SynchronizedGCTaskQueue* create(GCTaskQueue* queue, Monitor * lock) { 1.216 + return new SynchronizedGCTaskQueue(queue, lock); 1.217 + } 1.218 + static void destroy(SynchronizedGCTaskQueue* that) { 1.219 + if (that != NULL) { 1.220 + delete that; 1.221 + } 1.222 + } 1.223 + // Accessors 1.224 + GCTaskQueue* unsynchronized_queue() const { 1.225 + return _unsynchronized_queue; 1.226 + } 1.227 + Monitor * lock() const { 1.228 + return _lock; 1.229 + } 1.230 + // GCTaskQueue wrapper methods. 1.231 + // These check that you hold the lock 1.232 + // and then call the method on the queue. 1.233 + bool is_empty() const { 1.234 + guarantee(own_lock(), "don't own the lock"); 1.235 + return unsynchronized_queue()->is_empty(); 1.236 + } 1.237 + void enqueue(GCTask* task) { 1.238 + guarantee(own_lock(), "don't own the lock"); 1.239 + unsynchronized_queue()->enqueue(task); 1.240 + } 1.241 + void enqueue(GCTaskQueue* list) { 1.242 + guarantee(own_lock(), "don't own the lock"); 1.243 + unsynchronized_queue()->enqueue(list); 1.244 + } 1.245 + GCTask* dequeue() { 1.246 + guarantee(own_lock(), "don't own the lock"); 1.247 + return unsynchronized_queue()->dequeue(); 1.248 + } 1.249 + GCTask* dequeue(uint affinity) { 1.250 + guarantee(own_lock(), "don't own the lock"); 1.251 + return unsynchronized_queue()->dequeue(affinity); 1.252 + } 1.253 + uint length() const { 1.254 + guarantee(own_lock(), "don't own the lock"); 1.255 + return unsynchronized_queue()->length(); 1.256 + } 1.257 + // For guarantees. 1.258 + bool own_lock() const { 1.259 + return lock()->owned_by_self(); 1.260 + } 1.261 +protected: 1.262 + // Constructor. Clients use factory, but there might be subclasses. 1.263 + SynchronizedGCTaskQueue(GCTaskQueue* queue, Monitor * lock); 1.264 + // Destructor. Not virtual because no virtuals. 1.265 + ~SynchronizedGCTaskQueue(); 1.266 +}; 1.267 + 1.268 +// This is an abstract base class for getting notifications 1.269 +// when a GCTaskManager is done. 1.270 +class NotifyDoneClosure : public CHeapObj { 1.271 +public: 1.272 + // The notification callback method. 1.273 + virtual void notify(GCTaskManager* manager) = 0; 1.274 +protected: 1.275 + // Constructor. 1.276 + NotifyDoneClosure() { 1.277 + // Nothing to do. 1.278 + } 1.279 + // Virtual destructor because virtual methods. 1.280 + virtual ~NotifyDoneClosure() { 1.281 + // Nothing to do. 1.282 + } 1.283 +}; 1.284 + 1.285 +class GCTaskManager : public CHeapObj { 1.286 + friend class ParCompactionManager; 1.287 + friend class PSParallelCompact; 1.288 + friend class PSScavenge; 1.289 + friend class PSRefProcTaskExecutor; 1.290 + friend class RefProcTaskExecutor; 1.291 +private: 1.292 + // Instance state. 1.293 + NotifyDoneClosure* _ndc; // Notify on completion. 1.294 + const uint _workers; // Number of workers. 1.295 + Monitor* _monitor; // Notification of changes. 1.296 + SynchronizedGCTaskQueue* _queue; // Queue of tasks. 1.297 + GCTaskThread** _thread; // Array of worker threads. 1.298 + uint _busy_workers; // Number of busy workers. 1.299 + uint _blocking_worker; // The worker that's blocking. 1.300 + bool* _resource_flag; // Array of flag per threads. 1.301 + uint _delivered_tasks; // Count of delivered tasks. 1.302 + uint _completed_tasks; // Count of completed tasks. 1.303 + uint _barriers; // Count of barrier tasks. 1.304 + uint _emptied_queue; // Times we emptied the queue. 1.305 + NoopGCTask* _noop_task; // The NoopGCTask instance. 1.306 + uint _noop_tasks; // Count of noop tasks. 1.307 +public: 1.308 + // Factory create and destroy methods. 1.309 + static GCTaskManager* create(uint workers) { 1.310 + return new GCTaskManager(workers); 1.311 + } 1.312 + static GCTaskManager* create(uint workers, NotifyDoneClosure* ndc) { 1.313 + return new GCTaskManager(workers, ndc); 1.314 + } 1.315 + static void destroy(GCTaskManager* that) { 1.316 + if (that != NULL) { 1.317 + delete that; 1.318 + } 1.319 + } 1.320 + // Accessors. 1.321 + uint busy_workers() const { 1.322 + return _busy_workers; 1.323 + } 1.324 + // Pun between Monitor* and Mutex* 1.325 + Monitor* monitor() const { 1.326 + return _monitor; 1.327 + } 1.328 + Monitor * lock() const { 1.329 + return _monitor; 1.330 + } 1.331 + // Methods. 1.332 + // Add the argument task to be run. 1.333 + void add_task(GCTask* task); 1.334 + // Add a list of tasks. Removes task from the argument list. 1.335 + void add_list(GCTaskQueue* list); 1.336 + // Claim a task for argument worker. 1.337 + GCTask* get_task(uint which); 1.338 + // Note the completion of a task by the argument worker. 1.339 + void note_completion(uint which); 1.340 + // Is the queue blocked from handing out new tasks? 1.341 + bool is_blocked() const { 1.342 + return (blocking_worker() != sentinel_worker()); 1.343 + } 1.344 + // Request that all workers release their resources. 1.345 + void release_all_resources(); 1.346 + // Ask if a particular worker should release its resources. 1.347 + bool should_release_resources(uint which); // Predicate. 1.348 + // Note the release of resources by the argument worker. 1.349 + void note_release(uint which); 1.350 + // Constants. 1.351 + // A sentinel worker identifier. 1.352 + static uint sentinel_worker() { 1.353 + return (uint) -1; // Why isn't there a max_uint? 1.354 + } 1.355 + 1.356 + // Execute the task queue and wait for the completion. 1.357 + void execute_and_wait(GCTaskQueue* list); 1.358 + 1.359 + void print_task_time_stamps(); 1.360 + void print_threads_on(outputStream* st); 1.361 + void threads_do(ThreadClosure* tc); 1.362 + 1.363 +protected: 1.364 + // Constructors. Clients use factory, but there might be subclasses. 1.365 + // Create a GCTaskManager with the appropriate number of workers. 1.366 + GCTaskManager(uint workers); 1.367 + // Create a GCTaskManager that calls back when there's no more work. 1.368 + GCTaskManager(uint workers, NotifyDoneClosure* ndc); 1.369 + // Make virtual if necessary. 1.370 + ~GCTaskManager(); 1.371 + // Accessors. 1.372 + uint workers() const { 1.373 + return _workers; 1.374 + } 1.375 + NotifyDoneClosure* notify_done_closure() const { 1.376 + return _ndc; 1.377 + } 1.378 + SynchronizedGCTaskQueue* queue() const { 1.379 + return _queue; 1.380 + } 1.381 + NoopGCTask* noop_task() const { 1.382 + return _noop_task; 1.383 + } 1.384 + // Bounds-checking per-thread data accessors. 1.385 + GCTaskThread* thread(uint which); 1.386 + void set_thread(uint which, GCTaskThread* value); 1.387 + bool resource_flag(uint which); 1.388 + void set_resource_flag(uint which, bool value); 1.389 + // Modifier methods with some semantics. 1.390 + // Is any worker blocking handing out new tasks? 1.391 + uint blocking_worker() const { 1.392 + return _blocking_worker; 1.393 + } 1.394 + void set_blocking_worker(uint value) { 1.395 + _blocking_worker = value; 1.396 + } 1.397 + void set_unblocked() { 1.398 + set_blocking_worker(sentinel_worker()); 1.399 + } 1.400 + // Count of busy workers. 1.401 + void reset_busy_workers() { 1.402 + _busy_workers = 0; 1.403 + } 1.404 + uint increment_busy_workers(); 1.405 + uint decrement_busy_workers(); 1.406 + // Count of tasks delivered to workers. 1.407 + uint delivered_tasks() const { 1.408 + return _delivered_tasks; 1.409 + } 1.410 + void increment_delivered_tasks() { 1.411 + _delivered_tasks += 1; 1.412 + } 1.413 + void reset_delivered_tasks() { 1.414 + _delivered_tasks = 0; 1.415 + } 1.416 + // Count of tasks completed by workers. 1.417 + uint completed_tasks() const { 1.418 + return _completed_tasks; 1.419 + } 1.420 + void increment_completed_tasks() { 1.421 + _completed_tasks += 1; 1.422 + } 1.423 + void reset_completed_tasks() { 1.424 + _completed_tasks = 0; 1.425 + } 1.426 + // Count of barrier tasks completed. 1.427 + uint barriers() const { 1.428 + return _barriers; 1.429 + } 1.430 + void increment_barriers() { 1.431 + _barriers += 1; 1.432 + } 1.433 + void reset_barriers() { 1.434 + _barriers = 0; 1.435 + } 1.436 + // Count of how many times the queue has emptied. 1.437 + uint emptied_queue() const { 1.438 + return _emptied_queue; 1.439 + } 1.440 + void increment_emptied_queue() { 1.441 + _emptied_queue += 1; 1.442 + } 1.443 + void reset_emptied_queue() { 1.444 + _emptied_queue = 0; 1.445 + } 1.446 + // Count of the number of noop tasks we've handed out, 1.447 + // e.g., to handle resource release requests. 1.448 + uint noop_tasks() const { 1.449 + return _noop_tasks; 1.450 + } 1.451 + void increment_noop_tasks() { 1.452 + _noop_tasks += 1; 1.453 + } 1.454 + void reset_noop_tasks() { 1.455 + _noop_tasks = 0; 1.456 + } 1.457 + // Other methods. 1.458 + void initialize(); 1.459 +}; 1.460 + 1.461 +// 1.462 +// Some exemplary GCTasks. 1.463 +// 1.464 + 1.465 +// A noop task that does nothing, 1.466 +// except take us around the GCTaskThread loop. 1.467 +class NoopGCTask : public GCTask { 1.468 +private: 1.469 + const bool _is_c_heap_obj; // Is this a CHeapObj? 1.470 +public: 1.471 + // Factory create and destroy methods. 1.472 + static NoopGCTask* create(); 1.473 + static NoopGCTask* create_on_c_heap(); 1.474 + static void destroy(NoopGCTask* that); 1.475 + // Methods from GCTask. 1.476 + void do_it(GCTaskManager* manager, uint which) { 1.477 + // Nothing to do. 1.478 + } 1.479 +protected: 1.480 + // Constructor. 1.481 + NoopGCTask(bool on_c_heap) : 1.482 + GCTask(GCTask::Kind::noop_task), 1.483 + _is_c_heap_obj(on_c_heap) { 1.484 + // Nothing to do. 1.485 + } 1.486 + // Destructor-like method. 1.487 + void destruct(); 1.488 + // Accessors. 1.489 + bool is_c_heap_obj() const { 1.490 + return _is_c_heap_obj; 1.491 + } 1.492 +}; 1.493 + 1.494 +// A BarrierGCTask blocks other tasks from starting, 1.495 +// and waits until it is the only task running. 1.496 +class BarrierGCTask : public GCTask { 1.497 +public: 1.498 + // Factory create and destroy methods. 1.499 + static BarrierGCTask* create() { 1.500 + return new BarrierGCTask(); 1.501 + } 1.502 + static void destroy(BarrierGCTask* that) { 1.503 + if (that != NULL) { 1.504 + that->destruct(); 1.505 + delete that; 1.506 + } 1.507 + } 1.508 + // Methods from GCTask. 1.509 + void do_it(GCTaskManager* manager, uint which); 1.510 +protected: 1.511 + // Constructor. Clients use factory, but there might be subclasses. 1.512 + BarrierGCTask() : 1.513 + GCTask(GCTask::Kind::barrier_task) { 1.514 + // Nothing to do. 1.515 + } 1.516 + // Destructor-like method. 1.517 + void destruct(); 1.518 + // Methods. 1.519 + // Wait for this to be the only task running. 1.520 + void do_it_internal(GCTaskManager* manager, uint which); 1.521 +}; 1.522 + 1.523 +// A ReleasingBarrierGCTask is a BarrierGCTask 1.524 +// that tells all the tasks to release their resource areas. 1.525 +class ReleasingBarrierGCTask : public BarrierGCTask { 1.526 +public: 1.527 + // Factory create and destroy methods. 1.528 + static ReleasingBarrierGCTask* create() { 1.529 + return new ReleasingBarrierGCTask(); 1.530 + } 1.531 + static void destroy(ReleasingBarrierGCTask* that) { 1.532 + if (that != NULL) { 1.533 + that->destruct(); 1.534 + delete that; 1.535 + } 1.536 + } 1.537 + // Methods from GCTask. 1.538 + void do_it(GCTaskManager* manager, uint which); 1.539 +protected: 1.540 + // Constructor. Clients use factory, but there might be subclasses. 1.541 + ReleasingBarrierGCTask() : 1.542 + BarrierGCTask() { 1.543 + // Nothing to do. 1.544 + } 1.545 + // Destructor-like method. 1.546 + void destruct(); 1.547 +}; 1.548 + 1.549 +// A NotifyingBarrierGCTask is a BarrierGCTask 1.550 +// that calls a notification method when it is the only task running. 1.551 +class NotifyingBarrierGCTask : public BarrierGCTask { 1.552 +private: 1.553 + // Instance state. 1.554 + NotifyDoneClosure* _ndc; // The callback object. 1.555 +public: 1.556 + // Factory create and destroy methods. 1.557 + static NotifyingBarrierGCTask* create(NotifyDoneClosure* ndc) { 1.558 + return new NotifyingBarrierGCTask(ndc); 1.559 + } 1.560 + static void destroy(NotifyingBarrierGCTask* that) { 1.561 + if (that != NULL) { 1.562 + that->destruct(); 1.563 + delete that; 1.564 + } 1.565 + } 1.566 + // Methods from GCTask. 1.567 + void do_it(GCTaskManager* manager, uint which); 1.568 +protected: 1.569 + // Constructor. Clients use factory, but there might be subclasses. 1.570 + NotifyingBarrierGCTask(NotifyDoneClosure* ndc) : 1.571 + BarrierGCTask(), 1.572 + _ndc(ndc) { 1.573 + assert(notify_done_closure() != NULL, "can't notify on NULL"); 1.574 + } 1.575 + // Destructor-like method. 1.576 + void destruct(); 1.577 + // Accessor. 1.578 + NotifyDoneClosure* notify_done_closure() const { return _ndc; } 1.579 +}; 1.580 + 1.581 +// A WaitForBarrierGCTask is a BarrierGCTask 1.582 +// with a method you can call to wait until 1.583 +// the BarrierGCTask is done. 1.584 +// This may cover many of the uses of NotifyingBarrierGCTasks. 1.585 +class WaitForBarrierGCTask : public BarrierGCTask { 1.586 +private: 1.587 + // Instance state. 1.588 + Monitor* _monitor; // Guard and notify changes. 1.589 + bool _should_wait; // true=>wait, false=>proceed. 1.590 + const bool _is_c_heap_obj; // Was allocated on the heap. 1.591 +public: 1.592 + virtual char* name() { return (char *) "waitfor-barrier-task"; } 1.593 + 1.594 + // Factory create and destroy methods. 1.595 + static WaitForBarrierGCTask* create(); 1.596 + static WaitForBarrierGCTask* create_on_c_heap(); 1.597 + static void destroy(WaitForBarrierGCTask* that); 1.598 + // Methods. 1.599 + void do_it(GCTaskManager* manager, uint which); 1.600 + void wait_for(); 1.601 +protected: 1.602 + // Constructor. Clients use factory, but there might be subclasses. 1.603 + WaitForBarrierGCTask(bool on_c_heap); 1.604 + // Destructor-like method. 1.605 + void destruct(); 1.606 + // Accessors. 1.607 + Monitor* monitor() const { 1.608 + return _monitor; 1.609 + } 1.610 + bool should_wait() const { 1.611 + return _should_wait; 1.612 + } 1.613 + void set_should_wait(bool value) { 1.614 + _should_wait = value; 1.615 + } 1.616 + bool is_c_heap_obj() { 1.617 + return _is_c_heap_obj; 1.618 + } 1.619 +}; 1.620 + 1.621 +class MonitorSupply : public AllStatic { 1.622 +private: 1.623 + // State. 1.624 + // Control multi-threaded access. 1.625 + static Mutex* _lock; 1.626 + // The list of available Monitor*'s. 1.627 + static GrowableArray<Monitor*>* _freelist; 1.628 +public: 1.629 + // Reserve a Monitor*. 1.630 + static Monitor* reserve(); 1.631 + // Release a Monitor*. 1.632 + static void release(Monitor* instance); 1.633 +private: 1.634 + // Accessors. 1.635 + static Mutex* lock() { 1.636 + return _lock; 1.637 + } 1.638 + static GrowableArray<Monitor*>* freelist() { 1.639 + return _freelist; 1.640 + } 1.641 +};