/* * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package nsk.share.jvmti; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.Condition; import java.util.concurrent.TimeUnit; import nsk.share.Failure; /** * Functions to set and wait for states in threads. * Used to sync main thread and debuggee thread. */ public class ThreadState { private final Lock lock = new ReentrantLock(); private final Condition cond = lock.newCondition(); private volatile String currentState; private long timeoutMs; public ThreadState(String startState, long timeoutMs) { currentState = startState; this.timeoutMs = timeoutMs; } /** * Set new state. */ public void setState(String newState) { lock.lock(); try { log(MSG_SET_STATE, newState); currentState = newState; cond.signalAll(); } finally { lock.unlock(); } } /** * Wait for the specified state. * Throws Failure if timeout. */ public void waitForState(String waitState) { lock.lock(); try { log(MSG_WAIT_STATE, waitState); while (!currentState.equals(waitState)) { if (!cond.await(timeoutMs, TimeUnit.MILLISECONDS)) { throw new Failure(format(MSG_TIMEOUT, waitState)); } } log(MSG_GOT_STATE, waitState); } catch (InterruptedException e) { e.printStackTrace(); throw new Failure(e); } finally { lock.unlock(); } } /** * Simple helper that sets a new state and then wait for another state. */ public void setAndWait(String newState, String waitState) { setState(newState); waitForState(waitState); } private static final String MSG_TIMEOUT = "ThreadState(thread='%s', state='%s') timeout waiting for %s"; private static final String MSG_SET_STATE = "ThreadState(thread='%s', state='%s') set state to %s"; private static final String MSG_WAIT_STATE = "ThreadState(thread='%s', state='%s') waiting for state %s"; private static final String MSG_GOT_STATE = "ThreadState(thread='%s', state='%s') got state %s"; private String format(String pattern, String state) { final String threadName = Thread.currentThread().getName(); return String.format(pattern, threadName, currentState, state); } private void log(String pattern, String state) { System.out.println(format(pattern, state)); } }