package ovm.core.services.memory;

import ovm.core.execution.Context;
import ovm.core.services.threads.OVMThreadContext;
import ovm.core.services.threads.OVMThread;

/**
 * Associate Manager and Policy specific information with a thread
 * context.  This class is typically used with memory managers that
 * support the VM_Area interface and a memory policy that makes use of
 * the per-thread scratchpad area.
 *
 * @author <a href=mailto://baker29@cs.purdue.edu> Jason Baker </a>
 **/
public class ScopedMemoryContext extends OVMThreadContext {

    // the current memory context can be an inner scope to the scope
    // in which this ScopedMemoryContext was allocated. Hence we need
    // do disable scope checks when setting this.
    private Object memoryContext;
    private VM_Area scratchPadArea;

    public static Object getMemoryContext() {
	return ((ScopedMemoryContext) getCurrentContext()).memoryContext;
    }

    public static void setMemoryContext(Object mc) throws PragmaNoBarriers {
	((ScopedMemoryContext) getCurrentContext()).memoryContext = mc;
    }

    public static VM_Area getScratchPadArea() {
	return ((ScopedMemoryContext) getCurrentContext()).scratchPadArea;
    }

    protected ScopedMemoryContext(OVMThread thisThread)
	throws PragmaNoBarriers
    {
	super(thisThread);
	memoryContext = MemoryManager.the().makeMemoryContext();
	scratchPadArea =
	    ScopedMemoryPolicy.theScopedPolicy().makeScratchPadArea();
    }

    protected ScopedMemoryContext() {
	memoryContext = MemoryManager.the().makeMemoryContext();
	scratchPadArea = null;
    }

    public void bootPrimordialContext() throws PragmaNoBarriers {
	super.bootPrimordialContext();
	scratchPadArea =
	    ScopedMemoryPolicy.theScopedPolicy().makeScratchPadArea();
    }
    
    public static class Factory extends OVMThreadContext.Factory {
	public Context make() {
	    return new ScopedMemoryContext();
	}
	public OVMThreadContext make(OVMThread thisThread) {
	    return new ScopedMemoryContext(thisThread);
	}
    }

    // Force the invisible stitcher to check that we are using
    // ScopedMemoryContexts
    public static void forceCheck() {
	Factory _ = (Factory) OVMThreadContext.factory();
    }
}
