< prev index next >

src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/ArenaAllocator.java

Print this page
@@ -27,18 +27,27 @@
  
  import jdk.incubator.foreign.MemorySegment;
  import jdk.incubator.foreign.SegmentAllocator;
  import jdk.incubator.foreign.ResourceScope;
  
- public abstract class ArenaAllocator implements SegmentAllocator {
+ public final class ArenaAllocator implements SegmentAllocator {
  
-     protected MemorySegment segment;
+     public static final long DEFAULT_BLOCK_SIZE = 4 * 1024;
  
-     protected long sp = 0L;
+     MemorySegment segment;
  
-     ArenaAllocator(MemorySegment segment) {
-         this.segment = segment;
+     long sp = 0L;
+     long size = 0;
+     final long blockSize;
+     final long arenaSize;
+     final ResourceScope scope;
+ 
+     public ArenaAllocator(long blockSize, long arenaSize, ResourceScope scope) {
+         this.blockSize = blockSize;
+         this.arenaSize = arenaSize;
+         this.scope = scope;
+         this.segment = newSegment(blockSize, 1);
      }
  
      MemorySegment trySlice(long bytesSize, long bytesAlignment) {
          long min = segment.address().toRawLongValue();
          long start = Utils.alignUp(min + sp, bytesAlignment) - min;

@@ -49,101 +58,50 @@
              sp = start + bytesSize;
              return slice;
          }
      }
  
-     void checkConfinementIfNeeded() {
-         Thread ownerThread = scope().ownerThread();
-         if (ownerThread != null && ownerThread != Thread.currentThread()) {
-             throw new IllegalStateException("Attempt to allocate outside confinement thread");
-         }
+     public ResourceScope scope() {
+         return scope;
      }
  
-     ResourceScope scope() {
-         return segment.scope();
+     private MemorySegment newSegment(long size, long align) {
+         return MemorySegment.allocateNative(size, align, scope);
      }
  
-     public static class UnboundedArenaAllocator extends ArenaAllocator {
- 
-         private static final long DEFAULT_BLOCK_SIZE = 4 * 1024;
- 
-         public UnboundedArenaAllocator(ResourceScope scope) {
-             super(MemorySegment.allocateNative(DEFAULT_BLOCK_SIZE, 1, scope));
-         }
- 
-         private MemorySegment newSegment(long size, long align) {
-             return MemorySegment.allocateNative(size, align, segment.scope());
-         }
- 
-         @Override
-         public MemorySegment allocate(long bytesSize, long bytesAlignment) {
-             checkConfinementIfNeeded();
+     @Override
+     public MemorySegment allocate(long bytesSize, long bytesAlignment) {
+         long prevSp = sp;
+         long allocatedSize = 0L;
+         try {
              // try to slice from current segment first...
              MemorySegment slice = trySlice(bytesSize, bytesAlignment);
              if (slice != null) {
+                 allocatedSize = sp - prevSp;
                  return slice;
              } else {
                  long maxPossibleAllocationSize = bytesSize + bytesAlignment - 1;
-                 if (maxPossibleAllocationSize > DEFAULT_BLOCK_SIZE) {
+                 if (maxPossibleAllocationSize > blockSize) {
                      // too big
+                     allocatedSize = Utils.alignUp(bytesSize, bytesAlignment);
+                     if (size > arenaSize) {
+                         throw new OutOfMemoryError();
+                     }
                      return newSegment(bytesSize, bytesAlignment);
                  } else {
                      // allocate a new segment and slice from there
+                     allocatedSize += segment.byteSize() - sp;
                      sp = 0L;
-                     segment = newSegment(DEFAULT_BLOCK_SIZE, 1L);
-                     return trySlice(bytesSize, bytesAlignment);
+                     segment = newSegment(blockSize, 1L);
+                     slice = trySlice(bytesSize, bytesAlignment);
+                     allocatedSize += sp;
+                     return slice;
                  }
              }
-         }
-     }
- 
-     public static class BoundedArenaAllocator extends ArenaAllocator {
- 
-         public BoundedArenaAllocator(ResourceScope scope, long size) {
-             super(MemorySegment.allocateNative(size, 1, scope));
-         }
- 
-         @Override
-         public MemorySegment allocate(long bytesSize, long bytesAlignment) {
-             checkConfinementIfNeeded();
-             // try to slice from current segment first...
-             MemorySegment slice = trySlice(bytesSize, bytesAlignment);
-             if (slice != null) {
-                 return slice;
-             } else {
-                 throw new OutOfMemoryError("Not enough space left to allocate");
-             }
-         }
-     }
- 
-     public static class BoundedSharedArenaAllocator extends BoundedArenaAllocator {
-         public BoundedSharedArenaAllocator(ResourceScope scope, long size) {
-             super(scope, size);
-         }
- 
-         @Override
-         public synchronized MemorySegment allocate(long bytesSize, long bytesAlignment) {
-             return super.allocate(bytesSize, bytesAlignment);
-         }
-     }
- 
-     public static class UnboundedSharedArenaAllocator implements SegmentAllocator {
- 
-         final ResourceScope scope;
- 
-         final ThreadLocal<ArenaAllocator> allocators = new ThreadLocal<>() {
-             @Override
-             protected ArenaAllocator initialValue() {
-                 return new UnboundedArenaAllocator(scope);
+         } finally {
+             size += allocatedSize;
+             if (size > arenaSize) {
+                 throw new OutOfMemoryError();
              }
-         };
- 
-         public UnboundedSharedArenaAllocator(ResourceScope scope) {
-             this.scope = scope;
-         }
- 
-         @Override
-         public MemorySegment allocate(long bytesSize, long bytesAlignment) {
-             return allocators.get().allocate(bytesSize, bytesAlignment);
          }
      }
  }
< prev index next >