/**
* This file is part of ObjectFabric (http://objectfabric.org).
*
* ObjectFabric is licensed under the Apache License, Version 2.0, the terms
* of which may be found at http://www.apache.org/licenses/LICENSE-2.0.html.
*
* Copyright ObjectFabric Inc.
*
* This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
* WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
package org.objectfabric;
import org.objectfabric.ThreadAssert.SingleThreaded;
/**
* Allows a thread to be suspended, a stack is then used to store current state until work
* is resumed.
*/
@SingleThreaded
abstract class Continuation {
private final List<Object> _stack;
Continuation(List<Object> stack) {
if (stack == null)
throw new IllegalArgumentException();
_stack = stack;
}
final List<Object> getInterruptionStack() {
return _stack;
}
//
public final boolean interrupted() {
return _stack.size() > 0;
}
public final void interrupt(Object state) {
interruptImpl(state);
}
public final Object resume() {
return resumeImpl();
}
/*
* Use wrappers for primitives to remove Java boxing classes and avoid .cctor problem
* with the .NET version.
*/
final void interruptBoolean(boolean state) {
BooleanBox box = new BooleanBox();
box.Value = state;
interruptImpl(box);
}
final boolean resumeBoolean() {
BooleanBox box = (BooleanBox) resumeImpl();
return box.Value;
}
static final class BooleanBox {
boolean Value;
}
//
final void interruptByte(byte state) {
ByteBox box = new ByteBox();
box.Value = state;
interruptImpl(box);
}
final byte resumeByte() {
ByteBox box = (ByteBox) resumeImpl();
return box.Value;
}
static final class ByteBox {
byte Value;
}
//
final void interruptInt(int state) {
IntBox box = new IntBox();
box.Value = state;
interruptImpl(box);
}
final int resumeInt() {
IntBox box = (IntBox) resumeImpl();
return box.Value;
}
static final class IntBox {
int Value;
}
//
final void interruptLong(long state) {
LongBox box = new LongBox();
box.Value = state;
interruptImpl(box);
}
final long resumeLong() {
LongBox box = (LongBox) resumeImpl();
return box.Value;
}
private static final class LongBox {
long Value;
}
//
private final void interruptImpl(Object state) {
_stack.add(state);
if (Debug.STACKS && Platform.get().value() != Platform.GWT)
_stack.add(Platform.get().getCurrentStack());
}
private final Object resumeImpl() {
if (Debug.STACKS && Platform.get().value() != Platform.GWT)
Platform.get().assertCurrentStack(_stack.removeLast());
return _stack.removeLast();
}
// Debug
final List<Object> getThreadContextObjects() {
if (!Debug.THREADS)
throw new IllegalStateException();
List<Object> list = new List<Object>();
OverrideAssert.add(this);
addThreadContextObjects(list);
OverrideAssert.end(this);
return list;
}
void addThreadContextObjects(List<Object> list) {
if (!Debug.THREADS)
throw new IllegalStateException();
OverrideAssert.set(this);
list.add(this);
}
}