src/share/vm/utilities/yieldingWorkgroup.hpp

Thu, 20 Nov 2008 16:56:09 -0800

author
ysr
date
Thu, 20 Nov 2008 16:56:09 -0800
changeset 888
c96030fff130
parent 777
37f87013dfd8
child 1907
c18cbe5936b8
permissions
-rw-r--r--

6684579: SoftReference processing can be made more efficient
Summary: For current soft-ref clearing policies, we can decide at marking time if a soft-reference will definitely not be cleared, postponing the decision of whether it will definitely be cleared to the final reference processing phase. This can be especially beneficial in the case of concurrent collectors where the marking is usually concurrent but reference processing is usually not.
Reviewed-by: jmasa

duke@435 1 /*
duke@435 2 * Copyright 2005 Sun Microsystems, Inc. All Rights Reserved.
duke@435 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
duke@435 4 *
duke@435 5 * This code is free software; you can redistribute it and/or modify it
duke@435 6 * under the terms of the GNU General Public License version 2 only, as
duke@435 7 * published by the Free Software Foundation.
duke@435 8 *
duke@435 9 * This code is distributed in the hope that it will be useful, but WITHOUT
duke@435 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
duke@435 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
duke@435 12 * version 2 for more details (a copy is included in the LICENSE file that
duke@435 13 * accompanied this code).
duke@435 14 *
duke@435 15 * You should have received a copy of the GNU General Public License version
duke@435 16 * 2 along with this work; if not, write to the Free Software Foundation,
duke@435 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
duke@435 18 *
duke@435 19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
duke@435 20 * CA 95054 USA or visit www.sun.com if you need additional information or
duke@435 21 * have any questions.
duke@435 22 *
duke@435 23 */
duke@435 24
duke@435 25
duke@435 26 // Forward declarations
duke@435 27 class YieldingFlexibleWorkGang;
duke@435 28
duke@435 29 // Status of tasks
duke@435 30 enum Status {
duke@435 31 INACTIVE,
duke@435 32 ACTIVE,
duke@435 33 YIELDING,
duke@435 34 YIELDED,
duke@435 35 ABORTING,
duke@435 36 ABORTED,
duke@435 37 COMPLETING,
duke@435 38 COMPLETED
duke@435 39 };
duke@435 40
duke@435 41 // Class YieldingFlexibleGangWorker:
duke@435 42 // Several instances of this class run in parallel as workers for a gang.
duke@435 43 class YieldingFlexibleGangWorker: public GangWorker {
duke@435 44 public:
duke@435 45 // Ctor
duke@435 46 YieldingFlexibleGangWorker(AbstractWorkGang* gang, int id) :
duke@435 47 GangWorker(gang, id) { }
duke@435 48
duke@435 49 public:
duke@435 50 YieldingFlexibleWorkGang* yf_gang() const
duke@435 51 { return (YieldingFlexibleWorkGang*)gang(); }
duke@435 52
duke@435 53 protected: // Override from parent class
duke@435 54 virtual void loop();
duke@435 55 };
duke@435 56
duke@435 57 // An abstract task to be worked on by a flexible work gang,
duke@435 58 // and where the workers will periodically yield, usually
duke@435 59 // in response to some condition that is signalled by means
duke@435 60 // that are specific to the task at hand.
duke@435 61 // You subclass this to supply your own work() method.
duke@435 62 // A second feature of this kind of work gang is that
duke@435 63 // it allows for the signalling of certain exceptional
duke@435 64 // conditions that may be encountered during the performance
duke@435 65 // of the task and that may require the task at hand to be
duke@435 66 // `aborted' forthwith. Finally, these gangs are `flexible'
duke@435 67 // in that they can operate at partial capacity with some
duke@435 68 // gang workers waiting on the bench; in other words, the
duke@435 69 // size of the active worker pool can flex (up to an apriori
duke@435 70 // maximum) in response to task requests at certain points.
duke@435 71 // The last part (the flexible part) has not yet been fully
duke@435 72 // fleshed out and is a work in progress.
duke@435 73 class YieldingFlexibleGangTask: public AbstractGangTask {
duke@435 74 Status _status;
duke@435 75 YieldingFlexibleWorkGang* _gang;
duke@435 76 int _actual_size; // size of gang obtained
duke@435 77
duke@435 78 protected:
duke@435 79 int _requested_size; // size of gang requested
duke@435 80
duke@435 81 // Constructor and desctructor: only construct subclasses.
duke@435 82 YieldingFlexibleGangTask(const char* name): AbstractGangTask(name),
duke@435 83 _status(INACTIVE),
duke@435 84 _gang(NULL),
duke@435 85 _requested_size(0) { }
duke@435 86
duke@435 87 virtual ~YieldingFlexibleGangTask() { }
duke@435 88
duke@435 89 friend class YieldingFlexibleWorkGang;
duke@435 90 friend class YieldingFlexibleGangWorker;
duke@435 91 NOT_PRODUCT(virtual bool is_YieldingFlexibleGang_task() const {
duke@435 92 return true;
duke@435 93 })
duke@435 94
duke@435 95 void set_status(Status s) {
duke@435 96 _status = s;
duke@435 97 }
duke@435 98 YieldingFlexibleWorkGang* gang() {
duke@435 99 return _gang;
duke@435 100 }
duke@435 101 void set_gang(YieldingFlexibleWorkGang* gang) {
duke@435 102 assert(_gang == NULL || gang == NULL, "Clobber without intermediate reset?");
duke@435 103 _gang = gang;
duke@435 104 }
duke@435 105
duke@435 106 public:
duke@435 107 // The abstract work method.
duke@435 108 // The argument tells you which member of the gang you are.
duke@435 109 virtual void work(int i) = 0;
duke@435 110
duke@435 111 // Subclasses should call the parent's yield() method
duke@435 112 // after having done any work specific to the subclass.
duke@435 113 virtual void yield();
duke@435 114
duke@435 115 // An abstract method supplied by
duke@435 116 // a concrete sub-class which is used by the coordinator
duke@435 117 // to do any "central yielding" work.
duke@435 118 virtual void coordinator_yield() = 0;
duke@435 119
duke@435 120 // Subclasses should call the parent's abort() method
duke@435 121 // after having done any work specific to the sunbclass.
duke@435 122 virtual void abort();
duke@435 123
duke@435 124 Status status() const { return _status; }
duke@435 125 bool yielded() const { return _status == YIELDED; }
duke@435 126 bool completed() const { return _status == COMPLETED; }
duke@435 127 bool aborted() const { return _status == ABORTED; }
duke@435 128 bool active() const { return _status == ACTIVE; }
duke@435 129
duke@435 130 int requested_size() const { return _requested_size; }
duke@435 131 int actual_size() const { return _actual_size; }
duke@435 132
duke@435 133 void set_requested_size(int sz) { _requested_size = sz; }
duke@435 134 void set_actual_size(int sz) { _actual_size = sz; }
duke@435 135 };
duke@435 136
duke@435 137 // Class YieldingWorkGang: A subclass of WorkGang.
duke@435 138 // In particular, a YieldingWorkGang is made up of
duke@435 139 // YieldingGangWorkers, and provides infrastructure
duke@435 140 // supporting yielding to the "GangOverseer",
duke@435 141 // being the thread that orchestrates the WorkGang via run_task().
duke@435 142 class YieldingFlexibleWorkGang: public AbstractWorkGang {
duke@435 143 // Here's the public interface to this class.
duke@435 144 public:
duke@435 145 // Constructor and destructor.
ysr@777 146 YieldingFlexibleWorkGang(const char* name, int workers,
ysr@777 147 bool are_GC_task_threads);
duke@435 148
duke@435 149 YieldingFlexibleGangTask* yielding_task() const {
duke@435 150 assert(task() == NULL || task()->is_YieldingFlexibleGang_task(),
duke@435 151 "Incorrect cast");
duke@435 152 return (YieldingFlexibleGangTask*)task();
duke@435 153 }
duke@435 154 // Run a task; returns when the task is done, or the workers yield,
duke@435 155 // or the task is aborted, or the work gang is terminated via stop().
duke@435 156 // A task that has been yielded can be continued via this same interface
duke@435 157 // by using the same task repeatedly as the argument to the call.
duke@435 158 // It is expected that the YieldingFlexibleGangTask carries the appropriate
duke@435 159 // continuation information used by workers to continue the task
duke@435 160 // from its last yield point. Thus, a completed task will return
duke@435 161 // immediately with no actual work having been done by the workers.
duke@435 162 void run_task(AbstractGangTask* task) {
duke@435 163 guarantee(false, "Use start_task instead");
duke@435 164 }
duke@435 165 void start_task(YieldingFlexibleGangTask* new_task);
duke@435 166 void continue_task(YieldingFlexibleGangTask* gang_task);
duke@435 167
duke@435 168 // Abort a currently running task, if any; returns when all the workers
duke@435 169 // have stopped working on the current task and have returned to their
duke@435 170 // waiting stations.
duke@435 171 void abort_task();
duke@435 172
duke@435 173 // Yield: workers wait at their current working stations
duke@435 174 // until signalled to proceed by the overseer.
duke@435 175 void yield();
duke@435 176
duke@435 177 // Abort: workers are expected to return to their waiting
duke@435 178 // stations, whence they are ready for the next task dispatched
duke@435 179 // by the overseer.
duke@435 180 void abort();
duke@435 181
duke@435 182 private:
duke@435 183 // The currently active workers in this gang.
duke@435 184 // This is a number that is dynamically adjusted by
duke@435 185 // the run_task() method at each subsequent invocation,
duke@435 186 // using data in the YieldingFlexibleGangTask.
duke@435 187 int _active_workers;
duke@435 188 int _yielded_workers;
duke@435 189 void wait_for_gang();
duke@435 190
duke@435 191 public:
duke@435 192 // Accessors for fields
duke@435 193 int active_workers() const {
duke@435 194 return _active_workers;
duke@435 195 }
duke@435 196
duke@435 197 int yielded_workers() const {
duke@435 198 return _yielded_workers;
duke@435 199 }
duke@435 200
duke@435 201 private:
duke@435 202 friend class YieldingFlexibleGangWorker;
duke@435 203 void reset(); // NYI
duke@435 204 };

mercurial