Beispiel #1
0
 protected final void releaseAllLocks(Component host_) {
   String old_ = state;
   setState(State_UNLOCKING);
   for (LockPack p_ = (LockPack) host_.locks; p_ != null; p_ = p_.next)
     if (p_.holder == this) {
       // unlock(host_, p_.target, true);
       // below is copied from unlock()
       synchronized (p_) {
         p_.holder = null;
         p_.counter = -1;
         // p_.counter is not zero, see Note 1 above
         if (p_.lockReqCount == 0) {
           continue;
         }
         p_.lockReqCount--;
         synchronized (aruntime) {
           if (aruntime.getWorkforce()) {
             p_.notify(); // dont know who's going to wake up
             aruntime.nthreadsWaiting--;
           } else aruntime.newTask(Task.createNotify(p_), this);
         }
       }
     }
   setState(old_);
 }
Beispiel #2
0
 // Notifies all the threads waiting on the object.
 protected final void notifyAll(Component host_, Object o_) {
   if (o_ == null) return;
   String old_ = state;
   setState(State_NOTIFYING);
   // sleepOn = o_;
   LockPack p_ = lookforLock(host_, o_);
   synchronized (o_) {
     // setState(State_NOTIFYING2);
     // sleepOn = null;
     if (p_.waitCount == 0) return;
     // runtime._notifyMany(o_, p_.waitCount, this);
     synchronized (aruntime) {
       if (aruntime.getWorkforce(p_.waitCount)) {
         o_.notifyAll(); // dont know who's going to wake up
         aruntime.nthreadsWaiting -= p_.waitCount;
       } else {
         int remainingWorkforce_ = aruntime.getRemainingWorkforce();
         // notify "remainingWorkforce_" threads
         for (int i = 0; i < remainingWorkforce_; i++) o_.notify();
         aruntime.nthreadsWaiting -= remainingWorkforce_;
         for (int i = p_.waitCount - remainingWorkforce_; i > 0; i--)
           aruntime.newTask(Task.createNotify(o_), this);
       }
     }
     p_.waitCount = 0;
   }
   setState(old_);
 }
Beispiel #3
0
  protected void unlock(Component host_, Object o_, boolean release_) {
    LockPack p_ = lookforLock(host_, o_);

    String old_ = state;
    setState(State_UNLOCKING);
    synchronized (p_) {
      if (release_ || --p_.counter < 0) p_.counter = 0;

      if (p_.counter == 0) {
        if (p_.lockReqCount == 0) {
          p_.holder = null;
          return;
        }
        // Note 1:
        // what if another thread grabs the lock before
        // the one being notified below?
        // p_.counter is not zero so other threads cannot just grab it
        p_.lockReqCount--;
        p_.counter = -1;
        p_.holder = null;
        synchronized (aruntime) {
          if (aruntime.getWorkforce()) {
            p_.notify(); // dont know who's going to wake up
            aruntime.nthreadsWaiting--;
          } else {
            aruntime.newTask(Task.createNotify(p_), this);
          }
        }
        // ---
      }
    }
    setState(old_);
  }
Beispiel #4
0
  // Make thread wait on the object until being notified by another thread.
  protected final void wait(Component host_, Object o_) {
    // if (nextTask != null) _semanticsError("wait(Object)");
    // looking for LockPack in host
    LockPack p_ = lookforLock(host_, o_);

    String old_ = state;
    setState(State_WAITING);
    synchronized (o_) {
      // Records the status if the thread holds the lock.
      if (waitPack == null) waitPack = new WaitPack();
      waitPack.target = p_.target;
      if (p_.holder == this) {
        waitPack.counter = p_.counter;
        // unlock(host_, o_, true/* release all grabs */);
        // below is copied from unlock()
        synchronized (p_) {
          p_.holder = null;
          if (p_.lockReqCount == 0) p_.counter = 0;
          else {
            p_.counter = -1;
            // p_.counter is not zero, see Note 1 above
            p_.lockReqCount--;
            synchronized (aruntime) {
              if (aruntime.getWorkforce()) {
                p_.notify(); // dont know who's going to wake up
                aruntime.nthreadsWaiting--;
              } else aruntime.newTask(Task.createNotify(p_), this);
            }
          }
        }
      }
      p_.waitCount++;

      // waited to be notified
      _sleepOn(o_, State_WAITING, null);

      if (isOrphan()) throw new WorkerThreadInterruptedException("Orphan thread");

      // _awakened();

      // re-grabbing the lock if necessary.
      if (waitPack.counter > 0) {
        synchronized (p_) {
          if (p_.holder != null) lock(host_, p_.target);
          else {
            p_.holder = this;
            p_.counter = waitPack.counter;
          }
        }
      }
    }

    if (p_ != null) {
      waitPack.counter = 0;
      waitPack.target = null;
    }
  }
Beispiel #5
0
  /**
   * Returns the thread that is holding the lock of the target object. The returned thread may be an
   * orphan thread from previous run. final WorkerThread getHolder(Object o_) { Component host_ =
   * getHost(); if (host_ == null) return null; LockPack p_ = lookforLock(host_, o_); return p_ ==
   * null? null: p_.holder; }
   */
  protected void yieldToRuntime() {
    synchronized (this) { // avoid racing with runtime.stop()
      if (aruntime.isSuspend())
        // go into sleep if runtime is suspended
        __sleepOn(this, State_PREACTIVE, state);
      else if (runtime.resetting) throw new WorkerThreadInterruptedException();

      aruntime.newTask(Task.createNotify(this), this);
      _sleepOn(this, State_YIELD, null);
    }
  }
Beispiel #6
0
 // Notifies the first thread waiting on the object.
 protected final void notify(Component host_, Object o_) {
   if (o_ == null) return;
   String old_ = state;
   setState(State_NOTIFYING);
   // sleepOn = o_;
   LockPack p_ = lookforLock(host_, o_);
   synchronized (o_) {
     // setState(State_NOTIFYING2);
     // sleepOn = null;
     if (p_.waitCount == 0) return;
     p_.waitCount--;
     synchronized (aruntime) {
       if (aruntime.getWorkforce()) {
         o_.notify(); // dont know who's going to wake up
         aruntime.nthreadsWaiting--;
       } else {
         aruntime.newTask(Task.createNotify(o_), this);
       }
     }
   }
   setState(old_);
 }
Beispiel #7
0
 public String _toString() {
   if (runtime == null) return StringUtil.lastSubstring(super.toString(), ".") + "," + "<orphan>";
   else
     return StringUtil.lastSubstring(super.toString(), ".")
         + "--"
         + state
         + (sleepOn == null || sleepOn == this
             ? ""
             : " on "
                 + sleepOn
                 + (waitPack != null && waitPack.target != null ? "(waiting/locking)" : ""))
         + (state == State_SLEEPING ? " until " + wakeUpTime : "")
         + "--"
         + "context="
         + mainContext()
         + "--"
         + "next_task="
         + (nextTask != null ? nextTask.toString() : "<null>")
         + "--"
         + (currentContext == mainContext ? "" : "--currentContext=" + _currentContext())
         + (returnPort == null ? "" : "--return_port=" + returnPort)
         + (sendingPort == null ? "" : "--sending_port=" + sendingPort);
 }
Beispiel #8
0
 public String info(String prefix_) {
   if (runtime == null)
     return StringUtil.lastSubstring(prefix_ + super.toString(), ".") + "," + "<orphan>";
   StringBuffer sb_ =
       new StringBuffer(
           prefix_
               + StringUtil.lastSubstring(super.toString(), ".")
               + ", "
               + state
               + (sleepOn == null || sleepOn == this
                   ? ""
                   : " on "
                       + sleepOn
                       + (waitPack != null && waitPack.target != null ? "(waiting/locking)" : ""))
               + (state == State_SLEEPING ? " until " + wakeUpTime : "")
               + "\n"
               + prefix_
               + "Context="
               + mainContext()
               + (mainContext == null ? ", " : "\n" + prefix_)
               + "Next_Task="
               + (nextTask != null ? nextTask.toString() : "<null>")
               + "\n");
   if (currentContext != mainContext)
     sb_.append(prefix_ + "CurrentContext: " + _currentContext() + "\n");
   if (returnPort != null) sb_.append(prefix_ + "return_port: " + returnPort + "\n");
   if (sendingPort != null) sb_.append(prefix_ + "sending_port: " + sendingPort + "\n");
   sb_.append(prefix_ + "Locks: " + locks());
   sb_.append(prefix_ + "#arrivals: " + totalNumEvents + "\n");
   sb_.append(prefix_ + "last_sleepOn: " + lastsleepon + "\n");
   sb_.append(
       prefix_
           + "last_wkUp_thread: "
           + (lastwakeupthread == null ? null : currentThread(lastwakeupthread))
           + "\n");
   return sb_.toString();
 }
Beispiel #9
0
/** @see ARuntime */
public class AWorkerThread extends WorkerThread {
  static boolean RECYCLING = true; // thread recycling?
  static final Task DUMMY_CONTEXT = Task.createNotify("DUMMY_TASK");
  // used in run()
  static final Task REQUEST_WAITING = Task.createNotify("REQUEST_WAITING");
  // used in _sleepUntil()
  static final Task GETTING_TASK = Task.createNotify("Getting_Task");
  static final Object SEND_RCV_REQUEST = Port.SEND_RCV_REQUEST;

  /** The worker runtime of this thread. */
  protected ARuntime aruntime;

  /** The object that this thread waits on. */
  protected transient Object sleepOn = null;

  Task nextTask; // set if next task is available; set by runtime

  double wakeUpTime = 0.0; // time to wake up, informational

  WaitPack waitPack;
  boolean beingWakedup = false; // for ForkManager to call wakeUp();

  // for debug
  // FIFOQueue stateQ = new FIFOQueue(10); // temporary
  Thread lastwakeupthread = null;
  Object lastsleepon = null;

  public AWorkerThread() {
    super();
  }

  public AWorkerThread(ThreadGroup group_, String name_) {
    super(group_, name_);
  }

  public String info(String prefix_) {
    if (runtime == null)
      return StringUtil.lastSubstring(prefix_ + super.toString(), ".") + "," + "<orphan>";
    StringBuffer sb_ =
        new StringBuffer(
            prefix_
                + StringUtil.lastSubstring(super.toString(), ".")
                + ", "
                + state
                + (sleepOn == null || sleepOn == this
                    ? ""
                    : " on "
                        + sleepOn
                        + (waitPack != null && waitPack.target != null ? "(waiting/locking)" : ""))
                + (state == State_SLEEPING ? " until " + wakeUpTime : "")
                + "\n"
                + prefix_
                + "Context="
                + mainContext()
                + (mainContext == null ? ", " : "\n" + prefix_)
                + "Next_Task="
                + (nextTask != null ? nextTask.toString() : "<null>")
                + "\n");
    if (currentContext != mainContext)
      sb_.append(prefix_ + "CurrentContext: " + _currentContext() + "\n");
    if (returnPort != null) sb_.append(prefix_ + "return_port: " + returnPort + "\n");
    if (sendingPort != null) sb_.append(prefix_ + "sending_port: " + sendingPort + "\n");
    sb_.append(prefix_ + "Locks: " + locks());
    sb_.append(prefix_ + "#arrivals: " + totalNumEvents + "\n");
    sb_.append(prefix_ + "last_sleepOn: " + lastsleepon + "\n");
    sb_.append(
        prefix_
            + "last_wkUp_thread: "
            + (lastwakeupthread == null ? null : currentThread(lastwakeupthread))
            + "\n");
    return sb_.toString();
  }

  private String currentThread(Thread t_) {
    if (t_ == null) t_ = Thread.currentThread();
    return t_.toString();
  }

  public String _toString() {
    if (runtime == null) return StringUtil.lastSubstring(super.toString(), ".") + "," + "<orphan>";
    else
      return StringUtil.lastSubstring(super.toString(), ".")
          + "--"
          + state
          + (sleepOn == null || sleepOn == this
              ? ""
              : " on "
                  + sleepOn
                  + (waitPack != null && waitPack.target != null ? "(waiting/locking)" : ""))
          + (state == State_SLEEPING ? " until " + wakeUpTime : "")
          + "--"
          + "context="
          + mainContext()
          + "--"
          + "next_task="
          + (nextTask != null ? nextTask.toString() : "<null>")
          + "--"
          + (currentContext == mainContext ? "" : "--currentContext=" + _currentContext())
          + (returnPort == null ? "" : "--return_port=" + returnPort)
          + (sendingPort == null ? "" : "--sending_port=" + sendingPort);
  }

  String mainContext() {
    if (mainContext == null) return "<null>";
    return (mainContext.port != null ? mainContext.port + "," : "")
        + (mainContext.data != null ? mainContext.data.toString() : "<null>")
        + (returnPort == null ? "" : ",return_port:" + returnPort)
        + (sendingPort == null ? "" : ",sending_port:" + sendingPort);
  }

  /** Delay the starting until the time specified later(second). */
  public void start() {
    // if (port != null) System.out.println(this + " starts: " + data);
    // runtime.startRegister(this);

    if (aruntime.isSuspend()) return;

    if (isAlive()) {
      // __wakeUp();
      synchronized (this) {
        lastsleepon = this;
        lastwakeupthread = Thread.currentThread();

        try {
          this.notify();
        } catch (Exception e_) {
          drcl.Debug.error(this, "start()| " + e_, false);
        }
      }
    } else {
      // the thread is newly created
      setState(State_INACTIVE);
      super.start();
    }
  }

  final void setWakeupTime(double time_) {
    wakeUpTime = time_;
  }

  final double getWakeupTime() {
    return wakeUpTime;
  }

  /** */
  protected final void __sleepOn(Object sleepOn_, String prestate_, String poststate_) {
    sleepOn = sleepOn_;
    if (prestate_ != null) {
      if (poststate_ == null) poststate_ = state;
      setState(prestate_);
    }
    synchronized (sleepOn) {
      try {
        sleepOn.wait();
      } catch (InterruptedException e_) { // worker runtime is being reset
        throw new WorkerThreadInterruptedException();
      }
    }
    if (poststate_ != null) setState(poststate_);
    sleepOn = null;
  }

  /** Standard Thread.run(). */
  public /*final*/ void run() {
    if (Thread.currentThread() != this) {
      throw new WorkerThreadException(
          "not run() by the owning thread.  Current thread:"
              + Thread.currentThread()
              + "---owning thread:"
              + this);
    }

    try {
      if (aruntime.debug && aruntime.isDebugEnabledAt(ARuntime.Debug_THREAD))
        aruntime.println(ARuntime.Debug_THREAD, this, "THREAD STARTS");

      for (; ; ) {

        // Note:
        // getTask() and recycle() must happen atomically because
        // during the time after this thread cannot get more tasks
        // from runtime.getTask() and before it goes to recycle() to
        // return workforce, another thread may produce a new task in
        // the ready queue (without this thread knowing it) and that
        // thread goes to the waiting state.  Due to this racing,
        // the simulation could be stalled as no thread is actively
        // running to execute the new task in the ready queue.
        synchronized (aruntime) {
          if (mainContext == null || mainContext == DUMMY_CONTEXT) {
            // grab a task from worker pool
            nextTask = GETTING_TASK;
            // XXX: temporary for debug
            nextTask = aruntime.getTask(mainContext == null);
            if (nextTask != null) {
              // so null wont override DUMMY_CONTEXT
              mainContext = nextTask;
              nextTask = null;
            } else {
              setState(State_RECYCLING);
              sleepOn = this;
              aruntime.recycle(this);
              // return workforce in recycle()
            }
          }
        }

        if (state == State_RECYCLING) {
          setState(State_INACTIVE);
          // BOOKMARK1:
          // At this point, other threads may assign a new task
          // to this thread and start this thread, so check if
          // mainContext is being assigned within
          // the following synchronized claus
          synchronized (this) {
            if (mainContext == DUMMY_CONTEXT) mainContext = null;

            if (mainContext == null) {
              __sleepOn(this, State_INACTIVE, State_INACTIVE);
              continue;
            } else sleepOn = null;
          }
        }

        if (runtime.resetting) {
          throw new WorkerThreadInterruptedException();
        } else if (aruntime.isSuspend()) {
          // go into sleep if runtime is suspended
          synchronized (this) {
            __sleepOn(this, State_PREACTIVE, State_ACTIVE);
          }
        }

        if (mainContext.threadGroup != null) {
          if (mainContext instanceof TaskNotify) {
            // mainContext is TaskNotify:
            // the object to be notified on is in "data"
            synchronized (mainContext.data) {
              if (aruntime.debug && aruntime.isDebugEnabledAt(ARuntime.Debug_THREAD))
                aruntime.println(
                    ARuntime.Debug_THREAD,
                    this,
                    "EXECUTING notify:" + mainContext.data + "," + System.currentTimeMillis());
              mainContext.data.notify();
              aruntime.nthreadsWaiting--;
            }
            mainContext = null;
            // workforce transfered to the waked up thread
            continue;
          } else if (getThreadGroup() != mainContext.threadGroup) {
            aruntime.immediatelyStart(mainContext);
            mainContext = null;
            // workforce transfered to new thread
            continue;
          }
        }

        if (aruntime.debug && aruntime.isDebugEnabledAt(ARuntime.Debug_THREAD))
          aruntime.println(ARuntime.Debug_THREAD, this, "EXECUTING:" + mainContext);

        setState(State_ACTIVE);

        // runtime.runCheck(this);
        String method_ = "process()";
        currentContext = mainContext;
        returnPort = currentContext.returnPort;
        // from server port, new context
        try {
          mainContext.execute(this);
        } catch (NullPointerException e_) {
          if (runtime == null) return;
          e_.printStackTrace();
          drcl.Debug.error(info());
        } catch (Exception e_) {
          e_.printStackTrace();
          drcl.Debug.error(info());
        } catch (SendReceiveException e_) {
          e_.printStackTrace();
          drcl.Debug.error(info());
        }
        currentContext.port = null;
        currentContext.data = null;

        finishing();
        mainContext = DUMMY_CONTEXT;
        // to maintain the ownership of workforce

        if (!RECYCLING) {
          aruntime.remove(this);
          break;
        }

        if (nextTask != null) {
          // error checking
          if (mainContext != null && mainContext != DUMMY_CONTEXT)
            drcl.Debug.systemFatalError("task assigned to occupied thread:" + this);
          mainContext = nextTask;
          nextTask = null;
        }
      } // for(;;)
      drcl.Debug.systemFatalError("Unexpected finish at " + this);
    } catch (WorkerThreadInterruptedException e_) {
      // if (!runtime.resetting) {
      //  e_.printStackTrace();
      //  drcl.Debug.systemFatalError(
      //    "AWorkerThread terminates abnormally, " + this
      //      + "\nManager: " + runtime.diag());
      // }
      // Will releaseAllLocks()/cancelAllWaits() clean up the lock
      //   structure in components?
      // Not if the thread comes across multiple components...
      if (mainContext != null && mainContext.port != null) releaseAllLocks(mainContext.port.host);
      aruntime.remove(this);
    } catch (NullPointerException e_) {
      if (runtime != null) {
        e_.printStackTrace();
        drcl.Debug.error(info());
      }
    }
    runtime = null; // become an orphan
    aruntime = null;
  }

  //
  static void ___SUBCLASS_OVERRIDES___() {}
  //

  void _sleepUntil(double time_, String poststate_) {
    if (poststate_ == null) poststate_ = state;

    setWakeupTime(time_);
    // set the following two lines before calling
    // runtime.threadRequestsWaiting() to avoid racing
    // (see codes below)
    if (sleepOn == null) sleepOn = this;
    // for wait(Object, double), sleepOn is preset
    synchronized (sleepOn) {
      if (nextTask != null) _semanticsError("sleep()");
      if (aruntime.threadRequestsSleeping(this, time_)) {
        __sleepOn(sleepOn, State_SLEEPING, State_AWAKENING);
        // runtime.threadAwakeFromSleeping(this);
        if (aruntime.debug && aruntime.isDebugEnabledAt(aruntime.Debug_Q))
          aruntime.println(
              aruntime.Debug_Q, this, "awaked from finite sleep, " + _currentContext());
      }
      setWakeupTime(Double.NaN);
    }
    setState(poststate_);
  }

  void _sleepOn(Object sleepOn_, String prestate_, String poststate_) {
    if (poststate_ == null) poststate_ = state;

    sleepOn = sleepOn_;
    synchronized (sleepOn) {
      if (nextTask != null) _semanticsError("wait()");
      aruntime.threadBecomesWaiting(this);
      __sleepOn(sleepOn_, prestate_, State_AWAKENING);
      // runtime.threadAwakeFromWaiting(this);
      if (aruntime.debug && aruntime.isDebugEnabledAt(aruntime.Debug_Q))
        aruntime.println(
            aruntime.Debug_Q, this, "awaked from indefinite sleep: " + _currentContext());
    }
    setState(poststate_);
  }

  // protected void _awakened()
  // {}

  //
  static void ___API_FOR_COMPONENT___() {}
  //

  protected final void sleepFor(double time_) {
    // if (nextTask != null) _semanticsError("sleepFor(double)");
    _sleepUntil(runtime.getTime() + time_, State_AWAKENING);
    // _awakened();
    setState(State_ACTIVE);
  }

  protected final void sleepUntil(double time_) {
    // if (nextTask != null) _semanticsError("sleepUntil(double)");
    _sleepUntil(time_, State_AWAKENING);
    // _awakened();
    setState(State_ACTIVE);
  }

  /** Let go of the thread from sleep in idle. */
  public void kill() {
    if (isAlive()) interrupt();
    else aruntime.remove(this);
  }

  //
  static void ___EVENTS___() {}
  // Identify the events to make it easier to do simulation extension.
  //

  protected void changeCurrentContext(Port port_, Object data_, String state_) {
    // mainContext = new Task(port_, data_, mainContext.type, 0.0);
    if (currentContext == mainContext || currentContext == null)
      currentContext = new TaskReceive(port_, data_);
    else {
      currentContext.data = data_;
      currentContext.port = port_;
    }
    if (state_ != null) state = state_;
    ;
    if (aruntime.debug && aruntime.isDebugEnabledAt(ARuntime.Debug_THREAD))
      aruntime.println(
          ARuntime.Debug_THREAD,
          this,
          "currentContext ---> " + "state:" + state + "," + _currentContext());
  }

  String _currentContext() {
    if (currentContext == null || currentContext.data == null && currentContext.port == null)
      return "<null>";
    else
      return "PORT:"
          + currentContext.port
          + ",DATA:"
          + drcl.util.StringUtil.toString(currentContext.data);
  }

  public final boolean isReadyForNextTask() {
    return (state == State_FINISHING || state == State_INACTIVE) && nextTask == null;
  }

  //
  static void ___INFO___() {}
  //

  /*
  public final Component getHost()
  {
    return currentContext == null? null:
        (currentContext.port == null?
         (currentContext.data instanceof Component?
          (Component)currentContext.data: null):
          currentContext.port.host);
  }
  */

  //
  static void ___SYNC_APIS___() {}
  //

  private void _semanticsError(String method_) {
    drcl.Debug.fatalError(
        "Calling "
            + method_
            + " after doLastSending()/finishing() is prohibited.\n"
            + "Current_thread:"
            + this
            + "\n");
  }

  // String msg = "<nothing>";  // temporary
  // public String msg() { return msg; } // temporary

  public final String locks() {
    // XXX
    return "<not implemented yet>\n";
  }

  /*
  public static class LockPack implements Component.Locks
  {
    public Object target;
    public WorkerThread holder;
    public int counter; // # of times "holder" grabs the lock of "target"
    public int lockReqCount; // # of threads waiting for lock of "target"
    public int waitCount; // # of threads waiting on "target"
    public LockPack next;

    public LockPack(Object target_)
    {
      target = target_;
    }

    public String printAll()
    {
      LockPack p_ = this;
      StringBuffer sb_ = new StringBuffer();
      while (p_ != null) {
        sb_.append("   " + p_.target + ": " + p_.holder + ", count="
          + p_.counter + ", waitCount=" + p_.waitCount + "\n");
        p_ = p_.next;
      }
      return sb_.toString();
    }

    public String toString()
    { return "LockPack: " + target + ", holder=" + ", " + counter
        + ", " + lockReqCount + ", " + waitCount; }
  }
  */

  // store counterparts in LockPack that are reset when this thread
  // 'wait()' on something
  class WaitPack {
    Object target;
    // WorkerThread next; // next thread in waiting chain
    int counter;

    public WaitPack() {}
  }

  // Looking for LockPack in host.
  // Create one if necessary.
  private LockPack lookforLock(Component host_, Object o_) {
    LockPack p_ = null;
    // if (host_.locks != null) {
    //  p_ = (LockPack)host_.locks;
    //  while (p_ != null && p_.target != o_) p_ = p_.next;
    // }
    // if (p_ == null) {
    // First time the object is locked.
    // Search again in the synchronized claus to avoid racing.
    // Create one if it is still not there.
    synchronized (host_) {
      if (host_.locks != null) {
        p_ = (LockPack) host_.locks;
        while (p_ != null && p_.target != o_) p_ = p_.next;
      }
      if (p_ == null) {
        p_ = new LockPack(o_);
        p_.next = (LockPack) host_.locks;
        host_.locks = p_;
      }
    }
    // }
    return p_;
  }

  protected final void lock(Component host_, Object o_) {
    // looking for LockPack in host
    LockPack p_ = lookforLock(host_, o_);

    // No need to grab p_'s monitor if thread is already the lock holder.
    if (p_.holder == this) {
      p_.counter++;
      return;
    }

    String old_ = state;
    synchronized (p_) {
      // the lock holder may be an orphan from previous run
      // if (p_.holder == null || p_.holder.isOrphan()) {
      if (p_.counter == 0 || (p_.holder != null && p_.holder.isOrphan())) {
        // thread becomes the lock holder
        p_.holder = this;
        p_.counter = 1;
        return;
      }

      // if (nextTask != null) _semanticsError("lock(Object)");

      // Else:
      // 1. add thread itself to the waiting queue;
      // 2. going into sleep;
      // 3. getting the lock after awake;

      // p_.qWaiting.enqueue(this);
      p_.lockReqCount++;
      if (waitPack == null) waitPack = new WaitPack();
      waitPack.target = p_.target; // for debugging only
      _sleepOn(p_, State_LOCKING, null); // wait for lock
      waitPack.target = null;
      // p_.qWaiting.remove(this);
      if (isOrphan()) {
        p_.notify();
        return;
      }
      p_.holder = this;
      p_.counter = 1;
      // _awakened();
    }
  }

  protected final void unlock(Component host_, Object o_) {
    unlock(host_, o_, false);
  }

  protected void unlock(Component host_, Object o_, boolean release_) {
    LockPack p_ = lookforLock(host_, o_);

    String old_ = state;
    setState(State_UNLOCKING);
    synchronized (p_) {
      if (release_ || --p_.counter < 0) p_.counter = 0;

      if (p_.counter == 0) {
        if (p_.lockReqCount == 0) {
          p_.holder = null;
          return;
        }
        // Note 1:
        // what if another thread grabs the lock before
        // the one being notified below?
        // p_.counter is not zero so other threads cannot just grab it
        p_.lockReqCount--;
        p_.counter = -1;
        p_.holder = null;
        synchronized (aruntime) {
          if (aruntime.getWorkforce()) {
            p_.notify(); // dont know who's going to wake up
            aruntime.nthreadsWaiting--;
          } else {
            aruntime.newTask(Task.createNotify(p_), this);
          }
        }
        // ---
      }
    }
    setState(old_);
  }

  protected final void releaseAllLocks(Component host_) {
    String old_ = state;
    setState(State_UNLOCKING);
    for (LockPack p_ = (LockPack) host_.locks; p_ != null; p_ = p_.next)
      if (p_.holder == this) {
        // unlock(host_, p_.target, true);
        // below is copied from unlock()
        synchronized (p_) {
          p_.holder = null;
          p_.counter = -1;
          // p_.counter is not zero, see Note 1 above
          if (p_.lockReqCount == 0) {
            continue;
          }
          p_.lockReqCount--;
          synchronized (aruntime) {
            if (aruntime.getWorkforce()) {
              p_.notify(); // dont know who's going to wake up
              aruntime.nthreadsWaiting--;
            } else aruntime.newTask(Task.createNotify(p_), this);
          }
        }
      }
    setState(old_);
  }

  // Make thread wait on the object until being notified by another thread.
  protected final void wait(Component host_, Object o_) {
    // if (nextTask != null) _semanticsError("wait(Object)");
    // looking for LockPack in host
    LockPack p_ = lookforLock(host_, o_);

    String old_ = state;
    setState(State_WAITING);
    synchronized (o_) {
      // Records the status if the thread holds the lock.
      if (waitPack == null) waitPack = new WaitPack();
      waitPack.target = p_.target;
      if (p_.holder == this) {
        waitPack.counter = p_.counter;
        // unlock(host_, o_, true/* release all grabs */);
        // below is copied from unlock()
        synchronized (p_) {
          p_.holder = null;
          if (p_.lockReqCount == 0) p_.counter = 0;
          else {
            p_.counter = -1;
            // p_.counter is not zero, see Note 1 above
            p_.lockReqCount--;
            synchronized (aruntime) {
              if (aruntime.getWorkforce()) {
                p_.notify(); // dont know who's going to wake up
                aruntime.nthreadsWaiting--;
              } else aruntime.newTask(Task.createNotify(p_), this);
            }
          }
        }
      }
      p_.waitCount++;

      // waited to be notified
      _sleepOn(o_, State_WAITING, null);

      if (isOrphan()) throw new WorkerThreadInterruptedException("Orphan thread");

      // _awakened();

      // re-grabbing the lock if necessary.
      if (waitPack.counter > 0) {
        synchronized (p_) {
          if (p_.holder != null) lock(host_, p_.target);
          else {
            p_.holder = this;
            p_.counter = waitPack.counter;
          }
        }
      }
    }

    if (p_ != null) {
      waitPack.counter = 0;
      waitPack.target = null;
    }
  }

  // Notifies the first thread waiting on the object.
  protected final void notify(Component host_, Object o_) {
    if (o_ == null) return;
    String old_ = state;
    setState(State_NOTIFYING);
    // sleepOn = o_;
    LockPack p_ = lookforLock(host_, o_);
    synchronized (o_) {
      // setState(State_NOTIFYING2);
      // sleepOn = null;
      if (p_.waitCount == 0) return;
      p_.waitCount--;
      synchronized (aruntime) {
        if (aruntime.getWorkforce()) {
          o_.notify(); // dont know who's going to wake up
          aruntime.nthreadsWaiting--;
        } else {
          aruntime.newTask(Task.createNotify(o_), this);
        }
      }
    }
    setState(old_);
  }

  // Notifies all the threads waiting on the object.
  protected final void notifyAll(Component host_, Object o_) {
    if (o_ == null) return;
    String old_ = state;
    setState(State_NOTIFYING);
    // sleepOn = o_;
    LockPack p_ = lookforLock(host_, o_);
    synchronized (o_) {
      // setState(State_NOTIFYING2);
      // sleepOn = null;
      if (p_.waitCount == 0) return;
      // runtime._notifyMany(o_, p_.waitCount, this);
      synchronized (aruntime) {
        if (aruntime.getWorkforce(p_.waitCount)) {
          o_.notifyAll(); // dont know who's going to wake up
          aruntime.nthreadsWaiting -= p_.waitCount;
        } else {
          int remainingWorkforce_ = aruntime.getRemainingWorkforce();
          // notify "remainingWorkforce_" threads
          for (int i = 0; i < remainingWorkforce_; i++) o_.notify();
          aruntime.nthreadsWaiting -= remainingWorkforce_;
          for (int i = p_.waitCount - remainingWorkforce_; i > 0; i--)
            aruntime.newTask(Task.createNotify(o_), this);
        }
      }
      p_.waitCount = 0;
    }
    setState(old_);
  }

  /**
   * Returns the thread that is holding the lock of the target object. The returned thread may be an
   * orphan thread from previous run. final WorkerThread getHolder(Object o_) { Component host_ =
   * getHost(); if (host_ == null) return null; LockPack p_ = lookforLock(host_, o_); return p_ ==
   * null? null: p_.holder; }
   */
  protected void yieldToRuntime() {
    synchronized (this) { // avoid racing with runtime.stop()
      if (aruntime.isSuspend())
        // go into sleep if runtime is suspended
        __sleepOn(this, State_PREACTIVE, state);
      else if (runtime.resetting) throw new WorkerThreadInterruptedException();

      aruntime.newTask(Task.createNotify(this), this);
      _sleepOn(this, State_YIELD, null);
    }
  }

  //
  static void ___STATE___() {}
  //

  protected final void setState(String new_) {
    if (state == new_) return;

    if (aruntime.debug) aruntime.threadStateChange(this, state, new_);

    // if (stateQ.isFull()) stateQ.dequeue(); // temporary
    // stateQ.enqueue(state); // temporary
    state = new_;
  }

  // for ARuntime to stop()
  final boolean isActive() {
    return !(state == State_INACTIVE
        || state == State_SLEEPING
        || state == State_PREACTIVE
        || state == State_AWAKENING_WAITING
        || state == State_LOCKING
        || state == State_WAITING
        || state == State_YIELD);
  }

  // for ARuntime to resume()
  final boolean isInActive() {
    return state == State_INACTIVE || state == State_PREACTIVE;
  }

  // XX: Transient states, for debugging purpose.

  /** State of acquiring a lock. */
  static final String State_LOCKING = "LOCKING";
  // state of performing recycling tasks before runtime.recycle()
  static final String State_RECYCLING = "RECYCLING";
  // state of sleep before active due to suspended runtime
  static final String State_PREACTIVE = "PREACTIVE";
  // state of being awakened, but waiting for available workforce.
  static final String State_AWAKENING_WAITING = "AWAKENING-WAITING";
  // state of notifying on an object
  static final String State_NOTIFYING = "NOTIFYING(debug)";
  static final String State_NOTIFYING2 = "NOTIFYING2(debug)";
  // state of being awakened, re-grabbing workforce.
  static final String State_AWAKENING = "AWAKENING";
  // state of releasing a lock
  static final String State_UNLOCKING = "UNLOCKING(debug)";
  // state of yielding to other threads
  static final String State_YIELD = "YIELD(debug)";
}
  /** Invoked when the user presses the start button. */
  public void actionPerformed(ActionEvent evt) {
    if (evt.getActionCommand().equals("start")) {
      StartButton.setEnabled(false);
      cancelButton.setEnabled(true);
      setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
      // Instances of javax.swing.SwingWorker are not reusuable, so
      // we create new instances as needed.
      DownloadMessage theMessage =
          new DownloadMessage() {
            public void setProgress(int Progress) {
              if (myState.equals("SPLIT")) {
                progressBar.setValue(Progress);

              } else if (myState.equals("DOWNLOADREMOTE")) {
                progressBar.setValue(Progress);

              } else if (myState.equals("DOWNLOADLOCALBASE")) {
                progressBar3.setValue(Progress);

              } else if (myState.equals("TOTAL")) {
                progressBar4.setValue(Progress);
                progressBar3.setValue(0);
                progressBar2.setValue(0);
                progressBar.setValue(0);
              }
            }

            public void messageChanged(int Progress, String message) {
              setProgress(Progress);

              taskOutput.append(message + "\n");
              taskOutput.setCaretPosition(taskOutput.getDocument().getLength());

              // TODO Auto-generated method stub

            }

            public void stateChanged(String theState) {

              myState = theState;
              // TODO Auto-generated method stub

            }

            public void messageChanged(String theMessage) {
              taskOutput.append(theMessage + "\n");
              taskOutput.setCaretPosition(taskOutput.getDocument().getLength());
              // TODO Auto-generated method stub
              // TODO Auto-generated method stub

            }
          };

      task = new Task(theMessage, (String) myDownloadOptions.getSelectedItem());
      task.addPropertyChangeListener(this);
      task.execute();
    } else if (evt.getActionCommand().equals("cancel")) {
      task.cancel(false);
      //	startButton.setEnabled(true);
      //	cancelButton.setEnabled(false);

    }
  }