/** * 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); } }
/** 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(); } }
/** 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; }