Class ByteBufferSupply

java.lang.Object
org.jlab.coda.emu.support.data.ByteBufferSupply

public class ByteBufferSupply extends Object
This class is used to provide a very fast supply of ByteBuffer objects (actually ByteBufferItem objects each of which wraps a ByteBuffer) for reuse in 3 different modes (uses Disruptor software package).

1) It can be used as a simple supply of ByteBuffer(Item)s. In this mode, only get() and release() are called. A user does a get(), uses that buffer, then calls release() when done with it. If there are multiple users of a single buffer (say 5), then call bufferItem.setUsers(5) before it is used and the buffer is only released when all 5 users have called release().

2) As in the first usage, it can be used as a supply of ByteBuffers, but each buffer can be preset to a specific ByteBuffer object. Thus it can act as a supply of buffers in which each contains specific data. Because of the circular nature of the ring used to implement this code, after all ByteBuffers have been gotten by the user for the first time, it starts back over with the first -- going round and round.

To implement this, use the constructor which takes a list of ByteBuffer objects with which to fill this supply. The user does a getAsIs() which does not clear the buffer's position and limit. When finished reading/writing, user calls release(). It's up to the user to maintain proper values for the buffer's position and limit since it will be used again. If there are multiple users of a single buffer (say 5), then call bufferItem.setUsers(5) before it is used and the buffer is only released when all 5 users have called release().

3) It can be used as a supply of ByteBuffers in which a single producer provides data for a single consumer which is waiting for that data. The producer does a get(), fills the buffer with data, and finally does a publish() to let the consumer know the data is ready. Simultaneously, a consumer does a consumerGet() to access the data once it is ready. To access the ByteBuffer contained int the ByteBufferItem, call ByteBufferItem.getBufferAsIs(), do NOT call ByteBufferItem.getBuffer() as that clears the returned buffer. The consumer then calls release(ByteBufferItem) when finished which allows the producer to reuse the now unused buffer.

  • Field Summary

    Fields
    Modifier and Type
    Field
    Description
    Object to be associated with each ByteBufferItem.
  • Constructor Summary

    Constructors
    Constructor
    Description
    ByteBufferSupply(int ringSize, int bufferSize)
    Constructor.
    ByteBufferSupply(int ringSize, int bufferSize, ByteOrder order, boolean direct)
    Constructor.
    ByteBufferSupply(int ringSize, int bufferSize, ByteOrder order, boolean direct, boolean orderedRelease)
    Constructor.
    ByteBufferSupply(int ringSize, int bufferSize, ByteOrder order, boolean direct, boolean orderedRelease, org.jlab.coda.jevio.EvioNodePool[] pools)
    Constructor.
    ByteBufferSupply(int ringSize, List<ByteBuffer> bufList, boolean orderedRelease)
    Constructor.
  • Method Summary

    Modifier and Type
    Method
    Description
    Get the next available item in ring buffer for getting data already written into.
    get()
    Get the next available item in ring buffer for writing/reading data.
    void
    get(int n, ByteBufferItem[] items)
    Get the next "n" available item in ring buffer for writing/reading data.
    Get the next available item in ring buffer for writing/reading data.
    int
    What percentage of the byte buffers are being used? If this ring is full (of unused buffers), it corresponds to an empty input or output channel (0%).
    void
    publish(int n, ByteBufferItem[] items)
    Used to tell that the consumer that the ring buffer items are ready for consumption.
    void
    publish(ByteBufferItem byteBufferItem)
    Used to tell that the consumer that the ring buffer item is ready for consumption.
    void
    Consumer releases claim on the given ring buffer item so it becomes available for reuse.

    Methods inherited from class java.lang.Object

    equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
  • Field Details

    • auxObject

      public Object auxObject
      Object to be associated with each ByteBufferItem.
  • Constructor Details

    • ByteBufferSupply

      public ByteBufferSupply(int ringSize, int bufferSize) throws IllegalArgumentException
      Constructor. Buffers are big endian and not direct.
      Parameters:
      ringSize - number of ByteBufferItem objects in ring buffer.
      bufferSize - initial size (bytes) of ByteBuffer in each ByteBufferItem object.
      Throws:
      IllegalArgumentException - if args < 1 or ringSize not power of 2.
    • ByteBufferSupply

      public ByteBufferSupply(int ringSize, int bufferSize, ByteOrder order, boolean direct) throws IllegalArgumentException
      Constructor.
      Parameters:
      ringSize - number of ByteBufferItem objects in ring buffer.
      bufferSize - initial size (bytes) of ByteBuffer in each ByteBufferItem object.
      order - byte order of ByteBuffer in each ByteBufferItem object.
      direct - if true, make ByteBuffers direct.
      Throws:
      IllegalArgumentException - if args < 1 or ringSize not power of 2.
    • ByteBufferSupply

      public ByteBufferSupply(int ringSize, int bufferSize, ByteOrder order, boolean direct, boolean orderedRelease) throws IllegalArgumentException
      Constructor. Used when wanting to avoid locks for speed purposes. Say a ByteBufferItem is used by several users. This is true in ET or emu input channels in which many evio events all contain a reference to the same buffer. If the user can guarantee that all the users of one buffer release it before any of the users of the next, then synchronization is not necessary. If that isn't the case, then locks take care of preventing a later acquired buffer from being released first and consequently everything that came before it in the ring.
      Parameters:
      ringSize - number of ByteBufferItem objects in ring buffer.
      bufferSize - initial size (bytes) of ByteBuffer in each ByteBufferItem object.
      order - byte order of ByteBuffer in each ByteBufferItem object.
      direct - if true, make ByteBuffers direct.
      orderedRelease - if true, the user promises to release the ByteBufferItems in the same order as acquired. This avoids using synchronized code (no locks).
      Throws:
      IllegalArgumentException - if args < 1 or ringSize not power of 2.
    • ByteBufferSupply

      public ByteBufferSupply(int ringSize, int bufferSize, ByteOrder order, boolean direct, boolean orderedRelease, org.jlab.coda.jevio.EvioNodePool[] pools) throws IllegalArgumentException
      Constructor. Used when wanting to avoid locks for speed purposes. Say a ByteBufferItem is used by several users. This is true in ET or emu input channels in which many evio events all contain a reference to the same buffer. If the user can guarantee that all the users of one buffer release it before any of the users of the next, then synchronization is not necessary. If that isn't the case, then locks take care of preventing a later acquired buffer from being released first and consequently everything that came before it in the ring.

      In addition, each ByteBufferItem in this supply will have an object associated with it which is passed in through the last argument. Used to store an EvioNodePool with each buffer in the supply.

      Parameters:
      ringSize - number of ByteBufferItem objects in ring buffer.
      bufferSize - initial size (bytes) of ByteBuffer in each ByteBufferItem object.
      order - byte order of ByteBuffer in each ByteBufferItem object.
      direct - if true, make ByteBuffers direct.
      orderedRelease - if true, the user promises to release the ByteBufferItems in the same order as acquired. This avoids using synchronized code (no locks).
      pools - one EvioNodePool for each ByteBuffer.
      Throws:
      IllegalArgumentException - if args < 1 or ringSize not power of 2, pools array must have not be null or have less than ringSize number of elements.
    • ByteBufferSupply

      public ByteBufferSupply(int ringSize, List<ByteBuffer> bufList, boolean orderedRelease) throws IllegalArgumentException
      Constructor. Used when wanting a source of ByteBuffers which already contain data. Useful when testing.
      Parameters:
      ringSize - number of ByteBufferItem objects in ring buffer.
      bufList - list of ByteBuffers used to populate this supply. List must contain ringSize number of buffers.
      orderedRelease - if true, the user promises to release the ByteBufferItems in the same order as acquired. This avoids using synchronized code (no locks).
      Throws:
      IllegalArgumentException - bad arg or ringSize not power of 2.
  • Method Details

    • getFillLevel

      public int getFillLevel()
      What percentage of the byte buffers are being used? If this ring is full (of unused buffers), it corresponds to an empty input or output channel (0%). In this case, (ringSize - (ringSize - (produced - consumed))) = (produced - consumed) = 0. If it's empty then the channel is full (100%). In this case, (produced - consumed) = ringSize.
      Returns:
      fill level, 0% to 100%.
    • get

      public ByteBufferItem get() throws InterruptedException
      Get the next available item in ring buffer for writing/reading data. Not sure if this method is thread-safe.
      Returns:
      next available item in ring buffer.
      Throws:
      InterruptedException - if thread interrupted.
    • get

      public void get(int n, ByteBufferItem[] items) throws InterruptedException
      Get the next "n" available item in ring buffer for writing/reading data. This may only be used in conjunction with: publish(ByteBufferItem) or preferably publish(int, ByteBufferItem[]). Not sure if this method is thread-safe.
      Parameters:
      n - number of ring buffer items to get.
      items - array big enough to hold an array of n items.
      Throws:
      InterruptedException - if thread interrupted.
    • getAsIs

      public ByteBufferItem getAsIs() throws InterruptedException
      Get the next available item in ring buffer for writing/reading data. Does not set the ByteBuffer to position = 0 and limit = capacity. In other words, it facilitates reading existing data from the buffer. When finished with this item, it's up to the user to set position and limit to the correct value for the next user. Not sure if this method is thread-safe.
      Returns:
      next available item in ring buffer.
      Throws:
      InterruptedException - if thread interrupted.
    • consumerGet

      public ByteBufferItem consumerGet() throws InterruptedException
      Get the next available item in ring buffer for getting data already written into. Not sure if this method is thread-safe.
      Returns:
      next available item in ring buffer for getting data already written into.
      Throws:
      InterruptedException - if thread interrupted.
    • release

      public void release(ByteBufferItem item)
      Consumer releases claim on the given ring buffer item so it becomes available for reuse. This method ensures that sequences are released in order and is thread-safe. To be used in conjunction with get() and consumerGet().
      Parameters:
      item - item in ring buffer to release for reuse.
    • publish

      public void publish(ByteBufferItem byteBufferItem)
      Used to tell that the consumer that the ring buffer item is ready for consumption. Note, it also publishes all previously gotten items! Not sure if this method is thread-safe. To be used in conjunction with get() and consumerGet().
      Parameters:
      byteBufferItem - item available for consumer's use.
    • publish

      public void publish(int n, ByteBufferItem[] items)
      Used to tell that the consumer that the ring buffer items are ready for consumption. This may only be used in conjunction with get(int, ByteBufferItem[]). Not sure if this method is thread-safe.
      Parameters:
      n - number of array items available for consumer's use.
      items - array of items available for consumer's use.