// $Header: /p/sss/cvs/OpenVM/src/s3/services/io/async/SignalDescriptorBase.java,v 1.8 2004/10/09 21:43:04 pizlofj Exp $

package s3.services.io.async;

import ovm.core.*;
import ovm.core.execution.*;
import ovm.core.services.memory.*;
import ovm.core.stitcher.*;
import ovm.services.io.async.*;
import ovm.services.io.signals.*;
import ovm.services.threads.*;
import ovm.util.*;

/**
 *
 * @author Filip Pizlo
 */
abstract class SignalDescriptorBase extends DescriptorBase {
    protected UserLevelThreadManager tm;
    protected IOSignalManager iosm;

    SignalDescriptorBase(UserLevelThreadManager tm,
			 IOSignalManager iosm,
			 int fd) {
        super(fd);
        this.tm=tm;
        this.iosm=iosm;
    }
    
    protected static abstract class RWOpNode
        extends AsyncOpQueue.OpNode {
	
	private SignalDescriptorBase outer_;
	protected void setOuter(SignalDescriptorBase outer)
	    throws PragmaNoBarriers {
	    this.outer_=outer;
	}
	protected SignalDescriptorBase getOuter() throws PragmaNoBarriers {
	    return outer_;
	}
	
	// helper
	protected int getFD() {
	    return getOuter().getFD();
	}

        protected AsyncMemoryCallback data;
        protected int maxBytes;
        protected int result=0;
        
        public RWOpNode(SignalDescriptorBase outer,
			AsyncMemoryCallback data,
                        int maxBytes,
                        AsyncCallback cback)
	    throws PragmaNoBarriers {
            super(cback);
	    setOuter(outer);
            this.data=data;
            this.maxBytes=maxBytes;
        }
        
        public final int getNumBytes() {
            return result;
        }
    }
    
    protected static abstract class ReadOpNode
        extends RWOpNode
        implements RWIODescriptor.ReadFinalizer {
        
        public ReadOpNode(SignalDescriptorBase outer,
			  AsyncMemoryCallback data,
                          int maxBytes,
                          AsyncCallback cback) {
            super(outer,data,maxBytes,cback);
        }
        
        protected abstract int doRead(VM_Address buf);
        
        public final boolean doOp() {
	    VM_Address buf=data.getBuffer(maxBytes,false);
	    try {
		if (checkRepeat(result=doRead(buf),
				Native.getErrno())) {
		    return false;
		}
	    } finally {
		data.doneBuffer(buf,result<0?0:result);
	    }
	    return true;
        }
    }
    
    protected static abstract class WriteOpNode
        extends RWOpNode
        implements RWIODescriptor.WriteFinalizer {
        
        public WriteOpNode(SignalDescriptorBase outer,
			   AsyncMemoryCallback data,
                           int maxBytes,
                           AsyncCallback cback) {
            super(outer, data,maxBytes,cback);
	    setOuter(outer);
        }
        
        protected abstract int doWrite(VM_Address buf);
	        
        public final boolean doOp() {
	    VM_Address buf=data.getBuffer(maxBytes,false);
	    try {
		if (checkRepeat(result=doWrite(buf),
				Native.getErrno())) {
		    //Native.print_string("will repeat write doOp() for ");
		    //Native.print_int(getFD());
		    //Native.print_string("\n");
		    return false;
		}
	    } finally {
		data.doneBuffer(buf,0);
	    }
	    //Native.print_string("done write doOp() for "+getFD()+" with "+
	    //			"result = "+result+" and error = "+getError()+"\n");
	    //BasicIO.out.println("by the way, BasicIO.out still works!");
	    return true;
	}
    }

    public boolean readyForRead() {
	return true;
    }
    
    public boolean readyForWrite() {
	return true;
    }
    
    public boolean readyForExcept() {
	return true;
    }
    
    public abstract static class SpecificWrapifier
        implements FileDescriptorWrapifier.SpecificWrapifier {
        
        protected UserLevelThreadManager tm;
        protected IOSignalManager iosm;
        
        public SpecificWrapifier(IOSignalManager iosm) {
            tm = (UserLevelThreadManager)
                ((ThreadServicesFactory)ThreadServiceConfigurator.config.
                    getServiceFactory(ThreadServicesFactory.name)).getThreadManager();
            if (tm == null) {
                throw new OVMError.Configuration("need a configured thread manager");
            }
            
            this.iosm = iosm;
        }
        
        public abstract IODescriptor wrap(FileDescriptorWrapifier.FDType type,
					  int fd);
    }
}

