package net.openhft.chronicle.core.io;

import net.openhft.chronicle.core.Jvm;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.TimeUnit;

public enum BackgroundResourceReleaser {
    ;
    static final boolean BG_RELEASER = Jvm.getBoolean("background.releaser", true);

    private static final BlockingQueue<Object> RESOURCES = new ArrayBlockingQueue<>(128);
    private static transient long COUNT = 0;
    private static final Thread RELEASER = new Thread(BackgroundResourceReleaser::runReleaseResources,
            "background~resource~releaser");

    static {
        RELEASER.setDaemon(true);
        RELEASER.start();
    }

    private static void runReleaseResources() {
        try {
            for (; ; ) {
                Object o = RESOURCES.take();
                COUNT++;
                performRelease(o);
                COUNT++;
            }
        } catch (InterruptedException e) {
            Jvm.warn().on(BackgroundResourceReleaser.class, "Died on interrupt");
        }
    }

    public static void release(AbstractCloseable closeable) {
        release0(closeable);
    }

    private static void release0(Object o) {
        if (RESOURCES.offer(o))
            return;
        performRelease(o);
    }

    public static void releasePendingResources() {
        try {
            for (; ; ) {
                long count = COUNT;
                Object o = RESOURCES.poll(1, TimeUnit.MILLISECONDS);
                if (o == null) {
                    long count2 = COUNT;
                    if (count != count2 || (count2 & 1) == 1)
                        continue;
                    return;
                }
                performRelease(o);
            }
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }

    public static void release(AbstractReferenceCounted referenceCounted) {
        release0(referenceCounted);
    }

    private static void performRelease(Object o) {
        if (o instanceof AbstractCloseable)
            ((AbstractCloseable) o).performClose();
        else if (o instanceof AbstractReferenceCounted)
            ((AbstractReferenceCounted) o).performRelease();
        else
            Jvm.warn().on(BackgroundResourceReleaser.class, "Don't know how to release a " + o.getClass());
    }
}

@@ -429,53 +429,8 @@
 8);%0A
-    private static transient long COUNT = 0;%0A
     
@@ -528,16 +528,16 @@
 ources,%0A
+
         
@@ -798,33 +798,78 @@
             
-COUNT++;%0A
+synchronized (BackgroundResourceReleaser.class) %7B%0A    
             
@@ -911,16 +911,9 @@
     
-COUNT++;
+%7D
 %0A   
@@ -1388,44 +1388,8 @@
 ) %7B%0A
-                long count = COUNT;%0A
     
@@ -1510,90 +1510,57 @@
     
-long count2 = COUNT;%0A                    if (count != count2 %7C%7C (count2 & 1) == 1)
+synchronized (BackgroundResourceReleaser.class) %7B
 %0A   
@@ -1584,16 +1584,14 @@
     
-continue
+return
 ;%0A  
@@ -1600,39 +1600,33 @@
                 
-return;
+%7D
 %0A               

Use a lock to ensure the releasePendingResources() doesn't return while the background thread is busy.