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.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. /*
  2. Copyright (c) 2008 Health Market Science, Inc.
  3. This library is free software; you can redistribute it and/or
  4. modify it under the terms of the GNU Lesser General Public
  5. License as published by the Free Software Foundation; either
  6. version 2.1 of the License, or (at your option) any later version.
  7. This library is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  10. Lesser General Public License for more details.
  11. You should have received a copy of the GNU Lesser General Public
  12. License along with this library; if not, write to the Free Software
  13. Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
  14. USA
  15. You can contact Health Market Science at info@healthmarketscience.com
  16. or at the following address:
  17. Health Market Science
  18. 2700 Horizon Drive
  19. Suite 200
  20. King of Prussia, PA 19406
  21. */
  22. package com.healthmarketscience.jackcess;
  23. import java.lang.ref.Reference;
  24. import java.lang.ref.SoftReference;
  25. import java.nio.ByteBuffer;
  26. import java.nio.ByteOrder;
  27. /**
  28. * Manages a reference to a ByteBuffer.
  29. *
  30. * @author James Ahlborn
  31. */
  32. public abstract class TempBufferHolder {
  33. private static final Reference<ByteBuffer> EMPTY_BUFFER_REF =
  34. new SoftReference<ByteBuffer>(null);
  35. /**
  36. * The caching type for the buffer holder.
  37. */
  38. public enum Type {
  39. /** a hard reference is maintained to the created buffer */
  40. HARD,
  41. /** a soft reference is maintained to the created buffer (may be garbage
  42. collected if memory gets tight) */
  43. SOFT,
  44. /** no reference is maintained to a created buffer (new buffer every
  45. time) */
  46. NONE;
  47. }
  48. /** whether or not every get automatically rewinds the buffer */
  49. private final boolean _autoRewind;
  50. /** ByteOrder for all allocated buffers */
  51. private final ByteOrder _order;
  52. /** the mod count of the current buffer (changes on every realloc) */
  53. private int _modCount;
  54. protected TempBufferHolder(boolean autoRewind, ByteOrder order) {
  55. _autoRewind = autoRewind;
  56. _order = order;
  57. }
  58. /**
  59. * @return the modification count of the current buffer (this count is
  60. * changed every time the buffer is reallocated)
  61. */
  62. public int getModCount() {
  63. return _modCount;
  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. */
  71. public static TempBufferHolder newHolder(Type type, boolean autoRewind) {
  72. return newHolder(type, autoRewind, PageChannel.DEFAULT_BYTE_ORDER);
  73. }
  74. /**
  75. * Creates a new TempBufferHolder.
  76. * @param type the type of reference desired for any created buffer
  77. * @param autoRewind whether or not every get automatically rewinds the
  78. * buffer
  79. * @param order byte order for all allocated buffers
  80. */
  81. public static TempBufferHolder newHolder(Type type, boolean autoRewind,
  82. ByteOrder order)
  83. {
  84. switch(type) {
  85. case HARD:
  86. return new HardTempBufferHolder(autoRewind, order);
  87. case SOFT:
  88. return new SoftTempBufferHolder(autoRewind, order);
  89. case NONE:
  90. return new NoneTempBufferHolder(autoRewind, order);
  91. default:
  92. throw new IllegalStateException("Unknown type " + type);
  93. }
  94. }
  95. /**
  96. * Returns a ByteBuffer of at least the defined page size, with the limit
  97. * set to the page size, and the predefined byteOrder. Will be rewound iff
  98. * autoRewind is enabled for this buffer.
  99. */
  100. public final ByteBuffer getPageBuffer(PageChannel pageChannel) {
  101. return getBuffer(pageChannel, pageChannel.getFormat().PAGE_SIZE);
  102. }
  103. /**
  104. * Returns a ByteBuffer of at least the given size, with the limit set to
  105. * the given size, and the predefined byteOrder. Will be rewound iff
  106. * autoRewind is enabled for this buffer.
  107. */
  108. public final ByteBuffer getBuffer(PageChannel pageChannel, int size) {
  109. ByteBuffer buffer = getExistingBuffer();
  110. if((buffer == null) || (buffer.capacity() < size)) {
  111. buffer = pageChannel.createBuffer(size, _order);
  112. ++_modCount;
  113. setNewBuffer(buffer);
  114. } else {
  115. buffer.limit(size);
  116. }
  117. if(_autoRewind) {
  118. buffer.rewind();
  119. }
  120. return buffer;
  121. }
  122. /**
  123. * @return the currently referenced buffer, {@code null} if none
  124. */
  125. public abstract ByteBuffer getExistingBuffer();
  126. /**
  127. * Releases any referenced memory.
  128. */
  129. public abstract void clear();
  130. /**
  131. * Sets a new buffer for this holder.
  132. */
  133. protected abstract void setNewBuffer(ByteBuffer newBuffer);
  134. /**
  135. * TempBufferHolder which has a hard reference to the buffer.
  136. */
  137. private static final class HardTempBufferHolder extends TempBufferHolder
  138. {
  139. private ByteBuffer _buffer;
  140. private HardTempBufferHolder(boolean autoRewind, ByteOrder order) {
  141. super(autoRewind, order);
  142. }
  143. @Override
  144. public ByteBuffer getExistingBuffer() {
  145. return _buffer;
  146. }
  147. @Override
  148. protected void setNewBuffer(ByteBuffer newBuffer) {
  149. _buffer = newBuffer;
  150. }
  151. @Override
  152. public void clear() {
  153. _buffer = null;
  154. }
  155. }
  156. /**
  157. * TempBufferHolder which has a soft reference to the buffer.
  158. */
  159. private static final class SoftTempBufferHolder extends TempBufferHolder
  160. {
  161. private Reference<ByteBuffer> _buffer = EMPTY_BUFFER_REF;
  162. private SoftTempBufferHolder(boolean autoRewind, ByteOrder order) {
  163. super(autoRewind, order);
  164. }
  165. @Override
  166. public ByteBuffer getExistingBuffer() {
  167. return _buffer.get();
  168. }
  169. @Override
  170. protected void setNewBuffer(ByteBuffer newBuffer) {
  171. _buffer.clear();
  172. _buffer = new SoftReference<ByteBuffer>(newBuffer);
  173. }
  174. @Override
  175. public void clear() {
  176. _buffer.clear();
  177. }
  178. }
  179. /**
  180. * TempBufferHolder which has a no reference to the buffer.
  181. */
  182. private static final class NoneTempBufferHolder extends TempBufferHolder
  183. {
  184. private NoneTempBufferHolder(boolean autoRewind, ByteOrder order) {
  185. super(autoRewind, order);
  186. }
  187. @Override
  188. public ByteBuffer getExistingBuffer() {
  189. return null;
  190. }
  191. @Override
  192. protected void setNewBuffer(ByteBuffer newBuffer) {
  193. // nothing to do
  194. }
  195. @Override
  196. public void clear() {
  197. // nothing to do
  198. }
  199. }
  200. }