java/com/jetbrains/cef/SharedMemory.java (146 lines of code) (raw):
package com.jetbrains.cef;
import com.jetbrains.cef.remote.NativeServerManager;
import org.cef.OS;
import org.cef.SystemBootstrap;
import org.cef.misc.CefLog;
import org.cef.misc.Utils;
import java.io.File;
import java.nio.ByteBuffer;
public class SharedMemory {
private static final String ALT_MEM_HELPER_PATH;
private static volatile boolean isLoaded = false;
public final String mname;
public final long boostHandle;
public long lasUsedMs = 0;
final private long mySegment;
final private long myPtr;
final private long myMutex;
static {
final String altMemHelperPath = Utils.getString("ALT_MEM_HELPER_PATH");
if (altMemHelperPath != null && !altMemHelperPath.trim().isEmpty())
ALT_MEM_HELPER_PATH = altMemHelperPath.trim();
else if (NativeServerManager.ALT_CEF_SERVER_PATH != null && !NativeServerManager.ALT_CEF_SERVER_PATH.trim().isEmpty()) {
File libDir = new File(NativeServerManager.ALT_CEF_SERVER_PATH).getParentFile();
String libName;
if (OS.isWindows())
libName = "shared_mem_helper.dll";
else if (OS.isLinux())
libName = "libshared_mem_helper.so";
else {
// libshared_mem_helper.dylib is usually place near cef_server.app but ALT_CEF_SERVER_PATH is like cef_server.app/Contents/MacOS/cef_server
libDir = libDir.getParentFile().getParentFile().getParentFile();
libName = "libshared_mem_helper.dylib";
}
ALT_MEM_HELPER_PATH = new File(libDir, libName).getAbsolutePath();
} else
ALT_MEM_HELPER_PATH = null;
loadDynamicLib();
}
public static boolean isIsLoaded() { return isLoaded; }
public static void loadDynamicLib() {
if (isLoaded)
return;
try {
if (ALT_MEM_HELPER_PATH == null || ALT_MEM_HELPER_PATH.isEmpty()) {
CefLog.Debug("Load shared_mem_helper library from jbr bundle.");
SystemBootstrap.loadLibrary("shared_mem_helper");
} else {
CefLog.Debug("Load shared_mem_helper library from alt path %s", ALT_MEM_HELPER_PATH);
System.load(ALT_MEM_HELPER_PATH.trim());
}
isLoaded = true;
} catch (UnsatisfiedLinkError e) {
CefLog.Error("Can't load shared_mem_helper, exception: %s", e.getMessage());
}
}
public static void loadDynamicLib(String path) {
if (isLoaded)
return;
try {
CefLog.Debug("Load shared_mem_helper library from file %s", path);
System.load(path.trim());
isLoaded = true;
} catch (UnsatisfiedLinkError e) {
CefLog.Error("Can't load shared_mem_helper, exception: %s", e.getMessage());
}
}
public SharedMemory(String sharedMemName, long boostHandle) {
mname = sharedMemName;
this.boostHandle = boostHandle;
this.mySegment = openSharedSegment(sharedMemName);
this.myPtr = getPointer(mySegment, boostHandle);
myMutex = openSharedMutex(sharedMemName);
}
public void lock() {
lockSharedMutex(myMutex);
}
public void unlock() {
unlockSharedMutex(myMutex);
}
public long getPtr() {
return myPtr;
}
@Override
protected void finalize() throws Throwable {
try {
closeSharedSegment(mySegment);
closeSharedMutex(myMutex);
} finally {
super.finalize();
}
}
public ByteBuffer wrap(int size) {
return wrapNativeMem(myPtr, size);
}
public int readInt() {
return readInt(myPtr, 0);
}
public int readInt(int offset) {
return readInt(myPtr, offset);
}
public int readByte(int offset) {
return readByte(myPtr, offset);
}
// Helper method (for creating BufferedImage from native raster)
private static native ByteBuffer wrapNativeMem(long pdata, int length);
private static native int readInt(long pdata, int offset);
private static native int readByte(long pdata, int offset);
public static class WithRaster extends SharedMemory {
private int myWidth;
private int myHeight;
private int myDirtyRectsCount;
public WithRaster(String sharedMemName, long boostHandle) {
super(sharedMemName, boostHandle);
}
public ByteBuffer wrapRaster() {
return wrapNativeMem(getPtr(), myWidth * myHeight * 4);
}
public ByteBuffer wrapRects() {
return wrapNativeMem(getPtr() + getRectsOffset(), myDirtyRectsCount * 4 * 4);
}
public int getRectsOffset() { return myWidth * myHeight * 4; }
public int getWidth() {
return myWidth;
}
public void setWidth(int width) {
this.myWidth = width;
}
public int getHeight() {
return myHeight;
}
public void setHeight(int height) {
this.myHeight = height;
}
public int getDirtyRectsCount() {
return myDirtyRectsCount;
}
public void setDirtyRectsCount(int dirtyRectsCount) {
this.myDirtyRectsCount = dirtyRectsCount;
}
}
//
// Private native API
//
private static native long openSharedSegment(String sid);
private static native long getPointer(long segment, long handle);
private static native void closeSharedSegment(long segment);
private static native long openSharedMutex(String uid);
private static native void lockSharedMutex(long mutex);
private static native void unlockSharedMutex(long mutex);
private static native void closeSharedMutex(long mutex);
}