All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.objectfabric.Continuation Maven / Gradle / Ivy

There is a newer version: 0.9.1
Show newest version
/**
 * 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 _stack;

    protected Continuation(List stack) {
        if (stack == null)
            throw new IllegalArgumentException();

        _stack = stack;
    }

    final List getInterruptionStack() {
        return _stack;
    }

    //

    public final boolean interrupted() {
        return _stack.size() > 0;
    }

    public final void interrupt(Object state) {
        if (Debug.ENABLED)
            if (state != null && !(state instanceof String))
                Debug.assertion(!Platform.get().defaultToString(state).startsWith("java.lang"));

        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 getThreadContextObjects() {
        if (!Debug.THREADS)
            throw new IllegalStateException();

        List list = new List();
        OverrideAssert.add(this);
        addThreadContextObjects(list);
        OverrideAssert.end(this);
        return list;
    }

    void addThreadContextObjects(List list) {
        if (!Debug.THREADS)
            throw new IllegalStateException();

        OverrideAssert.set(this);
        list.add(this);
    }
}