| 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 */  | 
 | 
 | 
 | 
package sun.java2d.marlin;  | 
 | 
 | 
 | 
import java.lang.ref.PhantomReference;  | 
 | 
import java.lang.ref.ReferenceQueue;  | 
 | 
import java.security.AccessController;  | 
 | 
import java.security.PrivilegedAction;  | 
 | 
import java.util.Vector;  | 
 | 
import static sun.java2d.marlin.MarlinConst.logUnsafeMalloc;  | 
 | 
import sun.misc.ThreadGroupUtils;  | 
 | 
import sun.misc.Unsafe;  | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 */  | 
 | 
final class OffHeapArray  { | 
 | 
 | 
 | 
      | 
 | 
    static final Unsafe unsafe;  | 
 | 
      | 
 | 
    static final int SIZE_INT;  | 
 | 
 | 
 | 
      | 
 | 
    private static final ReferenceQueue<Object> rdrQueue  | 
 | 
        = new ReferenceQueue<Object>();  | 
 | 
      | 
 | 
    private static final Vector<OffHeapReference> refList  | 
 | 
        = new Vector<OffHeapReference>(32);  | 
 | 
 | 
 | 
    static { | 
 | 
        unsafe   = Unsafe.getUnsafe();  | 
 | 
        SIZE_INT = Unsafe.ARRAY_INT_INDEX_SCALE;  | 
 | 
 | 
 | 
          | 
 | 
        AccessController.doPrivileged(  | 
 | 
            (PrivilegedAction<Void>) () -> { | 
 | 
                  | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
                 */  | 
 | 
                final ThreadGroup rootTG  | 
 | 
                    = ThreadGroupUtils.getRootThreadGroup();  | 
 | 
                final Thread t = new Thread(rootTG, new OffHeapDisposer(),  | 
 | 
                    "MarlinRenderer Disposer");  | 
 | 
                t.setContextClassLoader(null);  | 
 | 
                t.setDaemon(true);  | 
 | 
                t.setPriority(Thread.MAX_PRIORITY);  | 
 | 
                t.start();  | 
 | 
                return null;  | 
 | 
            }  | 
 | 
        );  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
    long address;  | 
 | 
    long length;  | 
 | 
    int  used;  | 
 | 
 | 
 | 
    OffHeapArray(final Object parent, final long len) { | 
 | 
          | 
 | 
        this.address = unsafe.allocateMemory(len);  | 
 | 
        this.length  = len;  | 
 | 
        this.used    = 0;  | 
 | 
        if (logUnsafeMalloc) { | 
 | 
            MarlinUtils.logInfo(System.currentTimeMillis()  | 
 | 
                                + ": OffHeapArray.allocateMemory = "  | 
 | 
                                + len + " to addr = " + this.address);  | 
 | 
        }  | 
 | 
 | 
 | 
          | 
 | 
        refList.add(new OffHeapReference(parent, this));  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    void resize(final long len) { | 
 | 
          | 
 | 
        this.address = unsafe.reallocateMemory(address, len);  | 
 | 
        this.length  = len;  | 
 | 
        if (logUnsafeMalloc) { | 
 | 
            MarlinUtils.logInfo(System.currentTimeMillis()  | 
 | 
                                + ": OffHeapArray.reallocateMemory = "  | 
 | 
                                + len + " to addr = " + this.address);  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
    void free() { | 
 | 
        unsafe.freeMemory(this.address);  | 
 | 
        if (logUnsafeMalloc) { | 
 | 
            MarlinUtils.logInfo(System.currentTimeMillis()  | 
 | 
                                + ": OffHeapEdgeArray.free = "  | 
 | 
                                + this.length  | 
 | 
                                + " at addr = " + this.address);  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
    void fill(final byte val) { | 
 | 
        unsafe.setMemory(this.address, this.length, val);  | 
 | 
    }  | 
 | 
 | 
 | 
    static final class OffHeapReference extends PhantomReference<Object> { | 
 | 
 | 
 | 
        private final OffHeapArray array;  | 
 | 
 | 
 | 
        OffHeapReference(final Object parent, final OffHeapArray edges) { | 
 | 
            super(parent, rdrQueue);  | 
 | 
            this.array = edges;  | 
 | 
        }  | 
 | 
 | 
 | 
        void dispose() { | 
 | 
              | 
 | 
            this.array.free();  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
    static final class OffHeapDisposer implements Runnable { | 
 | 
        @Override  | 
 | 
        public void run() { | 
 | 
            final Thread currentThread = Thread.currentThread();  | 
 | 
            OffHeapReference ref;  | 
 | 
 | 
 | 
              | 
 | 
            for (; !currentThread.isInterrupted();) { | 
 | 
                try { | 
 | 
                    ref = (OffHeapReference)rdrQueue.remove();  | 
 | 
                    ref.dispose();  | 
 | 
 | 
 | 
                    refList.remove(ref);  | 
 | 
 | 
 | 
                } catch (InterruptedException ie) { | 
 | 
                    MarlinUtils.logException("OffHeapDisposer interrupted:", | 
 | 
                                             ie);  | 
 | 
                }  | 
 | 
            }  | 
 | 
        }  | 
 | 
    }  | 
 | 
}  |