com.github.bloodshura.ignitium.ntv.shm.impl.UnixSharedMemory Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of ignitium-native Show documentation
Show all versions of ignitium-native Show documentation
An API for working with native system APIs, with a higher-level interface.
The newest version!
package com.github.bloodshura.ignitium.ntv.shm.impl;
import com.github.bloodshura.ignitium.ntv.ErrorCodeNativeException;
import com.github.bloodshura.ignitium.ntv.NativeException;
import com.github.bloodshura.ignitium.ntv.lib.Unix;
import com.github.bloodshura.ignitium.ntv.shm.SharedMemory;
import com.github.bloodshura.ignitium.ntv.util.Buffer;
import com.github.bloodshura.ignitium.ntv.util.RangeUtils;
import com.sun.jna.Pointer;
import javax.annotation.Nonnull;
public class UnixSharedMemory implements SharedMemory {
private int identifier;
private Pointer segment;
private final int size;
public UnixSharedMemory(int key, int size, boolean createIfInexistent) throws NativeException {
this(key, size, createIfInexistent ? 0x1B6 | 0x200 : 0x1B6);
}
public UnixSharedMemory(int key, int size, int flags) throws NativeException {
this.identifier = Unix.Shm.shmget(key, size, flags);
this.size = size;
if (identifier == -1) {
throw new ErrorCodeNativeException("Could not retrieve identifier for shared memory of ID " + key + " and size " + size + " bytes");
}
this.segment = Unix.Shm.shmat(identifier, null, 0);
if (Pointer.nativeValue(segment) == 0xFFFFFFFF /* -1 */) {
throw new ErrorCodeNativeException("Could not attach to shared memory's identifier");
}
}
public void destroy() throws NativeException {
ensureNotMarkedToDestruction();
if (Unix.Shm.shmctl(identifier, 0x0 /* IPC_RMID */, null) != 0x0) {
throw new ErrorCodeNativeException("Could not mark shared memory segment to be destroyed");
}
this.identifier = -1;
}
@Override
public void dispose() throws NativeException {
ensureNotDisposed();
if (Unix.Shm.shmdt(segment) != 0x0) {
throw new ErrorCodeNativeException("Could not detach the shared memory segment");
}
this.segment = null;
}
@Override
public long getIdentifier() throws NativeException {
ensureNotMarkedToDestruction();
return identifier;
}
@Override
public int getSize() {
return size;
}
@Override
public boolean isReadable(long address, int size) throws NativeException {
ensureNotDisposed();
return RangeUtils.validateRange(address, size, getSize());
}
@Override
public boolean isWritable(long address, int size) throws NativeException {
ensureNotDisposed();
return RangeUtils.validateRange(address, size, getSize());
}
@Override
public void read(long address, @Nonnull Buffer buffer, int size) throws NativeException {
ensureNotDisposed();
RangeUtils.checkRange(address, size, (int) buffer.size());
RangeUtils.checkRange(address, size, getSize());
byte[] helper = new byte[size];
// TODO Should we use Pointer::getByteBuffer and ByteBuffer::put instead of primitive arrays?
segment.read(address, helper, 0, size);
buffer.write(0, helper, 0, size);
}
@Override
public void write(long address, @Nonnull Buffer buffer) throws NativeException {
ensureNotDisposed();
RangeUtils.checkRange(address, (int) buffer.size(), getSize());
int size = (int) buffer.size();
byte[] helper = new byte[size];
// TODO Should we use Pointer::getByteBuffer and ByteBuffer::put instead of primitive arrays?
buffer.read(0, helper, 0, size);
segment.write(address, helper, 0, size);
}
private void ensureNotDisposed() throws NativeException {
if (segment == null) {
throw new NativeException("Shared memory already disposed");
}
}
private void ensureNotMarkedToDestruction() throws NativeException {
if (identifier == -1) {
throw new NativeException("Shared memory already marked to be destroyed");
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy