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 final 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 result = module.defineClassUnder(,
                 module.getClass("Pointer"),
                 .);
         result.defineAnnotatedMethods(AutoPointer.class);
         result.defineAnnotatedConstants(AutoPointer.class);
 
         return result;
     }
 
     private static final class AutoPointerAllocator implements ObjectAllocator {
         static final ObjectAllocator INSTANCE = new AutoPointerAllocator();
 
         public IRubyObject allocate(Ruby runtimeRubyClass klazz) {
             return new AutoPointer(runtimeklazz);
         }
 
     }
 
     private 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(contextnew IRubyObject[] { value }, .);
     }
 
     @Override
     @JRubyMethod(name = "initialize", visibility = )
     public final IRubyObject initialize(ThreadContext contextIRubyObject pointerArg) {
 
         Ruby runtime = context.runtime;
 
         checkPointer(runtimepointerArg);
 
         // If no release method is defined, then memory leaks will result.
         if (!getMetaClass().respondsTo("release")) {
                 throw runtime.newRuntimeError("No release method defined");
         }
 
         setMemoryIO(((PointerpointerArg).getMemoryIO());
         this. = (PointerpointerArg;        
         setReaper(new Reaper(getMetaClass(), "release"));
 
         return this;
     }
 
     @Override
     @JRubyMethod(name = "initialize", visibility = )
     public final IRubyObject initialize(ThreadContext contextIRubyObject pointerArgIRubyObject releaser) {
 
         checkPointer(context.runtimepointerArg);
 
         setMemoryIO(((PointerpointerArg).getMemoryIO());
         this. = (PointerpointerArg;
         setReaper(new Reaper(releaser"call"));
 
        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(!.);
    }
    private void setReaper(Reaper reaper) {
        Reference<ReaperGroupreaperGroupReference = .get();
        ReaperGroup reaperGroup = reaperGroupReference != null ? reaperGroupReference.get() : null;
        Object referent = reaperGroup != null ? reaperGroup.get() : 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 WeakReferenceReaper<Objectimplements Runnable {
        private static int MAX_REAPERS_PER_GROUP = 100;
        private int reaperCount;
        private volatile Reaper head;
        
        ReaperGroup(Object referent) {
            super(referent);
        }
        
        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 String methodName;
        volatile Reaper next;
        volatile boolean released;
        volatile boolean unmanaged;
        private Reaper(Pointer ptrIRubyObject procString methodName) {
            this. = ptr;
            this. = proc;
            this. = methodName;
        }
        
        final Ruby getRuntime() {
            return .getRuntime();
        }
        
        void dispose(ThreadContext context) {
            .callMethod(context);
        }
        public final void release(ThreadContext context) {
            if (!) {
                 = true;
                dispose(context);
            }
        }
        public final void autorelease(boolean autorelease) {
            this. = !autorelease;
        }
    }
New to GrepCode? Check out our FAQ X