Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  
  package org.jruby.ext.ffi;
  
  import org.jruby.Ruby;
 
 import static org.jruby.runtime.Visibility.*;
 
 @JRubyClass(name = "FFI::" + ., parent = "FFI::Pointer")
 public class AutoPointer extends Pointer {
     static final String AUTOPTR_CLASS_NAME = "AutoPointer";
    
    
Keep strong references to the Reaper until cleanup
 
     private static final ConcurrentMap<ReaperGroupBooleanreferenceSet = new ConcurrentHashMap<ReaperGroupBoolean>();
     private static final ThreadLocal<Reference<ReaperGroup>> currentReaper = new ThreadLocal<Reference<ReaperGroup>>();
     
     private Pointer pointer;
     private Object referent;
     private transient volatile Reaper reaper;
     
     public static RubyClass createAutoPointerClass(Ruby runtimeRubyModule module) {
         RubyClass autoptrClass = module.defineClassUnder(,
                 module.getClass("Pointer"),
         autoptrClass.defineAnnotatedMethods(AutoPointer.class);
         autoptrClass.defineAnnotatedConstants(AutoPointer.class);
         autoptrClass.setReifiedClass(AutoPointer.class);
         autoptrClass.kindOf = new RubyModule.KindOf() {
             @Override
             public boolean isKindOf(IRubyObject objRubyModule type) {
                 return obj instanceof AutoPointer && super.isKindOf(objtype);
             }
         };
 
         return autoptrClass;
     }
 
     private static final class AutoPointerAllocator implements ObjectAllocator {
         static final ObjectAllocator INSTANCE = new AutoPointerAllocator();
 
         public IRubyObject allocate(Ruby runtimeRubyClass klazz) {
             return new AutoPointer(runtimeklazz);
         }
 
     }
 
     public AutoPointer(Ruby runtimeRubyClass klazz) {
         super(runtimeklazzruntime.getFFI().getNullMemoryIO());
     }
     
     private static final void checkPointer(Ruby runtimeIRubyObject ptr) {
         if (!(ptr instanceof Pointer)) {
             throw runtime.newTypeError(ptrruntime.getFFI().);
         }
         if (ptr instanceof MemoryPointer || ptr instanceof AutoPointer) {
             throw runtime.newTypeError("Cannot use AutoPointer with MemoryPointer or AutoPointer instances");
         }
     }
 
     @JRubyMethod(name="from_native", meta = true)
     public static IRubyObject from_native(ThreadContext contextIRubyObject recvIRubyObject valueIRubyObject ctx) {
         return ((RubyClassrecv).newInstance(contextvalue.);
     }
 
     @Override
     @JRubyMethod(name = "initialize", visibility = )
     public final IRubyObject initialize(ThreadContext contextIRubyObject pointerArg) {
 
         Ruby runtime = context.runtime;
 
         checkPointer(runtimepointerArg);
 
         Object ffiHandle = getMetaClass().getFFIHandle();
         if (!(ffiHandle instanceof ClassData)) {
             getMetaClass().setFFIHandle(ffiHandle = new ClassData());
         }
         ClassData classData = (ClassDataffiHandle;
 
         // If no release method is defined, then memory leaks will result.
         DynamicMethod releaseMethod = classData.releaseCallSite.retrieveCache(getMetaClass().getMetaClass(), classData.releaseCallSite.getMethodName()).;
         if (releaseMethod.isUndefined()) {
             throw runtime.newRuntimeError("release method undefined");
        } else if ((releaseMethod.getArity().isFixed() && releaseMethod.getArity().required() != 1) || releaseMethod.getArity().required() > 1) {
            throw runtime.newRuntimeError("wrong number of arguments to release method ("
                    + 1 + " for " + releaseMethod.getArity().required()  + ")");
        }
        setMemoryIO(((PointerpointerArg).getMemoryIO());
        this. = (PointerpointerArg;
        this. = .;
        this. = .;
        setReaper(new Reaper(getMetaClass(), classData.releaseCallSite));
        return this;
    }
    @Override
    @JRubyMethod(name = "initialize", visibility = )
    public final IRubyObject initialize(ThreadContext contextIRubyObject pointerArgIRubyObject releaser) {
        checkPointer(context.runtimepointerArg);
        setMemoryIO(((PointerpointerArg).getMemoryIO());
        this. = (PointerpointerArg;
        this. = .;
        this. = .;
        Object ffiHandle = releaser.getMetaClass().getFFIHandleAccessorField().getVariableAccessorForRead().get(releaser);
        if (!(ffiHandle instanceof ReleaserData)) {
            getMetaClass().setFFIHandle(ffiHandle = new ReleaserData());
        }
        ReleaserData releaserData = (ReleaserDataffiHandle;
        DynamicMethod releaseMethod = releaserData.releaseCallSite.retrieveCache(releaser.getMetaClass(), releaserData.releaseCallSite.getMethodName()).;
        // If no release method is defined, then memory leaks will result.
        if (releaseMethod.isUndefined()) {
            throw context.runtime.newRuntimeError("call method undefined");
        } else if ((releaseMethod.getArity().isFixed() && releaseMethod.getArity().required() != 1) || releaseMethod.getArity().required() > 1) {
            throw context.runtime.newRuntimeError("wrong number of arguments to call method ("
                    + 1 + " for " + releaseMethod.getArity().required()  + ")");
        }
        setReaper(new Reaper(releaserreleaserData.releaseCallSite));
        return this;
    }
    @JRubyMethod(name = "free")
    public final IRubyObject free(ThreadContext context) {
        Reaper r = ;
        if (r == null || r.released) {
            throw context.runtime.newRuntimeError("pointer already freed");
        }
        r.release(context);
         = null;
         = null;
        return context.runtime.getNil();
    }
    @JRubyMethod(name = "autorelease=")
    public final IRubyObject autorelease(ThreadContext contextIRubyObject autorelease) {
        Reaper r = ;
        if (r == null || r.released) {
            throw context.runtime.newRuntimeError("pointer already freed");
        }
        r.autorelease(autorelease.isTrue());
        return context.runtime.getNil();
    }
    @JRubyMethod(name = "autorelease?")
    public final IRubyObject autorelease_p(ThreadContext context) {
        return context.runtime.newBoolean( != null ? !. : false);
    }
    private void setReaper(Reaper reaper) {
        Reference<ReaperGroupreaperGroupReference = .get();
        ReaperGroup reaperGroup = reaperGroupReference != null ? reaperGroupReference.get() : null;
        Object referent = reaperGroup != null ? reaperGroup.referent() : null;
        if (referent == null || !reaperGroup.canAccept()) {
            reaperGroup = new ReaperGroup(referent = new Object());
            .set(new SoftReference<ReaperGroup>(reaperGroup));
            .put(reaperGroup.);
        }
        this. = referent;
        this. = reaper;
        reaperGroup.add(reaper);
    }
    private static final class ReaperGroup extends PhantomReferenceReaper<Objectimplements Runnable {
        private static int MAX_REAPERS_PER_GROUP = 100;
        private final WeakReference<Objectweakref;
        private int reaperCount;
        private volatile Reaper head;
        
        ReaperGroup(Object referent) {
            super(referent);
            this. = new WeakReference<Object>(referent);
        }
        
        Object referent() {
            return .get();
        }
        
        boolean canAccept() {
            return  < ;
        }
        
        void add(Reaper r) {
            ++;
            r.next = ;
             = r;
        }
        
        public void run() {
            .remove(this);
            Ruby runtime = null;
            ThreadContext ctx = null;
            Reaper r = ;
            
            while (r != null) {
                if (!r.released && !r.unmanaged) {
                    if (r.getRuntime() != runtime) {
                        runtime = r.getRuntime();
                        ctx = runtime.getCurrentContext();
                    }
                    r.dispose(ctx);
                }
                r = r.next;
            }
        } 
    }
    private static final class Reaper {
        final Pointer pointer;
        final IRubyObject proc;
        final CachingCallSite callSite;
        volatile Reaper next;
        volatile boolean released;
        volatile boolean unmanaged;
        private Reaper(Pointer ptrIRubyObject procCachingCallSite callSite) {
            this. = ptr;
            this. = proc;
            this. = callSite;
        }
        
        final Ruby getRuntime() {
            return .getRuntime();
        }
        
        void dispose(ThreadContext context) {
            .call(context);
        }
        public final void release(ThreadContext context) {
            if (!) {
                 = true;
                dispose(context);
            }
        }
        public final void autorelease(boolean autorelease) {
            this. = !autorelease;
        }
    }
    private static final class ClassData {
        private final CachingCallSite releaseCallSite = new FunctionalCachingCallSite("release");
    }
    private static final class ReleaserData {
        private final CachingCallSite releaseCallSite = new FunctionalCachingCallSite("call");
    }
New to GrepCode? Check out our FAQ X