1 /*
   2  * Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 package nsk.share.jpda;
  24 
  25 import nsk.share.TestBug;
  26 import nsk.share.locks.MonitorLockingThread;
  27 
  28 /*
  29  *  StateTestThread sequentially switches its state in following order:
  30  *  - thread not started
  31  *  - thread is running
  32  *  - thread is sleeping
  33  *  - thread in Object.wait()
  34  *  - thread wait on java monitor
  35  *  - thread is finished
  36  *
  37  *  To use this class create new instance of StateTestThread and sequentially call method nextState().
  38  */
  39 public class StateTestThread extends Thread {
  40     // thread states available through ThreadReference.state()
  41     public static String stateTestThreadStates[] = { "UNKNOWN", "RUNNING", "SLEEPING", "WAIT", "MONITOR", "ZOMBIE" };
  42 
  43     private Object waitOnObject = new Object();
  44 
  45     public StateTestThread(String name) {
  46         super(name);
  47     }
  48 
  49     private volatile boolean isRunning;
  50 
  51     private volatile boolean waitState;
  52 
  53     public int getCurrentState() {
  54         return currentState;
  55     }
  56 
  57     private MonitorLockingThread auxiliaryThread = new MonitorLockingThread(this);
  58 
  59     private boolean isExecutedWithErrors;
  60 
  61     private volatile boolean readyToBeBlocked;
  62 
  63     private String errorMessage;
  64 
  65     public void run() {
  66         isRunning = true;
  67 
  68         // running state
  69         while (isRunning)
  70             ;
  71 
  72         try {
  73             // sleeping state
  74             sleep(Long.MAX_VALUE);
  75         } catch (InterruptedException e) {
  76             // expected exception
  77         }
  78 
  79         synchronized (waitOnObject) {
  80             try {
  81                 // wait state
  82                 while (waitState)
  83                     waitOnObject.wait();
  84             } catch (InterruptedException e) {
  85                 isExecutedWithErrors = true;
  86                 errorMessage = "StateTestThread was unexpected interrupted during waiting";
  87             }
  88         }
  89 
  90         // start auxiliary thread which should acquire 'this' lock
  91         auxiliaryThread.acquireLock();
  92 
  93         readyToBeBlocked = true;
  94 
  95         // try acquire the same lock as auxiliaryThread, switch state to 'wait on monitor'
  96         synchronized (this) {
  97 
  98         }
  99     }
 100 
 101     private int currentState = 1;
 102 
 103     public void nextState() {
 104         // check is thread states change as expected
 105         if (isExecutedWithErrors)
 106             throw new TestBug(errorMessage);
 107 
 108         switch (currentState++) {
 109         case 1:
 110             // start thread
 111             start();
 112 
 113             while (!isRunning)
 114                 yield();
 115 
 116             break;
 117         case 2:
 118             // stop running
 119             isRunning = false;
 120 
 121             while (this.getState() != Thread.State.TIMED_WAITING)
 122                 yield();
 123 
 124             break;
 125         case 3:
 126             waitState = true;
 127 
 128             // stop sleeping
 129             interrupt();
 130 
 131             while (getState() != Thread.State.WAITING)
 132                 yield();
 133 
 134             break;
 135         case 4:
 136             waitState = false;
 137 
 138             // stop wait
 139             synchronized (waitOnObject) {
 140                 waitOnObject.notify();
 141             }
 142 
 143             while (!readyToBeBlocked || (getState() != Thread.State.BLOCKED))
 144                 yield();
 145 
 146             break;
 147         case 5:
 148             // let StateTestThread thread acquire lock
 149             auxiliaryThread.releaseLock();
 150             try {
 151                 join();
 152             } catch (InterruptedException e) {
 153                 throw new TestBug("Unexpected exception: " + e);
 154             }
 155             break;
 156 
 157         default:
 158             throw new TestBug("Invalid thread state");
 159         }
 160     }
 161 }