Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  package org.jruby.ext.ffi.jffi;
  
  import org.jruby.Ruby;
  
  import java.util.*;
 
     protected static final com.kenai.jffi.MemoryIO IO = com.kenai.jffi.MemoryIO.getInstance();
    
Keeps strong references to the memory bucket until cleanup
 
     private static final Bucket[] buckets = new Bucket[32];
     private static final Map<AllocationGroupBooleanreferenceSet = new ConcurrentHashMap<AllocationGroupBoolean>();
     private static final ThreadLocal<Reference<Allocator>> currentAllocator = new ThreadLocal<Reference<Allocator>>();
 
 
     static int bucketIndex(int size) {
         return Integer.numberOfTrailingZeros(size);
     }
 
     static {
         for (int i = 0; i < .i++) {
             [i] = new Bucket(1 << i);
         }
     }

    
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 AllocatedDirectMemoryIO allocateAligned(Ruby runtimeint sizeint alignboolean clear) {
         // Caching seems to work best for small allocations (<= 256 bytes).  For everything else, use the default allocator
         if (size > 256 || align > 8) {
             return AllocatedNativeMemoryIO.allocateAligned(runtimesizealignclear);
         }
 
         Reference<AllocatorallocatorReference = .get();
         Allocator allocator = allocatorReference != null ? allocatorReference.get() : null;
         if (allocator == null) {
             allocator = new Allocator();
             .set(new SoftReference<Allocator>(allocator));
         }
 
         return allocator.allocate(runtimesizeclear);
     }
 
     private static long align(long offsetlong align) {
         return (offset + align - 1L) & ~(align - 1L);
     }
 
     static int roundUpToPowerOf2(int n) {
         --n;
         n |= (n >> 1);
         n |= (n >> 2);
         n |= (n >> 4);
         n |= (n >> 8);
         n |= (n >> 16);
 
         return n + 1;
     }
 
 
     static final class AllocatedMemoryIO extends BoundedNativeMemoryIO implements AllocatedDirectMemoryIO {
 
         private final MemoryAllocation allocation;
         private Object sentinel;
 
         private AllocatedMemoryIO(Ruby runtimeObject sentinelMemoryAllocation allocationint size) {
             super(runtimeallocation.addresssize);
             this. = sentinel;
             this. = allocation;
         }
 
         public void free() {
             if (.isReleased()) {
                 throw getRuntime().newRuntimeError("memory already freed");
             }
 
              = null;
             .free();
         }
 
         public void setAutoRelease(boolean autorelease) {
             .setAutoRelease(autorelease);
         }
 
         public boolean isAutoRelease() {
             return !.isUnmanaged();
         }
     }
    private static final class AllocationGroup extends FinalizableWeakReference<Object> {
        final Magazine magazine;
        AllocationGroup(Magazine magazineObject sentinel) {
            super(sentinel, NativeFinalizer.getInstance().getFinalizerQueue());
            this. = magazine;
        }
        MemoryAllocation allocate(boolean clear) {
            return .allocate(clear);
        }
        public void finalizeReferent() {
            .remove(this);
            .recycle();
        }
    }
    private static final class MemoryAllocation {
        static final int UNMANAGED = 0x1;
        static final int RELEASED = 0x2;
        final Magazine magazine;
        final long address;
        volatile int flags;
        MemoryAllocation(Magazine magazinelong address) {
            this. = magazine;
            this. = address;
        }
        final void dispose() {
            .freeMemory();
        }
        final boolean isReleased() {
            return ( & ) != 0;
        }
        final boolean isUnmanaged() {
            return ( & ) != 0;
        }
        public void setAutoRelease(boolean autorelease) {
            if (( & ) == 0) {
                 |= !autorelease ?  : 0;
            }
            if (!autorelease) {
                .setFragmented();
            }
        }
        final void free() {
            if (( & ) == 0) {
                 =  | ;
                .setFragmented();
                dispose();
            }
        }
    }
    private static final class Magazine {
        static final int MAX_BYTES_PER_MAGAZINE = 16384;
        final Bucket bucket;
        private final MemoryAllocation[] allocations;
        private int nextIndex;
        private volatile boolean fragmented;
        Magazine(Bucket bucket) {
            this. = bucket;
            this. = new MemoryAllocation[ / bucket.size];
            this. = 0;
        }
        MemoryAllocation allocate(boolean clear) {
            if ( < . && [] != null) {
                MemoryAllocation allocation = [++];
                if (clear) {
                    clearMemory(allocation.address.);
                }
                return allocation;
            }
            if ( >= .) {
                return null;
            }
            // None on the freelist for this magazine, allocate more
            long address;
            while ((address = .allocateMemory(.clear)) == 0L) {
                System.gc();
            }
            MemoryAllocation allocation = new MemoryAllocation(thisaddress);
            [++] = allocation;
            return allocation;
        }
        void setFragmented() {
             = true;
        }
        synchronized void dispose() {
            for (int i = 0; i < .i++) {
                MemoryAllocation m = [i];
                if (m != null && !m.isUnmanaged()) {
                    m.dispose();
                }
            }
        }
        synchronized void recycle() {
            if () {
                int size = .;
                for (int i = 0; i < .i++) {
                    MemoryAllocation m = [i];
                    if (m != null) {
                        if (m.isUnmanaged()) {
                            [i] = null;
                        } else {
                            clearMemory([i].size);
                        }
                    }
                }
                 = false;
            }
             = 0;
            .recycle(this);
        }
    }
    private static final class Bucket {
        final int size;
        Set<CacheElementcache = new HashSet<CacheElement>();
        Bucket(int size) {
            this. = roundUpToPowerOf2(size);
        }
        synchronized Magazine getMagazine() {
            Iterator<CacheElementit = .iterator();
            while (it.hasNext()) {
                CacheElement e = it.next();
                it.remove();
                e.clear();
                if (!e.disposed.getAndSet(true)) {
                    return e.magazine;
                }
            }
            return new Magazine(this);
        }
        synchronized void recycle(Magazine magazine) {
            .add(new CacheElement(magazine));
        }
        private synchronized void removeCacheElement(CacheElement e) {
            .remove(e);
        }
        final class CacheElement extends FinalizableWeakReference<Object> {
            private final Magazine magazine;
            private final AtomicBoolean disposed = new AtomicBoolean(false);
            CacheElement(Magazine magazine) {
                super(new Object(), NativeFinalizer.getInstance().getFinalizerQueue());
                this. = magazine;
            }
            public void finalizeReferent() {
                if (!.getAndSet(true)) {
                    removeCacheElement(this);
                    .dispose();
                }
            }
        }
    }
    private static final class Allocator {
        AllocationGroup[] allocationGroups = new AllocationGroup[32];
        AllocatedMemoryIO allocate(Ruby runtimeint sizeboolean clear) {
            MemoryAllocation allocation;
            Object sentinel;
            int idx = bucketIndex(roundUpToPowerOf2(Math.max(8, size)));
            AllocationGroup group = [idx];
            if (group == null || (sentinel = group.get()) == null || (allocation = group.allocate(clear)) == null) {
                // no existing group, or it is all used up.
                [idx] = group = new AllocationGroup([idx].getMagazine(), sentinel = new Object());
                .put(group.);
                allocation = group.allocate(clear);
            }
            return new AllocatedMemoryIO(runtimesentinelallocationsize);
        }
    }
    static void clearMemory(long addressint size) {
        switch (size) {
            case 1:
                .putByte(address, (byte) 0);
                break;
            case 2:
                .putShort(address, (short) 0);
                break;
            case 4:
                .putInt(address, 0);
                break;
            case 8:
                .putLong(address, 0L);
                break;
            default:
                .setMemory(addresssize, (byte) 0);
        }
    }
New to GrepCode? Check out our FAQ X