|
27 | 27 | * manage continuous requests for larger or smaller memory. |
28 | 28 | * This capability is only available for writable, non-file-memory-mapping resources. |
29 | 29 | * |
| 30 | + * <p>The operation of this implementation is controlled by three conditions:</p> |
| 31 | + * <ul> |
| 32 | + * <li><b><i>origOffHeap:</i></b> If <i>true</i>, the originally allocated WritableMemory is off-heap.</li> |
| 33 | + * |
| 34 | + * <li><b><i>oneArena:</i></b> If <i>true</i>, all subsequent off-heap allocations will use the same Arena |
| 35 | + * obtained from the original off-heap WritableMemory. Otherwise, subsequent off-heap allocations will |
| 36 | + * use a new confined Arena created by this implementation.</li> |
| 37 | + * |
| 38 | + * <li><b><i>offHeap:</i></b> If <i>true</i>, all subsequent allocations will be off-heap. |
| 39 | + * If the originally allocated WritableMemory is on-heap, this variable is ignored.</li> |
| 40 | + * </ul> |
| 41 | + * |
| 42 | + * <p>These three variables work together as follows:</p> |
| 43 | + * |
| 44 | + * <ul> |
| 45 | + * <li>If the original WritableMemory is on-heap, all subsequent allocations will also be on-heap.</li> |
| 46 | + * |
| 47 | + * <li>If <i>origOffHeap</i> = <i>true</i>, <i>oneArena</i> = <i>true</i>, and <i>offHeap</i> = <i>true</i>, |
| 48 | + * all subsequent allocations will also be off-heap and associated with the original Arena. |
| 49 | + * It is the responsibility of the user to close the original Arena using a Try-With-Resource block, or directly.</li> |
| 50 | + * |
| 51 | + * <li>If the original WritableMemory is off-heap, <i>oneArena</i> is true, and <i>offHeap</i> is false, |
| 52 | + * all subsequent allocations will be on-heap. |
| 53 | + * It is the responsibility of the user to close the original Arena using a Try-With-Resource block, or directly.</li> |
| 54 | + * |
| 55 | + * <li>If the original WritableMemory is off-heap, <i>oneArena</i> is false, and <i>offHeap</i> is true, |
| 56 | + * all subsequent allocations will also be off-heap and associated with a new confined Arena assigned by this implementation. |
| 57 | + * It is the responsibility of the user to close the original Arena using a Try-With-Resource block, or directly, |
| 58 | + * and close the last returned new WritableMemory directly.</li> |
| 59 | + * </ul> |
| 60 | + * |
| 61 | + * <p>In summary:</p> |
| 62 | + * |
| 63 | + * <table> <caption><b>Configuration Options</b></caption> |
| 64 | + * <tr><th>Original Off-Heap</th> <th>OneArena</th> <th>OffHeap</th> <th>Subsequent Allocations</th></tr> |
| 65 | + * <tr><td>false</td> <td>N/A</td> <td>N/A</td> <td>All on-heap</td></tr> |
| 66 | + * <tr><td>true</td> <td>N/A</td> <td>false</td> <td>All on-heap</td></tr> |
| 67 | + * <tr><td>true</td> <td>true</td> <td>true</td> <td>All off-heap in original Arena</td></tr> |
| 68 | + * <tr><td>true</td> <td>false</td> <td>true</td> <td>All off-heap in separate Arenas</td></tr> |
| 69 | + * </table> |
| 70 | + * |
30 | 71 | * @author Lee Rhodes |
31 | 72 | */ |
| 73 | +@SuppressWarnings("resource") //can't use TWRs here |
32 | 74 | public final class DefaultMemoryRequestServer implements MemoryRequestServer { |
| 75 | + private final long alignmentBytes; |
| 76 | + private final ByteOrder byteOrder; |
| 77 | + private final boolean oneArena; |
| 78 | + private final boolean offHeap; |
33 | 79 |
|
34 | 80 | /** |
35 | 81 | * Default constructor. |
36 | 82 | */ |
37 | | - public DefaultMemoryRequestServer() { } |
| 83 | + public DefaultMemoryRequestServer() { |
| 84 | + alignmentBytes = 8; |
| 85 | + byteOrder = ByteOrder.nativeOrder(); |
| 86 | + oneArena = false; |
| 87 | + offHeap = false; |
| 88 | + } |
38 | 89 |
|
39 | | - @Override |
40 | | - public WritableMemory request( |
41 | | - final long newCapacityBytes, |
| 90 | + /** |
| 91 | + * Optional constructor 1. |
| 92 | + * @param oneArena if true, the original arena will be used for all requested allocations. |
| 93 | + * @param offHeap if true, new allocations will be off-heap. |
| 94 | + */ |
| 95 | + public DefaultMemoryRequestServer( |
| 96 | + final boolean oneArena, |
| 97 | + final boolean offHeap) { |
| 98 | + this.alignmentBytes = 8; |
| 99 | + this.byteOrder = ByteOrder.nativeOrder(); |
| 100 | + this.oneArena = oneArena; |
| 101 | + this.offHeap = offHeap; |
| 102 | + } |
| 103 | + |
| 104 | + /** |
| 105 | + * Optional constructor 2. |
| 106 | + * @param alignmentBytes requested segment alignment for all allocations. Typically 1, 2, 4 or 8. |
| 107 | + * @param byteOrder the given <i>ByteOrder</i>. It must be non-null. |
| 108 | + * @param oneArena if true, the same arena will be used for all requested allocations. |
| 109 | + * @param offHeap if true, new allocations will be off-heap. |
| 110 | + */ |
| 111 | + public DefaultMemoryRequestServer( |
42 | 112 | final long alignmentBytes, |
43 | 113 | final ByteOrder byteOrder, |
44 | | - final Arena arena) { |
45 | | - final WritableMemory newWmem; |
| 114 | + final boolean oneArena, |
| 115 | + final boolean offHeap) { |
| 116 | + this.alignmentBytes = alignmentBytes; |
| 117 | + this.byteOrder = byteOrder; |
| 118 | + this.oneArena = oneArena; |
| 119 | + this.offHeap = offHeap; |
| 120 | + } |
46 | 121 |
|
47 | | - if (arena != null) { |
48 | | - newWmem = WritableMemory.allocateDirect(newCapacityBytes, alignmentBytes, byteOrder, this, arena); |
49 | | - } |
50 | | - else { //On-heap |
| 122 | + @Override |
| 123 | + public WritableMemory request( |
| 124 | + final WritableMemory oldWmem, |
| 125 | + final long newCapacityBytes) { |
| 126 | + |
| 127 | + //On-heap |
| 128 | + if (oldWmem.getArena() == null || !offHeap) { |
51 | 129 | if (newCapacityBytes > Integer.MAX_VALUE) { |
52 | 130 | throw new IllegalArgumentException("Requested capacity exceeds Integer.MAX_VALUE."); |
53 | 131 | } |
54 | | - newWmem = WritableMemory.allocate((int)newCapacityBytes, byteOrder, this); |
| 132 | + return WritableMemory.allocate((int)newCapacityBytes, byteOrder, this); |
55 | 133 | } |
56 | 134 |
|
57 | | - return newWmem; |
| 135 | + //Acquire Arena |
| 136 | + final Arena arena = (oneArena) ? oldWmem.getArena() : Arena.ofConfined(); |
| 137 | + return WritableMemory.allocateDirect(newCapacityBytes, alignmentBytes, byteOrder, this, arena); |
58 | 138 | } |
59 | 139 |
|
60 | 140 | @Override |
61 | | - public void requestClose(final Arena arena) { |
62 | | - if (arena.scope().isAlive()) { arena.close(); } |
| 141 | + public void requestClose(final WritableMemory wmemToClose) { |
| 142 | + final Arena arena = wmemToClose.getArena(); |
| 143 | + if (oneArena || arena == null || !arena.scope().isAlive()) { return; } //can't close |
| 144 | + arena.close(); |
63 | 145 | } |
64 | 146 |
|
65 | 147 | } |
0 commit comments