Package xscript.runtime.nativemethod

Source Code of xscript.runtime.nativemethod.XNativeProvider

package xscript.runtime.nativemethod;

import java.util.HashMap;

import xscript.runtime.XModifier;
import xscript.runtime.XRuntimeException;
import xscript.runtime.XVirtualMachine;
import xscript.runtime.clazz.XClass;
import xscript.runtime.clazz.XPrimitive;
import xscript.runtime.clazz.XWrapper;
import xscript.runtime.genericclass.XGenericClass;
import xscript.runtime.genericclass.XGenericMethodProviderImp;
import xscript.runtime.method.XMethod;
import xscript.runtime.object.XObject;
import xscript.runtime.threads.XMethodExecutor;
import xscript.runtime.threads.XThread;

public class XNativeProvider {

  private int TIME_OUT=-1;
  private XVirtualMachine virtualMachine;
  private HashMap<String, XNativeMethod> nativeMethods;
 
  public XNativeProvider(XVirtualMachine virtualMachine) {
    this.virtualMachine = virtualMachine;
  }

  public void call(XThread thread, XMethodExecutor methodExecutor, XMethod method, XGenericClass[] generics, long[] params) {
    XNativeMethod nativeMethod = method.getNativeMethod();
   
    XObject _this = null;
    int i=0;
    if(!XModifier.isStatic(method.getModifier())){
      _this = virtualMachine.getObjectProvider().getObject(params[0]);
      i=1;
    }
    Object[] oParam = new Object[params.length-i];
    XGenericClass[] genericClasses = method.getParams(_this==null?null:_this.getXClass(), new XGenericMethodProviderImp(method, generics));
    if(oParam.length!=genericClasses.length)
      throw new XRuntimeException("An native call error happened");
    for(int j=0; j<oParam.length; j++){
      long value = params[j+i];
      XGenericClass genericClass = genericClasses[j];
      oParam[j] = XWrapper.getJavaObject(virtualMachine.getObjectProvider(), genericClass, value);
    }
   
    Object ret = invokeNative(nativeMethod, thread, methodExecutor, generics, _this, oParam);
    XGenericClass genericClass  = method.getReturnType(_this==null?null:_this.getXClass(), new XGenericMethodProviderImp(method, generics));
    if(XPrimitive.getPrimitiveID(genericClass.getXClass())!=XPrimitive.VOID){
      long l = XWrapper.getXObject(virtualMachine.getObjectProvider(), genericClass, ret);
      methodExecutor.push(l, XPrimitive.getPrimitiveID(genericClass.getXClass()));
    }
  }

  private Object invokeNative(XNativeMethod nativeMethod, XThread thread, XMethodExecutor methodExecutor, XGenericClass[] generics, XObject _this, Object[] params){
    if(TIME_OUT==-1){
      return nativeMethod.invoke(virtualMachine, thread, methodExecutor, generics, _this, params);
    }else{
      Object sync = new Object();
      InvokeThread invoke = new InvokeThread(sync, nativeMethod, virtualMachine, thread, methodExecutor, generics, _this, params);
      synchronized(sync){
        while(true){
          try {
            sync.wait(TIME_OUT);
            break;
          } catch (InterruptedException e) {}
        }
      }
      if(invoke.hasResult())
        return invoke.getReturn();
      throw new XRuntimeException("Timeout of native call");
    }
  }
 
  public XNativeMethod removeNativeMethod(String name) {
    return nativeMethods.remove(name);
  }

  public void addNativeMethod(String classname, String name, XNativeMethod nativeMethod){
    XClass xClass = virtualMachine.getClassProvider().getLoadedXClass(classname);
    XMethod method = xClass==null?null:xClass.getMethod(name);
    if(method==null){
      if(nativeMethod==null){
        nativeMethods.remove(classname+"."+name);
      }else{
        nativeMethods.put(classname+"."+name, nativeMethod);
      }
    }else{
      method.setNativeMethod(nativeMethod);
    }
  }
 
  private static class InvokeThread extends Thread{
   
    private Object ret;
    private boolean hasRet;
    private Object sync;
    private XNativeMethod nativeMethod;
    private XVirtualMachine virtualMachine;
    private XThread thread;
    private XMethodExecutor methodExecutor;
    private XGenericClass[] generics;
    private XObject _this;
    private Object[] params;
   
    public InvokeThread(Object sync, XNativeMethod nativeMethod, XVirtualMachine virtualMachine, XThread thread, XMethodExecutor methodExecutor, XGenericClass[] generics, XObject _this, Object[] params){
      this.sync = sync;
      this.nativeMethod = nativeMethod;
      this.virtualMachine = virtualMachine;
      this.thread = thread;
      this.methodExecutor = methodExecutor;
      this.generics = generics;
      this._this = _this;
      this.params = params;
      setDaemon(true);
      start();
    }

    public void run(){
      ret = nativeMethod.invoke(virtualMachine, thread, methodExecutor, generics, _this, params);
      hasRet = true;
      synchronized(sync){
        sync.notify();
      }
    }
   
    private Object getReturn(){
      return ret;
    }
   
    public boolean hasResult() {
      return hasRet;
    }
   
  }
 
}
TOP

Related Classes of xscript.runtime.nativemethod.XNativeProvider

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.