@Override public void close() throws IOException { try { super.close(); } finally { synchronized (REAPER_THREAD_LOCK) { --GLOBAL_SAFETY_NET_REGISTRY_COUNT; if (0 == GLOBAL_SAFETY_NET_REGISTRY_COUNT) { REAPER_THREAD.interrupt(); REAPER_THREAD = null; } } } }
@Test public void testSafetyNetClose() throws Exception { setup(20); startThreads(); joinThreads(); for (int i = 0; i < 5 && unclosedCounter.get() > 0; ++i) { System.gc(); Thread.sleep(50); } Assert.assertEquals(0, unclosedCounter.get()); closeableRegistry.close(); }
@Test public void testClose() throws Exception { setup(Integer.MAX_VALUE); startThreads(); for (int i = 0; i < 5; ++i) { System.gc(); Thread.sleep(40); } closeableRegistry.close(); joinThreads(); assertEquals(0, unclosedCounter.get()); assertEquals(0, closeableRegistry.getNumberOfRegisteredCloseables()); final TestCloseable testCloseable = new TestCloseable(); try { registerCloseable(testCloseable); fail("Closed registry should not accept closeables!"); } catch (IOException expected) {} assertTrue(testCloseable.isClosed()); assertEquals(0, unclosedCounter.get()); assertEquals(0, closeableRegistry.getNumberOfRegisteredCloseables()); }
@Test public void testNonBlockingClose() throws Exception { setup(Integer.MAX_VALUE); final BlockingTestCloseable blockingCloseable = new BlockingTestCloseable(); registerCloseable(blockingCloseable); assertEquals(1, closeableRegistry.getNumberOfRegisteredCloseables()); Thread closer = new Thread(() -> { try { closeableRegistry.close(); } catch (IOException ignore) { } }); closer.start(); blockingCloseable.awaitClose(TEST_TIMEOUT_SECONDS, TimeUnit.SECONDS); final TestCloseable testCloseable = new TestCloseable(); try { registerCloseable(testCloseable); fail("Closed registry should not accept closeables!"); } catch (IOException ignored) {} blockingCloseable.unblockClose(); closer.join(); assertTrue(testCloseable.isClosed()); assertEquals(0, closeableRegistry.getNumberOfRegisteredCloseables()); }
@Override public void close() throws IOException { try { super.close(); } finally { synchronized (REAPER_THREAD_LOCK) { --GLOBAL_SAFETY_NET_REGISTRY_COUNT; if (0 == GLOBAL_SAFETY_NET_REGISTRY_COUNT) { REAPER_THREAD.interrupt(); REAPER_THREAD = null; } } } }
@Override public void close() throws IOException { try { super.close(); } finally { synchronized (REAPER_THREAD_LOCK) { --GLOBAL_SAFETY_NET_REGISTRY_COUNT; if (0 == GLOBAL_SAFETY_NET_REGISTRY_COUNT) { REAPER_THREAD.interrupt(); REAPER_THREAD = null; } } } }