< prev index next >

test/jdk/java/lang/ScopedValue/StressStackOverflow.java

Print this page

 79                 return values[tlr.nextInt(3)];
 80             }
 81         }
 82 
 83         final Behaviour behaviour;
 84 
 85         public DeepRecursion(Behaviour behaviour) {
 86             this.behaviour = behaviour;
 87         }
 88 
 89         public void run() {
 90             final var last = el.get();
 91             while (ITERS-- > 0) {
 92                 if (System.nanoTime() - startTime > DURATION_IN_NANOS) {
 93                     return;
 94                 }
 95 
 96                 var nextRandomFloat = ThreadLocalRandom.current().nextFloat();
 97                 try {
 98                     switch (behaviour) {
 99                         case CALL -> ScopedValue.where(el, el.get() + 1).call(() -> fibonacci_pad(20, this));
100                         case GET -> ScopedValue.where(el, el.get() + 1).get(() -> fibonacci_pad(20, this));
101                         case RUN -> ScopedValue.where(el, el.get() + 1).run(() -> fibonacci_pad(20, this));
102                     }
103                     if (!last.equals(el.get())) {
104                         throw testFailureException;
105                     }
106                 } catch (StackOverflowError e) {
107                     if (nextRandomFloat <= 0.1) {
108                         ScopedValue.where(el, el.get() + 1).run(this);
109                     }
110                 } catch (TestFailureException e) {
111                     throw e;
112                 } catch (Throwable throwable) {
113                     // StackOverflowErrors cause many different failures. These include
114                     // StructureViolationExceptions and InvocationTargetExceptions. This test
115                     // checks that, no matter what the failure mode, scoped values are handled
116                     // correctly.
117                 } finally {
118                     if (!last.equals(el.get())) {
119                         throw testFailureException;
120                     }
121                 }
122 
123                 Thread.yield();
124             }
125         }
126 
127         public Object get() {
128             run();

169     // Run op in a new thread. Platform or virtual threads are chosen at random.
170     void runInNewThread(Runnable op) {
171         var threadFactory
172                 = (ThreadLocalRandom.current().nextBoolean() ? Thread.ofPlatform() : Thread.ofVirtual()).factory();
173         try (var scope = new StructuredTaskScope<>("", threadFactory)) {
174             var handle = scope.fork(() -> {
175                 op.run();
176                 return null;
177             });
178             scope.join();
179             handle.get();
180         } catch (TestFailureException e) {
181             throw e;
182         } catch (Exception e) {
183             throw new RuntimeException(e);
184         }
185     }
186 
187     public void run() {
188         try {
189             ScopedValue.where(inheritedValue, 42).where(el, 0).run(() -> {

190                 try (var scope = new StructuredTaskScope<>()) {
191                     try {
192                         if (ThreadLocalRandom.current().nextBoolean()) {
193                             // Repeatedly test Scoped Values set by ScopedValue::call(), get(), and run()
194                             final var deepRecursion
195                                 = new DeepRecursion(DeepRecursion.Behaviour.choose(ThreadLocalRandom.current()));
196                             deepRecursion.run();
197                         } else {
198                             // Recursively run ourself until we get a stack overflow
199                             // Catch the overflow and make sure the recovery path works
200                             // for values inherited from a StructuredTaskScope.
201                             Runnable op = new Runnable() {
202                                 public void run() {
203                                     try {
204                                         fibonacci_pad(20, this);
205                                     } catch (StackOverflowError e) {
206                                     } catch (TestFailureException e) {
207                                         throw e;
208                                     } catch (Throwable throwable) {
209                                         // StackOverflowErrors cause many different failures. These include

 79                 return values[tlr.nextInt(3)];
 80             }
 81         }
 82 
 83         final Behaviour behaviour;
 84 
 85         public DeepRecursion(Behaviour behaviour) {
 86             this.behaviour = behaviour;
 87         }
 88 
 89         public void run() {
 90             final var last = el.get();
 91             while (ITERS-- > 0) {
 92                 if (System.nanoTime() - startTime > DURATION_IN_NANOS) {
 93                     return;
 94                 }
 95 
 96                 var nextRandomFloat = ThreadLocalRandom.current().nextFloat();
 97                 try {
 98                     switch (behaviour) {
 99                         case CALL -> ScopedValue.callWhere(el, el.get() + 1, () -> fibonacci_pad(20, this));
100                         case GET -> ScopedValue.getWhere(el, el.get() + 1, () -> fibonacci_pad(20, this));
101                         case RUN -> ScopedValue.runWhere(el, el.get() + 1, () -> fibonacci_pad(20, this));
102                     }
103                     if (!last.equals(el.get())) {
104                         throw testFailureException;
105                     }
106                 } catch (StackOverflowError e) {
107                     if (nextRandomFloat <= 0.1) {
108                         ScopedValue.runWhere(el, el.get() + 1, this);
109                     }
110                 } catch (TestFailureException e) {
111                     throw e;
112                 } catch (Throwable throwable) {
113                     // StackOverflowErrors cause many different failures. These include
114                     // StructureViolationExceptions and InvocationTargetExceptions. This test
115                     // checks that, no matter what the failure mode, scoped values are handled
116                     // correctly.
117                 } finally {
118                     if (!last.equals(el.get())) {
119                         throw testFailureException;
120                     }
121                 }
122 
123                 Thread.yield();
124             }
125         }
126 
127         public Object get() {
128             run();

169     // Run op in a new thread. Platform or virtual threads are chosen at random.
170     void runInNewThread(Runnable op) {
171         var threadFactory
172                 = (ThreadLocalRandom.current().nextBoolean() ? Thread.ofPlatform() : Thread.ofVirtual()).factory();
173         try (var scope = new StructuredTaskScope<>("", threadFactory)) {
174             var handle = scope.fork(() -> {
175                 op.run();
176                 return null;
177             });
178             scope.join();
179             handle.get();
180         } catch (TestFailureException e) {
181             throw e;
182         } catch (Exception e) {
183             throw new RuntimeException(e);
184         }
185     }
186 
187     public void run() {
188         try {
189             var carrier = ScopedValue.where(inheritedValue, 42).where(el, 0);
190             ScopedValue.runWhere(carrier, () -> {
191                 try (var scope = new StructuredTaskScope<>()) {
192                     try {
193                         if (ThreadLocalRandom.current().nextBoolean()) {
194                             // Repeatedly test Scoped Values set by ScopedValue::call(), get(), and run()
195                             final var deepRecursion
196                                 = new DeepRecursion(DeepRecursion.Behaviour.choose(ThreadLocalRandom.current()));
197                             deepRecursion.run();
198                         } else {
199                             // Recursively run ourself until we get a stack overflow
200                             // Catch the overflow and make sure the recovery path works
201                             // for values inherited from a StructuredTaskScope.
202                             Runnable op = new Runnable() {
203                                 public void run() {
204                                     try {
205                                         fibonacci_pad(20, this);
206                                     } catch (StackOverflowError e) {
207                                     } catch (TestFailureException e) {
208                                         throw e;
209                                     } catch (Throwable throwable) {
210                                         // StackOverflowErrors cause many different failures. These include
< prev index next >