39
40 /**
41 * A one-shot delimited continuation.
42 */
43 public class Continuation {
44 private static final Unsafe U = Unsafe.getUnsafe();
45 private static final long MOUNTED_OFFSET = U.objectFieldOffset(Continuation.class, "mounted");
46 private static final boolean PRESERVE_SCOPED_VALUE_CACHE;
47 private static final JavaLangAccess JLA = SharedSecrets.getJavaLangAccess();
48 static {
49 ContinuationSupport.ensureSupported();
50
51 StackChunk.init(); // ensure StackChunk class is initialized
52
53 String value = GetPropertyAction.privilegedGetProperty("jdk.preserveScopedValueCache");
54 PRESERVE_SCOPED_VALUE_CACHE = (value == null) || Boolean.parseBoolean(value);
55 }
56
57 /** Reason for pinning */
58 public enum Pinned {
59 /** Native frame on stack */ NATIVE,
60 /** Monitor held */ MONITOR,
61 /** In critical section */ CRITICAL_SECTION }
62
63 /** Preemption attempt result */
64 public enum PreemptStatus {
65 /** Success */ SUCCESS(null),
66 /** Permanent failure */ PERM_FAIL_UNSUPPORTED(null),
67 /** Permanent failure: continuation already yielding */ PERM_FAIL_YIELDING(null),
68 /** Permanent failure: continuation not mounted on the thread */ PERM_FAIL_NOT_MOUNTED(null),
69 /** Transient failure: continuation pinned due to a held CS */ TRANSIENT_FAIL_PINNED_CRITICAL_SECTION(Pinned.CRITICAL_SECTION),
70 /** Transient failure: continuation pinned due to native frame */ TRANSIENT_FAIL_PINNED_NATIVE(Pinned.NATIVE),
71 /** Transient failure: continuation pinned due to a held monitor */ TRANSIENT_FAIL_PINNED_MONITOR(Pinned.MONITOR);
72
73 final Pinned pinned;
74 private PreemptStatus(Pinned reason) { this.pinned = reason; }
75 /**
76 * Whether or not the continuation is pinned.
77 * @return whether or not the continuation is pinned
78 **/
79 public Pinned pinned() { return pinned; }
80 }
81
336 * Suspends the current continuations up to the given scope
337 *
338 * @param scope The {@link ContinuationScope} to suspend
339 * @return {@code true} for success; {@code false} for failure
340 * @throws IllegalStateException if not currently in the given {@code scope},
341 */
342 @Hidden
343 public static boolean yield(ContinuationScope scope) {
344 Continuation cont = JLA.getContinuation(currentCarrierThread());
345 Continuation c;
346 for (c = cont; c != null && c.scope != scope; c = c.parent)
347 ;
348 if (c == null)
349 throw new IllegalStateException("Not in scope " + scope);
350
351 return cont.yield0(scope, null);
352 }
353
354 @Hidden
355 private boolean yield0(ContinuationScope scope, Continuation child) {
356 preempted = false;
357
358 if (scope != this.scope)
359 this.yieldInfo = scope;
360 int res = doYield();
361 U.storeFence(); // needed to prevent certain transformations by the compiler
362
363 assert scope != this.scope || yieldInfo == null : "scope: " + scope + " this.scope: " + this.scope + " yieldInfo: " + yieldInfo + " res: " + res;
364 assert yieldInfo == null || scope == this.scope || yieldInfo instanceof Integer : "scope: " + scope + " this.scope: " + this.scope + " yieldInfo: " + yieldInfo + " res: " + res;
365
366 if (child != null) { // TODO: ugly
367 if (res != 0) {
368 child.yieldInfo = res;
369 } else if (yieldInfo != null) {
370 assert yieldInfo instanceof Integer;
371 child.yieldInfo = yieldInfo;
372 } else {
373 child.yieldInfo = res;
374 }
375 this.yieldInfo = null;
376 } else {
377 if (res == 0 && yieldInfo != null) {
|
39
40 /**
41 * A one-shot delimited continuation.
42 */
43 public class Continuation {
44 private static final Unsafe U = Unsafe.getUnsafe();
45 private static final long MOUNTED_OFFSET = U.objectFieldOffset(Continuation.class, "mounted");
46 private static final boolean PRESERVE_SCOPED_VALUE_CACHE;
47 private static final JavaLangAccess JLA = SharedSecrets.getJavaLangAccess();
48 static {
49 ContinuationSupport.ensureSupported();
50
51 StackChunk.init(); // ensure StackChunk class is initialized
52
53 String value = GetPropertyAction.privilegedGetProperty("jdk.preserveScopedValueCache");
54 PRESERVE_SCOPED_VALUE_CACHE = (value == null) || Boolean.parseBoolean(value);
55 }
56
57 /** Reason for pinning */
58 public enum Pinned {
59 NATIVE(2, "Native frame or <clinit> on stack"),
60 MONITOR(3, "Monitor held"),
61 CRITICAL_SECTION(4, "In critical section");
62
63 private final int reasonCode;
64 private final String reasonString;
65 Pinned(int reasonCode, String reasonString) {
66 this.reasonCode = reasonCode;
67 this.reasonString = reasonString;
68 }
69 public int reasonCode() {
70 return reasonCode;
71 }
72 public String reasonString() {
73 return reasonString;
74 }
75 }
76
77 /** Preemption attempt result */
78 public enum PreemptStatus {
79 /** Success */ SUCCESS(null),
80 /** Permanent failure */ PERM_FAIL_UNSUPPORTED(null),
81 /** Permanent failure: continuation already yielding */ PERM_FAIL_YIELDING(null),
82 /** Permanent failure: continuation not mounted on the thread */ PERM_FAIL_NOT_MOUNTED(null),
83 /** Transient failure: continuation pinned due to a held CS */ TRANSIENT_FAIL_PINNED_CRITICAL_SECTION(Pinned.CRITICAL_SECTION),
84 /** Transient failure: continuation pinned due to native frame */ TRANSIENT_FAIL_PINNED_NATIVE(Pinned.NATIVE),
85 /** Transient failure: continuation pinned due to a held monitor */ TRANSIENT_FAIL_PINNED_MONITOR(Pinned.MONITOR);
86
87 final Pinned pinned;
88 private PreemptStatus(Pinned reason) { this.pinned = reason; }
89 /**
90 * Whether or not the continuation is pinned.
91 * @return whether or not the continuation is pinned
92 **/
93 public Pinned pinned() { return pinned; }
94 }
95
350 * Suspends the current continuations up to the given scope
351 *
352 * @param scope The {@link ContinuationScope} to suspend
353 * @return {@code true} for success; {@code false} for failure
354 * @throws IllegalStateException if not currently in the given {@code scope},
355 */
356 @Hidden
357 public static boolean yield(ContinuationScope scope) {
358 Continuation cont = JLA.getContinuation(currentCarrierThread());
359 Continuation c;
360 for (c = cont; c != null && c.scope != scope; c = c.parent)
361 ;
362 if (c == null)
363 throw new IllegalStateException("Not in scope " + scope);
364
365 return cont.yield0(scope, null);
366 }
367
368 @Hidden
369 private boolean yield0(ContinuationScope scope, Continuation child) {
370 if (scope != this.scope)
371 this.yieldInfo = scope;
372 int res = doYield();
373 U.storeFence(); // needed to prevent certain transformations by the compiler
374
375 assert scope != this.scope || yieldInfo == null : "scope: " + scope + " this.scope: " + this.scope + " yieldInfo: " + yieldInfo + " res: " + res;
376 assert yieldInfo == null || scope == this.scope || yieldInfo instanceof Integer : "scope: " + scope + " this.scope: " + this.scope + " yieldInfo: " + yieldInfo + " res: " + res;
377
378 if (child != null) { // TODO: ugly
379 if (res != 0) {
380 child.yieldInfo = res;
381 } else if (yieldInfo != null) {
382 assert yieldInfo instanceof Integer;
383 child.yieldInfo = yieldInfo;
384 } else {
385 child.yieldInfo = res;
386 }
387 this.yieldInfo = null;
388 } else {
389 if (res == 0 && yieldInfo != null) {
|