yieldingWorkgroup.hpp 7.3 KB
Newer Older
D
duke 已提交
1
/*
2
 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
D
duke 已提交
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
19 20 21
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
D
duke 已提交
22 23 24
 *
 */

25 26 27 28 29 30 31
#ifndef SHARE_VM_UTILITIES_YIELDINGWORKGROUP_HPP
#define SHARE_VM_UTILITIES_YIELDINGWORKGROUP_HPP

#ifndef SERIALGC
#include "utilities/workgroup.hpp"
#endif

D
duke 已提交
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63

// Forward declarations
class YieldingFlexibleWorkGang;

// Status of tasks
enum Status {
    INACTIVE,
    ACTIVE,
    YIELDING,
    YIELDED,
    ABORTING,
    ABORTED,
    COMPLETING,
    COMPLETED
};

// Class YieldingFlexibleGangWorker:
//   Several instances of this class run in parallel as workers for a gang.
class YieldingFlexibleGangWorker: public GangWorker {
public:
  // Ctor
  YieldingFlexibleGangWorker(AbstractWorkGang* gang, int id) :
    GangWorker(gang, id) { }

public:
  YieldingFlexibleWorkGang* yf_gang() const
    { return (YieldingFlexibleWorkGang*)gang(); }

protected: // Override from parent class
  virtual void loop();
};

64 65 66 67 68 69 70 71 72 73
class FlexibleGangTask: public AbstractGangTask {
  int _actual_size;                      // size of gang obtained
protected:
  int _requested_size;                   // size of gang requested
public:
 FlexibleGangTask(const char* name): AbstractGangTask(name),
    _requested_size(0) {}

  // The abstract work method.
  // The argument tells you which member of the gang you are.
74
  virtual void work(uint worker_id) = 0;
75 76 77 78 79 80 81 82

  int requested_size() const { return _requested_size; }
  int actual_size()    const { return _actual_size; }

  void set_requested_size(int sz) { _requested_size = sz; }
  void set_actual_size(int sz)    { _actual_size    = sz; }
};

D
duke 已提交
83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
// An abstract task to be worked on by a flexible work gang,
// and where the workers will periodically yield, usually
// in response to some condition that is signalled by means
// that are specific to the task at hand.
// You subclass this to supply your own work() method.
// A second feature of this kind of work gang is that
// it allows for the signalling of certain exceptional
// conditions that may be encountered during the performance
// of the task and that may require the task at hand to be
// `aborted' forthwith. Finally, these gangs are `flexible'
// in that they can operate at partial capacity with some
// gang workers waiting on the bench; in other words, the
// size of the active worker pool can flex (up to an apriori
// maximum) in response to task requests at certain points.
// The last part (the flexible part) has not yet been fully
// fleshed out and is a work in progress.
99
class YieldingFlexibleGangTask: public FlexibleGangTask {
D
duke 已提交
100 101 102 103 104
  Status _status;
  YieldingFlexibleWorkGang* _gang;

protected:
  // Constructor and desctructor: only construct subclasses.
105
  YieldingFlexibleGangTask(const char* name): FlexibleGangTask(name),
D
duke 已提交
106
    _status(INACTIVE),
107
    _gang(NULL) { }
D
duke 已提交
108

109
  ~YieldingFlexibleGangTask() { }
D
duke 已提交
110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130

  friend class YieldingFlexibleWorkGang;
  friend class YieldingFlexibleGangWorker;
  NOT_PRODUCT(virtual bool is_YieldingFlexibleGang_task() const {
    return true;
  })

  void set_status(Status s) {
    _status = s;
  }
  YieldingFlexibleWorkGang* gang() {
    return _gang;
  }
  void set_gang(YieldingFlexibleWorkGang* gang) {
    assert(_gang == NULL || gang == NULL, "Clobber without intermediate reset?");
    _gang = gang;
  }

public:
  // The abstract work method.
  // The argument tells you which member of the gang you are.
131
  virtual void work(uint worker_id) = 0;
D
duke 已提交
132 133 134 135 136 137 138 139 140 141 142 143 144 145 146

  // Subclasses should call the parent's yield() method
  // after having done any work specific to the subclass.
  virtual void yield();

  // An abstract method supplied by
  // a concrete sub-class which is used by the coordinator
  // to do any "central yielding" work.
  virtual void coordinator_yield() = 0;

  // Subclasses should call the parent's abort() method
  // after having done any work specific to the sunbclass.
  virtual void abort();

  Status status()  const { return _status; }
147
  bool yielding()  const { return _status == YIELDING; }
D
duke 已提交
148 149 150 151 152 153 154 155 156 157
  bool yielded()   const { return _status == YIELDED; }
  bool completed() const { return _status == COMPLETED; }
  bool aborted()   const { return _status == ABORTED; }
  bool active()    const { return _status == ACTIVE; }
};
// Class YieldingWorkGang: A subclass of WorkGang.
// In particular, a YieldingWorkGang is made up of
// YieldingGangWorkers, and provides infrastructure
// supporting yielding to the "GangOverseer",
// being the thread that orchestrates the WorkGang via run_task().
158
class YieldingFlexibleWorkGang: public FlexibleWorkGang {
D
duke 已提交
159 160 161
  // Here's the public interface to this class.
public:
  // Constructor and destructor.
162
  YieldingFlexibleWorkGang(const char* name, uint workers,
163
                           bool are_GC_task_threads);
D
duke 已提交
164 165 166 167 168 169

  YieldingFlexibleGangTask* yielding_task() const {
    assert(task() == NULL || task()->is_YieldingFlexibleGang_task(),
           "Incorrect cast");
    return (YieldingFlexibleGangTask*)task();
  }
170
  // Allocate a worker and return a pointer to it.
171
  GangWorker* allocate_worker(uint which);
172

D
duke 已提交
173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201
  // Run a task; returns when the task is done, or the workers yield,
  // or the task is aborted, or the work gang is terminated via stop().
  // A task that has been yielded can be continued via this same interface
  // by using the same task repeatedly as the argument to the call.
  // It is expected that the YieldingFlexibleGangTask carries the appropriate
  // continuation information used by workers to continue the task
  // from its last yield point. Thus, a completed task will return
  // immediately with no actual work having been done by the workers.
  void run_task(AbstractGangTask* task) {
    guarantee(false, "Use start_task instead");
  }
  void start_task(YieldingFlexibleGangTask* new_task);
  void continue_task(YieldingFlexibleGangTask* gang_task);

  // Abort a currently running task, if any; returns when all the workers
  // have stopped working on the current task and have returned to their
  // waiting stations.
  void abort_task();

  // Yield: workers wait at their current working stations
  // until signalled to proceed by the overseer.
  void yield();

  // Abort: workers are expected to return to their waiting
  // stations, whence they are ready for the next task dispatched
  // by the overseer.
  void abort();

private:
202
  uint _yielded_workers;
D
duke 已提交
203 204 205
  void wait_for_gang();

public:
206
  // Accessors for fields
207
  uint yielded_workers() const {
D
duke 已提交
208 209 210 211 212 213 214
    return _yielded_workers;
  }

private:
  friend class YieldingFlexibleGangWorker;
  void reset(); // NYI
};
215 216

#endif // SHARE_VM_UTILITIES_YIELDINGWORKGROUP_HPP