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 frame on stack */ NATIVE(2),
60 /** Monitor held */ MONITOR(3),
61 /** In critical section */ CRITICAL_SECTION(4);
62
63 private final int value;
64 Pinned(int value) {
65 this.value = value;
66 }
67 public int value() {
68 return value;
69 }
70 }
71
72 /** Preemption attempt result */
73 public enum PreemptStatus {
74 /** Success */ SUCCESS(null),
75 /** Permanent failure */ PERM_FAIL_UNSUPPORTED(null),
76 /** Permanent failure: continuation already yielding */ PERM_FAIL_YIELDING(null),
77 /** Permanent failure: continuation not mounted on the thread */ PERM_FAIL_NOT_MOUNTED(null),
78 /** Transient failure: continuation pinned due to a held CS */ TRANSIENT_FAIL_PINNED_CRITICAL_SECTION(Pinned.CRITICAL_SECTION),
79 /** Transient failure: continuation pinned due to native frame */ TRANSIENT_FAIL_PINNED_NATIVE(Pinned.NATIVE),
80 /** Transient failure: continuation pinned due to a held monitor */ TRANSIENT_FAIL_PINNED_MONITOR(Pinned.MONITOR);
81
82 final Pinned pinned;
83 private PreemptStatus(Pinned reason) { this.pinned = reason; }
84 /**
85 * Whether or not the continuation is pinned.
86 * @return whether or not the continuation is pinned
87 **/
88 public Pinned pinned() { return pinned; }
89 }
90
345 * Suspends the current continuations up to the given scope
346 *
347 * @param scope The {@link ContinuationScope} to suspend
348 * @return {@code true} for success; {@code false} for failure
349 * @throws IllegalStateException if not currently in the given {@code scope},
350 */
351 @Hidden
352 public static boolean yield(ContinuationScope scope) {
353 Continuation cont = JLA.getContinuation(currentCarrierThread());
354 Continuation c;
355 for (c = cont; c != null && c.scope != scope; c = c.parent)
356 ;
357 if (c == null)
358 throw new IllegalStateException("Not in scope " + scope);
359
360 return cont.yield0(scope, null);
361 }
362
363 @Hidden
364 private boolean yield0(ContinuationScope scope, Continuation child) {
365 if (scope != this.scope)
366 this.yieldInfo = scope;
367 int res = doYield();
368 U.storeFence(); // needed to prevent certain transformations by the compiler
369
370 assert scope != this.scope || yieldInfo == null : "scope: " + scope + " this.scope: " + this.scope + " yieldInfo: " + yieldInfo + " res: " + res;
371 assert yieldInfo == null || scope == this.scope || yieldInfo instanceof Integer : "scope: " + scope + " this.scope: " + this.scope + " yieldInfo: " + yieldInfo + " res: " + res;
372
373 if (child != null) { // TODO: ugly
374 if (res != 0) {
375 child.yieldInfo = res;
376 } else if (yieldInfo != null) {
377 assert yieldInfo instanceof Integer;
378 child.yieldInfo = yieldInfo;
379 } else {
380 child.yieldInfo = res;
381 }
382 this.yieldInfo = null;
383 } else {
384 if (res == 0 && yieldInfo != null) {
|