001: /*
002: * <copyright>
003: *
004: * Copyright 1997-2004 BBNT Solutions, LLC
005: * under sponsorship of the Defense Advanced Research Projects
006: * Agency (DARPA).
007: *
008: * You can redistribute this software and/or modify it under the
009: * terms of the Cougaar Open Source License as published on the
010: * Cougaar Open Source Website (www.cougaar.org).
011: *
012: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
013: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
014: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
015: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
016: * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
017: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
018: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
019: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
020: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
021: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
022: * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
023: *
024: * </copyright>
025: */
026:
027: package org.cougaar.core.thread;
028:
029: import java.util.List;
030:
031: /**
032: * This experimenatal extension of {@link Scheduler} is not currently used.
033: */
034: public class RightsPropagatingScheduler extends Scheduler {
035: private static final long MaxTime = 20; // ms
036: private int ownedRights = 0;
037: private long lastReleaseTime = 0;
038:
039: public RightsPropagatingScheduler(ThreadListenerProxy listenerProxy) {
040: super (listenerProxy);
041: }
042:
043: boolean requestRights(Scheduler requestor) {
044: TreeNode parent_node = getTreeNode().getParent();
045: boolean result;
046: if (parent_node == null) {
047: // This is the root
048: result = super .requestRights(requestor);
049: } else if (ownedRights > 0) {
050: return false;
051: } else {
052: Scheduler parent = parent_node.getScheduler(getLane());
053: result = parent.requestRights(this );
054: }
055: synchronized (this ) {
056: if (result)
057: ++ownedRights;
058: }
059: return result;
060: }
061:
062: void releaseRights(Scheduler consumer) {
063: TreeNode parent_node = getTreeNode().getParent();
064: if (parent_node == null) {
065: // This is the root
066: super .releaseRights(consumer);
067: } else {
068: long now = System.currentTimeMillis();
069: if (now - lastReleaseTime > MaxTime) {
070: releaseToParent(consumer);
071: } else {
072: offerRights(consumer);
073: }
074: }
075: }
076:
077: private void releaseToParent(Scheduler consumer) {
078: TreeNode parent_node = getTreeNode().getParent();
079: Scheduler parent = parent_node.getScheduler(getLane());
080: parent.releaseRights(this );
081: lastReleaseTime = System.currentTimeMillis();
082: synchronized (this ) {
083: --ownedRights;
084: }
085: }
086:
087: private synchronized void offerRights(Scheduler consumer) {
088: SchedulableObject handoff = getNextPending();
089: if (handoff != null) {
090: handoff.thread_start();
091: } else {
092: releaseToParent(consumer);
093: }
094: }
095:
096: // Holds the next index of the round-robin selection. A value of
097: // -1 refers to the local queue, a value >= 0 refers to the
098: // corresponding child.
099: private int currentIndex = -1;
100:
101: private SchedulableObject checkNextPending(List<TreeNode> children) {
102: SchedulableObject handoff = null;
103: if (currentIndex == -1) {
104: handoff = super .getNextPending();
105: currentIndex = children.size() == 0 ? -1 : 0;
106: } else {
107: TreeNode child_node = children.get(currentIndex++);
108: if (currentIndex == children.size())
109: currentIndex = -1;
110: Scheduler child = child_node.getScheduler(getLane());
111: handoff = child.getNextPending();
112: }
113: return handoff;
114: }
115:
116: SchedulableObject getNextPending() {
117: int initialIndex = currentIndex;
118: List<TreeNode> children = getTreeNode().getChildren();
119: SchedulableObject handoff = null;
120: // repeat-until
121: while (true) {
122: handoff = checkNextPending(children);
123: if (handoff != null)
124: return handoff;
125: if (currentIndex == initialIndex)
126: break;
127: }
128: return null;
129: }
130:
131: }
|