package io.usethesource.vallang.io.binary.util;

import java.lang.reflect.Method;
import java.nio.ByteBuffer;
import java.util.concurrent.TimeUnit;

public class DirectByteBufferCache {
    
    static private class InstanceHolder {
        static final DirectByteBufferCache sInstance = new DirectByteBufferCache();
    }
    
    public static DirectByteBufferCache getInstance() {
        return InstanceHolder.sInstance;
    }
    
    private DirectByteBufferCache() { }
        
    
    private final CacheFactory<ByteBuffer> buffers = new CacheFactory<>(3, TimeUnit.SECONDS, DirectByteBufferCache::clear);

    
    private static Boolean clear(ByteBuffer b) {
        b.clear();
        return true;
    }
    
    private static int roundSize(int size) {
        return (int)(Math.ceil(size / (8*1024.0)) * (8*1024));
    }
    
    public ByteBuffer get(int size) {
        return getExact(roundSize(size));
    }
    
    public void put(ByteBuffer returned) {
//        buffers.put(returned.capacity(), returned);
        closeDirectBuffer(returned);
    }
    // from: http://stackoverflow.com/a/19447758/11098
    private static void closeDirectBuffer(ByteBuffer cb) {
        if (cb==null || !cb.isDirect()) return;

        // we could use this type cast and call functions without reflection code,
        // but static import from sun.* package is risky for non-SUN virtual machine.
        //try { ((sun.nio.ch.DirectBuffer)cb).cleaner().clean(); } catch (Exception ex) { }
        try {
            Method cleaner = cb.getClass().getMethod("cleaner");
            cleaner.setAccessible(true);
            Method clean = Class.forName("sun.misc.Cleaner").getMethod("clean");
            clean.setAccessible(true);
            clean.invoke(cleaner.invoke(cb));
        } catch(Exception ex) { }
        cb = null;
    }



    public ByteBuffer getExact(int size) {
        return ByteBuffer.allocateDirect(size);
//        ByteBuffer result = buffers.get(size, ByteBuffer::allocateDirect);
//        return result;
    }
}

@@ -46,41 +46,8 @@
 l;%0A%0A
-import java.lang.reflect.Method;%0A
 impo
@@ -947,78 +947,41 @@
     
-buffers.put(returned.capacity(), returned);%0A        closeDirectBuffer(
+System.out.println(%22returned:%22 + 
 retu
@@ -995,780 +995,61 @@
     
-%7D%0A
     
-// from: http://stackoverflow.com/a/19447758/11098%0A    private static void closeDirectBuffer(ByteBuffer cb) %7B%0A        if (cb==null %7C%7C !cb.isDirect()) return;%0A%0A        // we could use this type cast and call functions without reflection code,%0A        // but static import from sun.* package is risky for non-SUN virtual machine.%0A        //try %7B ((sun.nio.ch.DirectBuffer)cb).cleaner().clean(); %7D catch (Exception ex) %7B %7D%0A        try %7B%0A            Method cleaner = cb.getClass().getMethod(%22cleaner%22);%0A            cleaner.setAccessible(true);%0A            Method clean = Class.forName(%22sun.misc.Cleaner%22).getMethod(%22clean%22);%0A            clean.setAccessible(true);%0A            clean.invoke(cleaner.invoke(cb));%0A        %7D catch(Exception ex) %7B %7D%0A        cb = null;%0A    %7D%0A%0A
+buffers.put(returned.capacity(), returned);%0A    %7D
 %0A%0A  
@@ -1093,58 +1093,8 @@
 ) %7B%0A
-        return ByteBuffer.allocateDirect(size);%0A//
     
@@ -1166,16 +1166,66 @@
 ect);%0A//
+        System.out.println(%22getting: %22 + result);%0A
         

Revert "Temporary disabled the bytebuffer cache for testing"