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_); }
// 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_); }
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_); }
// 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; } }
/** * 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); } }
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 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()); }
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_; }
// 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_); }
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_); }
/** 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(); } }
/** Let go of the thread from sleep in idle. */ public void kill() { if (isAlive()) interrupt(); else aruntime.remove(this); }
/** 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; }