void clean(QNode pred, QNode s) {
		Thread w = s.waiter;
		if (w != null) { // Wake up thread
			s.waiter = null;
			if (w != Thread.currentThread()) {
				LockSupport.unpark(w);
			}
		}
		/*
		 * At any given time, exactly one node on list cannot be deleted -- the
		 * last inserted node. To accommodate this, if we cannot delete s, we
		 * save its predecessor as "cleanMe", processing the previously saved
		 * version first. At least one of node s or the node previously saved
		 * can always be processed, so this always terminates.
		 */
		while (pred.next == s) {
			QNode oldpred = reclean(); // First, help get rid of cleanMe
			QNode t = getValidatedTail();
			if (s != t) { // If not tail, try to unsplice
				QNode sn = s.next; // s.next == s means s already off list
				if (sn == s || pred.casNext(s, sn)) {
					break;
				}
			} else if (oldpred == pred || // Already saved
					oldpred == null && this.cleanMe.compareAndSet(null, pred)) {
				break; // Postpone cleaning
			}
		}
	}