--- /dev/null
+/*
+ * Copyright (C) 2021 Michael Zucchi
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package api;
+
+import jdk.incubator.foreign.MemoryAccess;
+import jdk.incubator.foreign.MemorySegment;
+
+public interface Frame extends AutoCloseable {
+
+ MemorySegment allocate(long size, long alignment);
+
+ @Override
+ public void close();
+
+ default MemorySegment allocate(long size) {
+ return allocate(size, 1);
+ }
+
+ default MemorySegment copy(byte value) {
+ MemorySegment mem = allocate(1);
+ MemoryAccess.setByte(mem, value);
+ return mem;
+ }
+
+ default MemorySegment copy(int value) {
+ MemorySegment mem = allocate(4, 4);
+ MemoryAccess.setInt(mem, value);
+ return mem;
+ }
+
+ default MemorySegment copy(long value) {
+ MemorySegment mem = allocate(8, 8);
+ MemoryAccess.setLong(mem, value);
+ return mem;
+ }
+
+ default MemorySegment copy(byte[] value, int alignment) {
+ MemorySegment mem = allocate(value.length, alignment);
+ mem.copyFrom(MemorySegment.ofArray(value));
+ return mem;
+ }
+
+ default MemorySegment copy(int[] value, int alignment) {
+ MemorySegment mem = allocate(value.length * 4, alignment);
+ mem.copyFrom(MemorySegment.ofArray(value));
+ return mem;
+ }
+
+ default MemorySegment copy(long[] value, int alignment) {
+ MemorySegment mem = allocate(value.length * 8, alignment);
+ mem.copyFrom(MemorySegment.ofArray(value));
+ return mem;
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (C) 2021 Michael Zucchi
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package au.notzed.zcl;
+
+import api.Frame;
+import api.Memory;
+import jdk.incubator.foreign.MemorySegment;
+import static org.junit.Assert.*;
+import org.junit.Before;
+import org.junit.Test;
+
+public class MemoryTest {
+
+ @Before
+ public void setup() {
+ }
+
+ @Test
+ public void testFrameAlignment() throws Exception {
+ System.out.println("testFrame Alignment");
+
+ try (Frame frame = Memory.createFrame()) {
+ MemorySegment a = frame.allocate(1, 1);
+ MemorySegment b = frame.allocate(16, 16);
+ MemorySegment c = frame.allocate(2, 2);
+ MemorySegment d = frame.allocate(8, 8);
+
+ assertEquals(b.address().toRawLongValue() & 15, 0);
+ assertEquals(d.address().toRawLongValue() & 7, 0);
+ }
+ }
+
+ /*
+ @Test
+ public void testFrameExhaustion() throws Exception {
+ Throwable x = null;
+
+ System.out.println("testFrame Exhaustion");
+
+ try (Frame frame = Memory.createFrame()) {
+ while (true)
+ frame.allocate(8);
+ } catch (OutOfMemoryError e) {
+ x = e;
+ }
+
+ assertNotNull(x);
+ assertEquals(x.getClass(), OutOfMemoryError.class);
+ }*/
+ @Test
+ public void testFrameLarge() throws Exception {
+ System.out.println("testFrame Large");
+
+ try (Frame frame = Memory.createFrame()) {
+ MemorySegment a = frame.allocate(1024 * 1024);
+ MemorySegment b = frame.allocate(1024 * 1024);
+ MemorySegment c = frame.allocate(1024 * 1024);
+ assertNotNull(a);
+ assertNotNull(b);
+ assertNotNull(c);
+ }
+ }
+
+ @Test
+ public void testBadAlignment() throws Exception {
+ Throwable x = null;
+
+ System.out.println("testFrame Bad alignment");
+
+ try (Frame frame = Memory.createFrame()) {
+ MemorySegment a = frame.allocate(1, 3);
+ } catch (IllegalArgumentException e) {
+ x = e;
+ }
+
+ assertNotNull(x);
+ assertEquals(x.getClass(), IllegalArgumentException.class);
+ }
+
+ @Test
+ public void testAfterClose() throws Exception {
+ Throwable x = null;
+
+ System.out.println("testFrame use after close");
+
+ Frame frame = Memory.createFrame();
+ frame.close();
+ try {
+ MemorySegment a = frame.allocate(1, 3);
+ } catch (IllegalStateException e) {
+ x = e;
+ }
+
+ assertNotNull(x);
+ assertEquals(x.getClass(), IllegalStateException.class);
+ }
+
+ static void assertSeparate(MemorySegment a, MemorySegment b) {
+ long ap = a.address().toRawLongValue();
+ long as = a.byteSize();
+ long bp = b.address().toRawLongValue();
+ long bs = b.byteSize();
+
+ assertNotEquals(ap, bp);
+ if (ap < bp) {
+ assertTrue(String.format("memory overlap %016x - %016x, %016x - %016x", ap, ap + as, bp, bp + bs), ap + as <= bp);
+ } else {
+ assertTrue(String.format("memory overlap %016x - %016x, %016x - %016x", bp, bp + bs, ap, ap + as), bp + bs <= ap);
+ }
+
+ }
+
+ @Test
+ public void testFrameAlloc() throws Exception {
+ System.out.println("testFrame Alloc");
+
+ try (Frame frame = Memory.createFrame()) {
+ MemorySegment a = frame.allocate(1, 1);
+ MemorySegment b = frame.allocate(16, 16);
+ MemorySegment c = frame.allocate(2, 2);
+ MemorySegment d = frame.allocate(8, 8);
+
+ assertEquals(a.byteSize(), 1);
+ assertEquals(b.byteSize(), 16);
+ assertEquals(c.byteSize(), 2);
+ assertEquals(d.byteSize(), 8);
+
+ assertSeparate(a, b);
+ assertSeparate(a, c);
+ assertSeparate(a, d);
+
+ assertSeparate(b, c);
+ assertSeparate(b, d);
+
+ assertSeparate(c, d);
+ }
+ }
+
+ @Test
+ public void testFrameNested() throws Exception {
+ System.out.println("testFrame Nested");
+
+ try (Frame framea = Memory.createFrame()) {
+ MemorySegment a = framea.allocate(1, 1);
+ MemorySegment b = framea.allocate(16, 16);
+
+ try (Frame frameb = Memory.createFrame()) {
+ MemorySegment c = frameb.allocate(2, 2);
+ MemorySegment d = frameb.allocate(8, 8);
+
+ assertEquals(a.byteSize(), 1);
+ assertEquals(b.byteSize(), 16);
+ assertEquals(c.byteSize(), 2);
+ assertEquals(d.byteSize(), 8);
+
+ assertSeparate(a, b);
+ assertSeparate(a, c);
+ assertSeparate(a, d);
+
+ assertSeparate(b, c);
+ assertSeparate(b, d);
+
+ assertSeparate(c, d);
+ }
+
+ MemorySegment c = framea.allocate(2, 2);
+ MemorySegment d = framea.allocate(8, 8);
+
+ assertEquals(c.byteSize(), 2);
+ assertEquals(d.byteSize(), 8);
+
+ assertSeparate(a, b);
+ assertSeparate(a, c);
+ assertSeparate(a, d);
+
+ assertSeparate(b, c);
+ assertSeparate(b, d);
+
+ assertSeparate(c, d);
+ }
+ }
+
+}