Refactor G2DRenderer and G2DRendererControl to replace Semaphore with ReentrantReadWriteLock for improved concurrency management
This commit is contained in:
@@ -9,8 +9,9 @@ import java.io.ByteArrayOutputStream;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.Semaphore;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.concurrent.locks.Lock;
|
||||||
|
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||||
|
|
||||||
import javax.imageio.ImageIO;
|
import javax.imageio.ImageIO;
|
||||||
|
|
||||||
@@ -36,7 +37,7 @@ public class G2DRenderer implements Renderer {
|
|||||||
|
|
||||||
private static final Logger LOGGER = LoggerFactory.getLogger(G2DRenderer.class);
|
private static final Logger LOGGER = LoggerFactory.getLogger(G2DRenderer.class);
|
||||||
|
|
||||||
private static final long SLEEP_PRECISION = TimeUnit.MILLISECONDS.toNanos(3);
|
private static final long SLEEP_PRECISION = TimeUnit.MILLISECONDS.toNanos(2);
|
||||||
|
|
||||||
private final RingBuffer<Integer> fpsHistory = new RingBuffer<>(90);
|
private final RingBuffer<Integer> fpsHistory = new RingBuffer<>(90);
|
||||||
|
|
||||||
@@ -54,7 +55,7 @@ public class G2DRenderer implements Renderer {
|
|||||||
|
|
||||||
private long frameDur;
|
private long frameDur;
|
||||||
|
|
||||||
private final Semaphore semaphore = new Semaphore(1);
|
private final ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock(true);
|
||||||
|
|
||||||
private String title;
|
private String title;
|
||||||
|
|
||||||
@@ -63,6 +64,7 @@ public class G2DRenderer implements Renderer {
|
|||||||
public G2DRenderer() {
|
public G2DRenderer() {
|
||||||
LOGGER.info("ctor");
|
LOGGER.info("ctor");
|
||||||
|
|
||||||
|
System.setProperty("java.awt.headless", "false");
|
||||||
System.setProperty("sun.java2d.uiScale", "1");
|
System.setProperty("sun.java2d.uiScale", "1");
|
||||||
System.setProperty("awt.nativeDoubleBuffering", "true");
|
System.setProperty("awt.nativeDoubleBuffering", "true");
|
||||||
System.setProperty("awt.useSystemAAFontSettings", "on");
|
System.setProperty("awt.useSystemAAFontSettings", "on");
|
||||||
@@ -100,7 +102,7 @@ public class G2DRenderer implements Renderer {
|
|||||||
@Override
|
@Override
|
||||||
public void run(final List<RenderingBo> renderingBOs) throws InterruptedException {
|
public void run(final List<RenderingBo> renderingBOs) throws InterruptedException {
|
||||||
try {
|
try {
|
||||||
this.semaphore.acquire();
|
this.rwLock.readLock().lockInterruptibly();
|
||||||
try {
|
try {
|
||||||
if (this.mainFrame == null) {
|
if (this.mainFrame == null) {
|
||||||
return;
|
return;
|
||||||
@@ -180,7 +182,7 @@ public class G2DRenderer implements Renderer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
this.semaphore.release();
|
this.rwLock.readLock().unlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (final G2DRendererWindowNotInitializedException e) {
|
catch (final G2DRendererWindowNotInitializedException e) {
|
||||||
@@ -291,8 +293,12 @@ public class G2DRenderer implements Renderer {
|
|||||||
this.mainFrame = mainFrame;
|
this.mainFrame = mainFrame;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Semaphore getSemaphore() {
|
public Lock getReadLock() {
|
||||||
return this.semaphore;
|
return this.rwLock.readLock();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Lock getWriteLock() {
|
||||||
|
return this.rwLock.writeLock();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -49,12 +49,7 @@ public class G2DRendererControl implements RendererControl {
|
|||||||
@Override
|
@Override
|
||||||
public void applyVideoOptions() {
|
public void applyVideoOptions() {
|
||||||
final Runnable run = () -> {
|
final Runnable run = () -> {
|
||||||
try {
|
this.renderer.getWriteLock().lock();
|
||||||
this.renderer.getSemaphore().acquire();
|
|
||||||
}
|
|
||||||
catch (final InterruptedException e) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
try {
|
try {
|
||||||
if (this.renderer.getMainFrame() != null) {
|
if (this.renderer.getMainFrame() != null) {
|
||||||
this.renderer.getMainFrame().unregisterFullScreenWindow();
|
this.renderer.getMainFrame().unregisterFullScreenWindow();
|
||||||
@@ -95,7 +90,7 @@ public class G2DRendererControl implements RendererControl {
|
|||||||
this.updateViewPort(false, false);
|
this.updateViewPort(false, false);
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
this.renderer.getSemaphore().release();
|
this.renderer.getWriteLock().unlock();
|
||||||
this.videoOptionsAppliedAt = System.currentTimeMillis();
|
this.videoOptionsAppliedAt = System.currentTimeMillis();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -162,11 +157,7 @@ public class G2DRendererControl implements RendererControl {
|
|||||||
|
|
||||||
final Runnable run = () -> {
|
final Runnable run = () -> {
|
||||||
if (lockRenderer) {
|
if (lockRenderer) {
|
||||||
try {
|
this.renderer.getWriteLock().lock();
|
||||||
this.renderer.getSemaphore().acquire();
|
|
||||||
}
|
|
||||||
catch (final InterruptedException e) {
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
this.updateAbsoluteViewportPortDimension();
|
this.updateAbsoluteViewportPortDimension();
|
||||||
@@ -176,7 +167,7 @@ public class G2DRendererControl implements RendererControl {
|
|||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
if (lockRenderer) {
|
if (lockRenderer) {
|
||||||
this.renderer.getSemaphore().release();
|
this.renderer.getWriteLock().unlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user