| /* |
| * Copyright (C) 2017 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package art; |
| |
| import java.io.PrintWriter; |
| import java.io.StringWriter; |
| import java.lang.reflect.Executable; |
| import java.lang.reflect.Method; |
| import java.lang.reflect.Field; |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.Collection; |
| import java.util.HashSet; |
| import java.util.List; |
| import java.util.concurrent.Semaphore; |
| import java.util.Vector; |
| import java.util.function.Function; |
| import java.util.function.Predicate; |
| import java.util.function.Supplier; |
| import java.util.function.Consumer; |
| |
| public class Test1917 { |
| public final static boolean TEST_PRINT_ALL = false; |
| |
| public static class ThreadPauser implements Runnable { |
| public Semaphore sem_wakeup_main = new Semaphore(0); |
| public Semaphore sem_wait = new Semaphore(0); |
| |
| public void run() { |
| try { |
| sem_wakeup_main.release(); |
| sem_wait.acquire(); |
| } catch (Exception e) { |
| throw new Error("Error with semaphores!", e); |
| } |
| } |
| |
| public void waitForOtherThreadToPause() throws Exception { |
| sem_wakeup_main.acquire(); |
| while (!sem_wait.hasQueuedThreads()) {} |
| } |
| |
| public void wakeupOtherThread() throws Exception { |
| sem_wait.release(); |
| } |
| } |
| |
| public static class StackTraceGenerator implements Runnable { |
| private final Thread thr; |
| private final Consumer<StackTrace.StackFrameData> con; |
| public StackTraceGenerator(Thread thr, Consumer<StackTrace.StackFrameData> con) { |
| this.thr = thr; |
| this.con = con; |
| } |
| |
| public StackTraceGenerator(Consumer<StackTrace.StackFrameData> con) { |
| this(null, con); |
| } |
| |
| public Thread getThread() { |
| if (thr == null) { |
| return Thread.currentThread(); |
| } else { |
| return thr; |
| } |
| } |
| public void run() { |
| for (StackTrace.StackFrameData s : StackTrace.GetStackTrace(getThread())) { |
| con.accept(s); |
| } |
| } |
| } |
| |
| public static class RecurCount implements Runnable { |
| private final int cnt; |
| private final Runnable then; |
| public RecurCount(int cnt, Runnable then) { |
| this.cnt = cnt; |
| this.then = then; |
| } |
| |
| public void run() { |
| doRecur(0); |
| } |
| |
| public void doRecur(int n) { |
| if (n < cnt) { |
| doRecur(n + 1); |
| } else { |
| then.run(); |
| } |
| } |
| } |
| |
| public static Consumer<StackTrace.StackFrameData> makePrintStackFramesConsumer() |
| throws Exception { |
| final Method end_method = Test1917.class.getDeclaredMethod("run"); |
| return new Consumer<StackTrace.StackFrameData>() { |
| public void accept(StackTrace.StackFrameData data) { |
| if (TEST_PRINT_ALL) { |
| System.out.println(data); |
| } else { |
| Package p = data.method.getDeclaringClass().getPackage(); |
| // Filter out anything to do with the testing harness. |
| if (p != null && p.equals(Test1917.class.getPackage())) { |
| System.out.printf("'%s' line: %d\n", |
| data.method, |
| Breakpoint.locationToLine(data.method, data.current_location)); |
| } else if (data.method.getDeclaringClass().equals(Semaphore.class)) { |
| System.out.printf("'%s' line: <NOT-DETERMINISTIC>\n", data.method); |
| } |
| } |
| } |
| }; |
| } |
| |
| public static void run() throws Exception { |
| System.out.println("Recurring 5 times"); |
| new RecurCount(5, new StackTraceGenerator(makePrintStackFramesConsumer())).run(); |
| |
| System.out.println("Recurring 5 times on another thread"); |
| Thread thr = new Thread( |
| Thread.currentThread().getThreadGroup(), |
| new RecurCount(5, new StackTraceGenerator(makePrintStackFramesConsumer())), |
| "Recurring Thread 1", |
| 10*1000000 /* 10 mb*/); |
| thr.start(); |
| thr.join(); |
| |
| System.out.println("Recurring 5 times on another thread. Stack trace from main thread!"); |
| ThreadPauser pause = new ThreadPauser(); |
| Thread thr2 = new Thread( |
| Thread.currentThread().getThreadGroup(), |
| new RecurCount(5, pause), |
| "Recurring Thread 2", |
| 10*1000000 /* 10 mb*/); |
| thr2.start(); |
| pause.waitForOtherThreadToPause(); |
| new StackTraceGenerator(thr2, makePrintStackFramesConsumer()).run(); |
| pause.wakeupOtherThread(); |
| thr2.join(); |
| } |
| } |