Test1917.java revision 4013595d91898c5a18fbc480cbd4023c4307ec62
1/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package art;
18
19import java.io.PrintWriter;
20import java.io.StringWriter;
21import java.lang.reflect.Executable;
22import java.lang.reflect.Method;
23import java.lang.reflect.Field;
24import java.util.ArrayList;
25import java.util.Arrays;
26import java.util.Collection;
27import java.util.HashSet;
28import java.util.List;
29import java.util.concurrent.Semaphore;
30import java.util.Vector;
31import java.util.function.Function;
32import java.util.function.Predicate;
33import java.util.function.Supplier;
34import java.util.function.Consumer;
35
36public class Test1917 {
37  public final static boolean TEST_PRINT_ALL = false;
38
39  public static class ThreadPauser implements Runnable {
40    public Semaphore sem_wakeup_main = new Semaphore(0);
41    public Semaphore sem_wait = new Semaphore(0);
42
43    public void run() {
44      try {
45        sem_wakeup_main.release();
46        sem_wait.acquire();
47      } catch (Exception e) {
48        throw new Error("Error with semaphores!", e);
49      }
50    }
51
52    public void waitForOtherThreadToPause() throws Exception {
53      sem_wakeup_main.acquire();
54      while (!sem_wait.hasQueuedThreads()) {}
55    }
56
57    public void wakeupOtherThread() throws Exception {
58      sem_wait.release();
59    }
60  }
61
62  public static class StackTraceGenerator implements Runnable {
63    private final Thread thr;
64    private final Consumer<StackTrace.StackFrameData> con;
65    public StackTraceGenerator(Thread thr, Consumer<StackTrace.StackFrameData> con) {
66      this.thr = thr;
67      this.con = con;
68    }
69
70    public StackTraceGenerator(Consumer<StackTrace.StackFrameData> con) {
71      this(null, con);
72    }
73
74    public Thread getThread() {
75      if (thr == null) {
76        return Thread.currentThread();
77      } else {
78        return thr;
79      }
80    }
81    public void run() {
82      for (StackTrace.StackFrameData s : StackTrace.GetStackTrace(getThread())) {
83        con.accept(s);
84      }
85    }
86  }
87
88  public static class RecurCount implements Runnable {
89    private final int cnt;
90    private final Runnable then;
91    public RecurCount(int cnt, Runnable then) {
92      this.cnt = cnt;
93      this.then = then;
94    }
95
96    public void run() {
97      doRecur(0);
98    }
99
100    public void doRecur(int n) {
101      if (n < cnt) {
102        doRecur(n + 1);
103      } else {
104        then.run();
105      }
106    }
107  }
108
109  public static Consumer<StackTrace.StackFrameData> makePrintStackFramesConsumer()
110      throws Exception {
111    final Method end_method = Test1917.class.getDeclaredMethod("run");
112    return new Consumer<StackTrace.StackFrameData>() {
113      public void accept(StackTrace.StackFrameData data) {
114        if (TEST_PRINT_ALL) {
115          System.out.println(data);
116        } else {
117          Package p = data.method.getDeclaringClass().getPackage();
118          // Filter out anything to do with the testing harness.
119          if (p != null && p.equals(Test1917.class.getPackage())) {
120            System.out.printf("'%s' line: %d\n",
121                data.method,
122                Breakpoint.locationToLine(data.method, data.current_location));
123          } else if (data.method.getDeclaringClass().equals(Semaphore.class)) {
124            System.out.printf("'%s' line: <NOT-DETERMINISTIC>\n", data.method);
125          }
126        }
127      }
128    };
129  }
130
131  public static void run() throws Exception {
132    System.out.println("Recurring 5 times");
133    new RecurCount(5, new StackTraceGenerator(makePrintStackFramesConsumer())).run();
134
135    System.out.println("Recurring 5 times on another thread");
136    Thread thr = new Thread(
137        new RecurCount(5, new StackTraceGenerator(makePrintStackFramesConsumer())));
138    thr.start();
139    thr.join();
140
141    System.out.println("Recurring 5 times on another thread. Stack trace from main thread!");
142    ThreadPauser pause = new ThreadPauser();
143    Thread thr2 = new Thread(new RecurCount(5, pause));
144    thr2.start();
145    pause.waitForOtherThreadToPause();
146    new StackTraceGenerator(thr2, makePrintStackFramesConsumer()).run();
147    pause.wakeupOtherThread();
148    thr2.join();
149  }
150}
151