1. /*
  2. * @(#)ByteBufferPoolImpl.java 1.12 04/06/21
  3. *
  4. * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package com.sun.corba.se.impl.transport;
  8. import java.nio.ByteBuffer;
  9. import java.util.ArrayList;
  10. import com.sun.corba.se.spi.orb.ORB;
  11. import com.sun.corba.se.pept.transport.ByteBufferPool;
  12. /**
  13. * @author Charlie Hunt
  14. */
  15. public class ByteBufferPoolImpl implements ByteBufferPool
  16. {
  17. private ORB itsOrb;
  18. private int itsByteBufferSize;
  19. private ArrayList itsPool;
  20. private int itsObjectCounter = 0;
  21. private boolean debug;
  22. // Construct a ByteBufferPool for a pool of NIO ByteBuffers
  23. // of ORB fragment size.
  24. public ByteBufferPoolImpl(ORB theORB)
  25. {
  26. itsByteBufferSize = theORB.getORBData().getGIOPFragmentSize();
  27. itsPool = new ArrayList();
  28. itsOrb = theORB;
  29. debug = theORB.transportDebugFlag;
  30. }
  31. /*
  32. * Locations where ByteBuffers are gotten from the pool:
  33. * 1. ContactInfoBase.createMessageMediator()
  34. * 2. ByteBufferWithInfo.growBuffer()
  35. * 3. ByteBufferWithInfo(ORB, BufferManagerWrite) - constructor
  36. */
  37. // If the requested ByteBuffer size is less than or equal to
  38. // the ORB fragment size, and we have not disabled use of
  39. // direct byte buffers (normally for debugging purposes)
  40. // then get a DirectByteBuffer from the
  41. // pool if there is one, if there is not one in the pool,
  42. // then allocate a a DirectByteBuffer of ORB fragment size.
  43. //
  44. // If the request ByteBuffer size is greater than the ORB fragment
  45. // size, allocate a new non-direct ByteBuffer.
  46. public ByteBuffer getByteBuffer(int theAskSize)
  47. {
  48. ByteBuffer abb = null;
  49. if ((theAskSize <= itsByteBufferSize) &&
  50. !itsOrb.getORBData().disableDirectByteBufferUse())
  51. {
  52. // check if there's one in the pool, if not allocate one.
  53. int poolSize;
  54. synchronized (itsPool)
  55. {
  56. poolSize = itsPool.size();
  57. if (poolSize > 0)
  58. {
  59. abb = (ByteBuffer)itsPool.remove(poolSize - 1);
  60. // clear ByteBuffer before returning it
  61. abb.clear();
  62. }
  63. }
  64. // NOTE: Moved the 'else' part of the above if statement
  65. // outside the synchronized block since it is likely
  66. // less expensive to check poolSize than to allocate a
  67. // DirectByteBuffer in the synchronized block.
  68. if (poolSize <= 0)
  69. {
  70. abb = ByteBuffer.allocateDirect(itsByteBufferSize);
  71. }
  72. // increment the number of ByteBuffers gotten from pool
  73. // IMPORTANT: Since this counter is used only for information
  74. // purposes, it does not use synchronized access.
  75. itsObjectCounter++;
  76. }
  77. else
  78. {
  79. // Requested ByteBuffer size larger than the pool manages.
  80. // Just allocate a non-direct ByteBuffer
  81. abb = ByteBuffer.allocate(theAskSize);
  82. }
  83. return abb;
  84. }
  85. /*
  86. * Locations where ByteBuffers are released to the pool:
  87. * 1. ByteBufferWithInfo.growBuffer()
  88. * 2. BufferManagerWriteCollect.sendMessage()
  89. * 3. CDROutputStream_1_0.close()
  90. * 4. CDRInputStream_1_0.close()
  91. * 5. BufferManagerReadStream.underflow()
  92. * 6. BufferManagerWrite.close()
  93. * 7. BufferManagerRead.close()
  94. * 8. CorbaMessageMediatorImpl.releaseByteBufferToPool()
  95. */
  96. // If the ByteBuffer is a DirectByteBuffer, add it to the pool.
  97. // Otherwise, set its reference to null since it's not kept in
  98. // the pool and caller is saying he/she is done with it.
  99. // NOTE: The size of the ByteBuffer is not checked with the
  100. // this pool's ByteBuffer size since only DirectByteBuffers
  101. // ever allocated. Hence, only DirectByteBuffer are checked
  102. // here. An additional check could be added here for that though.
  103. public void releaseByteBuffer(ByteBuffer thebb)
  104. {
  105. if (thebb.isDirect())
  106. {
  107. synchronized (itsPool)
  108. {
  109. // use with debug to determine if byteBuffer is already
  110. // in the pool.
  111. boolean refInPool = false;
  112. int bbAddr = 0;
  113. if (debug)
  114. {
  115. // Check to make sure we don't have 'thebb' reference
  116. // already in the pool before adding it.
  117. for (int i = 0; i < itsPool.size() && refInPool == false; i++)
  118. {
  119. ByteBuffer tmpbb = (ByteBuffer)itsPool.get(i);
  120. if (thebb == tmpbb)
  121. {
  122. refInPool = true;
  123. bbAddr = System.identityHashCode(thebb);
  124. }
  125. }
  126. }
  127. // NOTE: The else part of this if will only get called
  128. // if debug = true and refInPool = true, see logic above.
  129. if (refInPool == false || debug == false)
  130. {
  131. // add ByteBuffer back to the pool
  132. itsPool.add(thebb);
  133. }
  134. else // otherwise, log a stack trace with duplicate message
  135. {
  136. String threadName = Thread.currentThread().getName();
  137. Throwable t =
  138. new Throwable(threadName +
  139. ": Duplicate ByteBuffer reference (" +
  140. bbAddr + ")");
  141. t.printStackTrace(System.out);
  142. }
  143. }
  144. // decrement the count of ByteBuffers released
  145. // IMPORTANT: Since this counter is used only for information
  146. // purposes, it does not use synchronized access.
  147. itsObjectCounter--;
  148. }
  149. else
  150. {
  151. // ByteBuffer not pooled nor needed
  152. thebb = null;
  153. }
  154. }
  155. // Get a count of the outstanding allocated DirectByteBuffers.
  156. // (Those allocated and have not been returned to the pool).
  157. // IMPORTANT: Since this counter is used only for information
  158. // purposes, it does not use synchronized access.
  159. public int activeCount()
  160. {
  161. return itsObjectCounter;
  162. }
  163. }
  164. // End of file.