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