package org.jruby.ext.ffi.jffi;

import com.kenai.jffi.CallingConvention;
import com.kenai.jffi.Closure;
import com.kenai.jffi.ClosureManager;
import org.jruby.Ruby;
import org.jruby.RubyClass;
import org.jruby.RubyModule;
import org.jruby.RubyObject;
import org.jruby.ext.ffi.AbstractInvoker;
import org.jruby.ext.ffi.CallbackInfo;
import org.jruby.ext.ffi.Type;
import org.jruby.runtime.ObjectAllocator;

import java.util.Map;
import java.util.WeakHashMap;


Manages Callback instances for the low level FFI backend.
/** * Manages Callback instances for the low level FFI backend. */
public class CallbackManager extends org.jruby.ext.ffi.CallbackManager { private final Map<CallbackInfo, NativeCallbackFactory> factories = new WeakHashMap<CallbackInfo, NativeCallbackFactory>();
Holder for the single instance of CallbackManager
/** Holder for the single instance of CallbackManager */
private static final class SingletonHolder { static final CallbackManager INSTANCE = new CallbackManager(); }
Gets the singleton instance of CallbackManager
/** * Gets the singleton instance of CallbackManager */
public static final CallbackManager getInstance() { return SingletonHolder.INSTANCE; }
Creates a Callback class for a ruby runtime
Params:
  • runtime – The runtime to create the class for
  • module – The module to place the class in
Returns:The newly created ruby class
/** * Creates a Callback class for a ruby runtime * * @param runtime The runtime to create the class for * @param module The module to place the class in * * @return The newly created ruby class */
public static RubyClass createCallbackClass(Ruby runtime, RubyModule module) { RubyClass cbClass = module.defineClassUnder("Callback", module.getClass("Pointer"), ObjectAllocator.NOT_ALLOCATABLE_ALLOCATOR); cbClass.defineAnnotatedMethods(AbstractInvoker.class); cbClass.defineAnnotatedConstants(AbstractInvoker.class); return cbClass; } public final org.jruby.ext.ffi.Pointer getCallback(Ruby runtime, CallbackInfo cbInfo, Object proc) { return proc instanceof RubyObject ? getCallbackFactory(runtime, cbInfo).getCallback((RubyObject) proc) : getCallbackFactory(runtime, cbInfo).newCallback(proc); } public final synchronized NativeCallbackFactory getCallbackFactory(Ruby runtime, CallbackInfo cbInfo) { NativeCallbackFactory factory = factories.get(cbInfo); if (factory == null) { factories.put(cbInfo, factory = new NativeCallbackFactory(runtime, cbInfo)); } return factory; } /** */ final CallbackMemoryIO newClosure(Ruby runtime, Type returnType, Type[] parameterTypes, Object proc, CallingConvention convention) { NativeFunctionInfo info = new NativeFunctionInfo(runtime, returnType, parameterTypes, convention); final NativeClosureProxy cbProxy = new NativeClosureProxy(runtime, info, proc); final Closure.Handle handle = ClosureManager.getInstance().newClosure(cbProxy, info.callContext); return new CallbackMemoryIO(runtime, handle, proc); } }