Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  package org.jruby.ext.ffi.jffi;
  
  import java.util.Map;
  
  import org.jruby.Ruby;
 
 final class AllocatedNativeMemoryIO extends BoundedNativeMemoryIO implements AllocatedDirectMemoryIO {
    
Keeps strong references to the memory bucket until cleanup
 
     private static final Map<AllocationGroupBooleanreferenceSet = new ConcurrentHashMap<AllocationGroupBoolean>();
     private static final ThreadLocal<Reference<AllocationGroup>> currentBucket = new ThreadLocal<Reference<AllocationGroup>>();
 
     private final MemoryAllocation allocation;
     private final Object sentinel;

    
Allocates native memory

Parameters:
runtime The Ruby runtime
size The number of bytes to allocate
clear Whether the memory should be cleared (zeroed)
Returns:
A new org.jruby.ext.ffi.AllocatedDirectMemoryIO
 
     static final AllocatedNativeMemoryIO allocate(Ruby runtimeint sizeboolean clear) {
         return allocateAligned(runtimesize, 1, clear);
     }

    
Allocates native memory, aligned to a minimum boundary.

Parameters:
runtime The Ruby runtime
size The number of bytes to allocate
align The minimum alignment of the memory
clear Whether the memory should be cleared (zeroed)
Returns:
A new org.jruby.ext.ffi.AllocatedDirectMemoryIO
 
     static AllocatedNativeMemoryIO allocateAligned(Ruby runtimeint sizeint alignboolean clear) {
         long address;
         for (int i = 0; (address = .allocateMemory(size + align - 1, clear)) == 0L && i < 100; i++) {
             // No available memory; trigger a full GC to reclaim some memory
             System.gc();
         }
         if (address == 0L) {
             throw runtime.newRuntimeError("failed to allocate " + size + " bytes of native memory");
         }
 
         try {
             /*
             * Instead of using a WeakReference per memory allocation to free the native memory, memory allocations
             * are grouped together into a bucket with a reference to a common object which has a WeakReference.
             *
             * When all the MemoryIO instances are no longer referenced, the common object can be garbage collected
             * and its WeakReference en-queued, and then the group of memory allocations will be freed in one hit.
             *
             * This reduces the overhead of automatically freed native memory allocations by about 70%
             */
             Reference<AllocationGroupallocationGroupReference = .get();
             AllocationGroup allocationGroup = allocationGroupReference != null ? allocationGroupReference.get() : null;
             Object sentinel = allocationGroup != null ? allocationGroup.get() : null;
 
             if (sentinel == null || !allocationGroup.canAccept(size)) {
                 .put(allocationGroup = new AllocationGroup(sentinel = new Object()), .);
                 .set(new SoftReference<AllocationGroup>(allocationGroup));
             }
 
             AllocatedNativeMemoryIO io = new AllocatedNativeMemoryIO(runtimesentineladdresssizealign);
             allocationGroup.add(io.allocationsize);
 
             return io;
 
         } catch (Throwable t) {
             .freeMemory(address);
             throw new RuntimeException(t);
         }
     }
     
     private AllocatedNativeMemoryIO(Ruby runtimeObject sentinellong addressint sizeint align) {
         super(runtime, ((address - 1) & ~(align - 1)) + alignsize);
         this. = sentinel;
         this. = new MemoryAllocation(address);
     }
 
     public void free() {
         if (.) {
             throw getRuntime().newRuntimeError("memory already freed");
         }
         
         .free();
     }
 
     public void setAutoRelease(boolean autorelease) {
         if (autorelease && !.) {
             . = !autorelease;
         }
    }
    public boolean isAutoRelease() {
        return !.;
    }

    
Holder for a group of memory allocations.
    private static final class AllocationGroup extends WeakReferenceReaper<Objectimplements Runnable {
        public static final int MAX_BYTES_PER_BUCKET = 4096;
        private volatile MemoryAllocation head = null;
        private long bytesUsed = 0;
        
        AllocationGroup(Object sentinel) {
            super(sentinel);
        }
        void add(MemoryAllocation mint size) {
             += size;
            m.next = ;
             = m;
        }
        boolean canAccept(int size) {
            return  + size < ;
        }
        public final void run() {
            .remove(this);
            MemoryAllocation m = ;
            while (m != null) {
                if (!m.unmanaged) {
                    m.dispose();
                }
                m = m.next;
            }
        }
    }

    
Represents a single native memory allocation
    private static final class MemoryAllocation {
        private final long address;
        volatile boolean released;
        volatile boolean unmanaged;
        volatile MemoryAllocation next;
        MemoryAllocation(long address) {
            this. = address;
        }
        final void dispose() {
            .freeMemory();
        }
        final void free() {
            if (!) {
                 = true;
                 = true;
                dispose();
            }
        }
    }
New to GrepCode? Check out our FAQ X