You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

TempBufferHolder.java 6.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. /*
  2. Copyright (c) 2008 Health Market Science, Inc.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package com.healthmarketscience.jackcess.impl;
  14. import java.lang.ref.Reference;
  15. import java.lang.ref.SoftReference;
  16. import java.nio.ByteBuffer;
  17. import java.nio.ByteOrder;
  18. /**
  19. * Manages a reference to a ByteBuffer.
  20. *
  21. * @author James Ahlborn
  22. */
  23. public abstract class TempBufferHolder {
  24. private static final Reference<ByteBuffer> EMPTY_BUFFER_REF =
  25. new SoftReference<ByteBuffer>(null);
  26. /**
  27. * The caching type for the buffer holder.
  28. */
  29. public enum Type {
  30. /** a hard reference is maintained to the created buffer */
  31. HARD,
  32. /** a soft reference is maintained to the created buffer (may be garbage
  33. collected if memory gets tight) */
  34. SOFT,
  35. /** no reference is maintained to a created buffer (new buffer every
  36. time) */
  37. NONE;
  38. }
  39. /** whether or not every get automatically rewinds the buffer */
  40. private final boolean _autoRewind;
  41. /** ByteOrder for all allocated buffers */
  42. private final ByteOrder _order;
  43. /** the mod count of the current buffer (changes on every realloc) */
  44. private int _modCount;
  45. protected TempBufferHolder(boolean autoRewind, ByteOrder order) {
  46. _autoRewind = autoRewind;
  47. _order = order;
  48. }
  49. /**
  50. * @return the modification count of the current buffer (this count is
  51. * changed every time the buffer is reallocated)
  52. */
  53. public int getModCount() {
  54. return _modCount;
  55. }
  56. /**
  57. * Creates a new TempBufferHolder.
  58. * @param type the type of reference desired for any created buffer
  59. * @param autoRewind whether or not every get automatically rewinds the
  60. * buffer
  61. */
  62. public static TempBufferHolder newHolder(Type type, boolean autoRewind) {
  63. return newHolder(type, autoRewind, PageChannel.DEFAULT_BYTE_ORDER);
  64. }
  65. /**
  66. * Creates a new TempBufferHolder.
  67. * @param type the type of reference desired for any created buffer
  68. * @param autoRewind whether or not every get automatically rewinds the
  69. * buffer
  70. * @param order byte order for all allocated buffers
  71. */
  72. public static TempBufferHolder newHolder(Type type, boolean autoRewind,
  73. ByteOrder order)
  74. {
  75. switch(type) {
  76. case HARD:
  77. return new HardTempBufferHolder(autoRewind, order);
  78. case SOFT:
  79. return new SoftTempBufferHolder(autoRewind, order);
  80. case NONE:
  81. return new NoneTempBufferHolder(autoRewind, order);
  82. default:
  83. throw new IllegalStateException("Unknown type " + type);
  84. }
  85. }
  86. /**
  87. * Returns a ByteBuffer of at least the defined page size, with the limit
  88. * set to the page size, and the predefined byteOrder. Will be rewound iff
  89. * autoRewind is enabled for this buffer.
  90. */
  91. public final ByteBuffer getPageBuffer(PageChannel pageChannel) {
  92. return getBuffer(pageChannel, pageChannel.getFormat().PAGE_SIZE);
  93. }
  94. /**
  95. * Returns a ByteBuffer of at least the given size, with the limit set to
  96. * the given size, and the predefined byteOrder. Will be rewound iff
  97. * autoRewind is enabled for this buffer.
  98. */
  99. public final ByteBuffer getBuffer(PageChannel pageChannel, int size) {
  100. ByteBuffer buffer = getExistingBuffer();
  101. if((buffer == null) || (buffer.capacity() < size)) {
  102. buffer = PageChannel.createBuffer(size, _order);
  103. ++_modCount;
  104. setNewBuffer(buffer);
  105. } else {
  106. buffer.limit(size);
  107. }
  108. if(_autoRewind) {
  109. buffer.rewind();
  110. }
  111. return buffer;
  112. }
  113. /**
  114. * @return the currently referenced buffer, {@code null} if none
  115. */
  116. public abstract ByteBuffer getExistingBuffer();
  117. /**
  118. * Releases any referenced memory.
  119. */
  120. public abstract void clear();
  121. /**
  122. * Sets a new buffer for this holder.
  123. */
  124. protected abstract void setNewBuffer(ByteBuffer newBuffer);
  125. /**
  126. * TempBufferHolder which has a hard reference to the buffer.
  127. */
  128. private static final class HardTempBufferHolder extends TempBufferHolder
  129. {
  130. private ByteBuffer _buffer;
  131. private HardTempBufferHolder(boolean autoRewind, ByteOrder order) {
  132. super(autoRewind, order);
  133. }
  134. @Override
  135. public ByteBuffer getExistingBuffer() {
  136. return _buffer;
  137. }
  138. @Override
  139. protected void setNewBuffer(ByteBuffer newBuffer) {
  140. _buffer = newBuffer;
  141. }
  142. @Override
  143. public void clear() {
  144. _buffer = null;
  145. }
  146. }
  147. /**
  148. * TempBufferHolder which has a soft reference to the buffer.
  149. */
  150. private static final class SoftTempBufferHolder extends TempBufferHolder
  151. {
  152. private Reference<ByteBuffer> _buffer = EMPTY_BUFFER_REF;
  153. private SoftTempBufferHolder(boolean autoRewind, ByteOrder order) {
  154. super(autoRewind, order);
  155. }
  156. @Override
  157. public ByteBuffer getExistingBuffer() {
  158. return _buffer.get();
  159. }
  160. @Override
  161. protected void setNewBuffer(ByteBuffer newBuffer) {
  162. _buffer.clear();
  163. _buffer = new SoftReference<ByteBuffer>(newBuffer);
  164. }
  165. @Override
  166. public void clear() {
  167. _buffer.clear();
  168. }
  169. }
  170. /**
  171. * TempBufferHolder which has a no reference to the buffer.
  172. */
  173. private static final class NoneTempBufferHolder extends TempBufferHolder
  174. {
  175. private NoneTempBufferHolder(boolean autoRewind, ByteOrder order) {
  176. super(autoRewind, order);
  177. }
  178. @Override
  179. public ByteBuffer getExistingBuffer() {
  180. return null;
  181. }
  182. @Override
  183. protected void setNewBuffer(ByteBuffer newBuffer) {
  184. // nothing to do
  185. }
  186. @Override
  187. public void clear() {
  188. // nothing to do
  189. }
  190. }
  191. }