All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.bloodshura.ignitium.ntv.shm.impl.UnixSharedMemory Maven / Gradle / Ivy

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