Logo
Distributed Genetic Programming Framework
print print

File org.sfc.collections.CircularBuffer.java

Here you can find all the information about the file org.sfc.collections.CircularBuffer.java. You may explore it here or download it onto your local disk.
/*
 * Copyright (c) 2006 Thomas Weise
 *
 * E-Mail           : tweise@gmx.de
 * Creation Date    : 2006-02-27 04:56:59
 * Original Filename: org.sfc.collections.CircularBuffer.java
 * Version          : 3.1.0
 * Last modification: 2006-05-12
 *                by: Thomas Weise
 *
 * License          : GNU LESSER GENERAL PUBLIC LICENSE
 *                    Version 2.1, February 1999
 *                    You should have received a copy of this license along
 *                    with this library; if not, write to the Free Software
 *                    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *                    MA 02111-1307, USA or download the license under
 *                    http://www.gnu.org/copyleft/lesser.html.
 *
 * Warranty         : This software is provided "as is" without any
 *                    warranty; without even the implied warranty of
 *                    merchantability or fitness for a particular purpose.
 *                    See the Gnu Lesser General Public License for more
 *                    details.
 */


package org.sfc.collections;


/**
 * This class represents a circular buffer that might be used for temporary
 * data storage.
 * @param <Type>  The data-type of the items stored.
 * @author Thomas Weise
 */

public class CircularBuffer<Type>
  {
/**
 * The buffer.
 */

  private       Type[]      m_buffer  ;
/**
 * The current buffer size, this might be less than
 * <code>m_buffer.length</code>.
 */

  private       int         m_buffer_size ;
/**
 * The internal synchronizer.
 */

  private final Object      m_sync  ;
/**
 * The insertion pointer.
 */

  private       int         m_ins     ;
/**
 * The count of sockets stored.
 */

  private       int         m_count   ;
/**
 * <code>true</code> as long as the buffer is in use.
 */

  private       boolean     m_running ;
/**
 * The component type class.
 */

  private final Class<Type> m_class ;

/**
 * Create a new circular buffer for at most a specified count of items of
 * the specified class.
 * @param p_class   The class of the items to be stored.
 * @param p_size    The size of the buffer to allocate.
 */

  public  CircularBuffer  (final Class<Type>  p_class,
                                 int       p_size)
    {
    super();
    if(p_size < 1) p_size = 1;

    this.m_buffer_size = p_size;
    this.m_class       = p_class;
    this.m_buffer      = Arrays.create(p_class, p_size);
    this.m_sync        = new Object();
    this.m_running     = true;
    }


/**
 * This method will be called whenever the buffer overflows and an item
 * should be determined to be dropped. If none can be found, the new item
 * will be dropped. This method returns <code>true</code> if the specified
 * old item can be dropped and the new one can be buffered instead.
 * @param p_old_item    The old item to be maybe dropped.
 * @param p_new_item    The new item, which could possible replace the old
 *                      one.
 * @return  <code>true</code> if and only if the new item may replace the
 *          old one, <code>false</code> if the old item should be kept.
 */

  protected boolean can_drop  (final Type p_old_item,
                               final Type p_new_item)
    {
    return false;
    }

/**
 * This method will be called whenever an item gets dropped.
 * @param p_item  The item to be dropped from the buffer.
 */

  protected void  drop  (final Type p_item)
    {
   // does nothing, override to provide behavior
    }

/**
 * Enqueue a new item into the buffer.
 * @param p_new The new item to be enqueued.
 */

  public  final void  enqueue (final Type p_new)
    {
          Type[]  l_s;
          int     l_ins, l_cnt, l_i, l_j;
    final int     l_bs;
          Type    l_t;

all:
      {
      synchronized(this.m_sync)
        {
        if(this.m_running)
          {
          l_bs  = this.m_buffer_size;
          l_s   = this.m_buffer;
          l_ins = this.m_ins;
          l_cnt = this.m_count;

dropper:
            {
            if(l_cnt >= l_bs)
              {
              l_j = l_ins;
              for(l_i = l_bs; l_i > 0; l_i--)
                {
                l_t = l_s[l_j];
                if(l_t.equals(p_new) || this.can_drop(l_t, p_new))
                  {
                  this.drop(l_t);
                  l_s[l_j] = l_s[l_ins];
                  break dropper;
                  }
                if((++l_j) >= l_bs) l_j = 0;
                }
              break all;
//            drop(p_new);
//            return;
              }
  
            l_cnt++;
            }

          l_s[l_ins] = p_new;
          if((++l_ins) >= l_bs) this.m_ins = 0;
          else                  this.m_ins = l_ins;
  
          this.m_count = l_cnt;
          this.m_sync.notifyAll();
          return;
          }      
        }
      }
    
    this.drop(p_new);
    }

/**
 * Dequeue an element from the buffer. Warning: If the buffer size is 0,
 * this call will block forever.
 * @return  Either an element which was enqueued before, or
 *          <code>null</code> if the circular buffer has been aborted.
 */

  public  final Type  dequeue ()
    {
    int   l_ins, l_cnt;
    Type  l_t;

    for(;;)
      {
      synchronized(this.m_sync)
        {
        if(this.m_running)
          {
          l_cnt = this.m_count;
          if(l_cnt > 0)
            {
            l_ins                 = (this.m_ins - l_cnt);
            if(l_ins < 0) l_ins += this.m_buffer_size;
            this.m_count          = (l_cnt - 1);
            l_t                   = this.m_buffer[l_ins];
            this.m_buffer[l_ins]  = null;
            return l_t;
            }

          try
            {
            this.m_sync.wait();
            }
          catch(InterruptedException l_ie)
            {
            //
            }
          }
        else
          {
          return null;
          }
        }
      }
    }

/**
 * Dequeue an element from the buffer without blocking. This will only
 * yield an item if the buffer is not empty.
 * @return  Either an element which was enqueued before, or
 *          <code>null</code> if currently no item is stored in the
 *          buffer.
 */

  public  final Type  nonblocking_dequeue ()
    {
    int   l_ins, l_cnt;
    Type  l_t;

    synchronized(this.m_sync)
      {
      if(this.m_running)
        {
        l_cnt = this.m_count;
        if(l_cnt > 0)
          {
          l_ins                 = (this.m_ins - l_cnt);
          if(l_ins < 0) l_ins += this.m_buffer_size;
          this.m_count          = (l_cnt - 1);
          l_t                   = this.m_buffer[l_ins];
          this.m_buffer[l_ins]  = null;
          return l_t;
          }
        }
      }

    return null;
    }

/**
 * Abort the circular buffer, release all waiting threads and drop all the
 * items enqueued.
 */

  public  final void  abort ()
    {
    final int     l_bs;
          int     l_i, l_ins;
          Type[]  l_b;

    synchronized(this.m_sync)
      {
      if(this.m_running)
        {
        this.m_running = false;
        l_i            = this.m_count;
        this.m_count   = 0;
        this.m_sync.notifyAll();        
        }
      else return;

      this.m_sync.notifyAll();
      }
    
    l_b            = this.m_buffer;
    l_bs           = this.m_buffer_size;
    l_ins          = this.m_ins - l_i;
    if(l_ins < 0) l_ins += l_bs;

    for(; l_i > 0; l_i--)
      {
      this.drop(l_b[l_ins]);
      l_b[l_ins] = null;
      if((++l_ins) >= l_bs) l_ins = 0;
      }
    
    synchronized(this.m_sync)
      {
      this.m_sync.notifyAll();
      }
    }

/**
 * Resize the buffer to the specified size.
 * @param p_buffer_size The new buffer size. Warning: If this is 0, a call
 *                      to <code>dequeue</code> will block forever.
 * @see #dequeue()
 */

  public  final void  set_size  (final int p_buffer_size)
    {
    final int     l_bs;
          int     l_ins, l_cnt,  l_sp_1, l_sp_2, l_i, l_j;
          Type[]  l_buf;
          Type    l_t;

    synchronized(this.m_sync)
      {
      if(this.m_running)
        {
        l_bs = this.m_buffer_size;

        if(l_bs != p_buffer_size)
          {
// If our buffer's size does differ from the wanted one, we first need
// to re-arrange its contents.

          l_cnt   = this.m_count;
          l_ins   = this.m_ins;
          l_sp_2  = (l_ins - l_cnt);
          if(l_sp_2 < 0) l_sp_2 += l_bs;
          l_buf   = this.m_buffer;

          if(p_buffer_size > 0)
            {
            if(l_cnt > 0)
              {
              if(l_ins > l_sp_2)
                {
                System.arraycopy(l_buf, l_sp_2, l_buf, 0, l_cnt);
                l_sp_1 = Math.max(l_cnt, l_sp_2);
                Arrays.fill(l_buf, null, l_sp_1, l_ins - l_sp_1);
                l_ins = l_cnt;
                }
              else
                {
                l_sp_1  = 0;

                for(;;)
                  {
                  l_j = l_sp_2;
                  for(l_i = l_sp_1; l_i < l_sp_2; l_i++)
                    {
                    l_t        = l_buf[l_i];
                    l_buf[l_i] = l_buf[l_j];
                    l_buf[l_j] = l_t;
                    if((++l_j) >= l_bs) l_j = l_sp_2;
                    }

                  l_sp_1 = l_sp_2;
                  l_sp_2 = l_j;
                  if(l_sp_1 >= l_sp_2) break;
                  }

                }
              }

            this.m_buffer_size = p_buffer_size;

  // fine, re-arranging is done
  // now resize
            if(p_buffer_size > l_bs)
              {
              if(p_buffer_size < l_buf.length) return;
              l_buf = Arrays.create(this.m_class, (p_buffer_size*3)>>>1);
              System.arraycopy(this.m_buffer, 0, l_buf, 0, l_cnt);
              this.m_ins    = l_cnt;
              this.m_buffer = l_buf;
              }
            else
              {
              for(l_i = p_buffer_size; l_i < l_cnt; l_i++)
                {
                this.drop(l_buf[l_i]);
                }

              if(l_bs > (3*p_buffer_size))
                {
                l_buf = Arrays.create(this.m_class, p_buffer_size);
                System.arraycopy(this.m_buffer, 0, l_buf, 0, p_buffer_size);
                this.m_buffer = l_buf;
                }

              if(l_cnt < p_buffer_size)
                {
                this.m_ins = l_cnt;
                }
              else
                {
                this.m_ins   = 0;
                this.m_count = p_buffer_size;
                }
              }
            }
          else
            {
            for(; l_cnt > 0; l_cnt--)
              {
              this.drop(l_buf[l_sp_2]);
              l_sp_2++;
              if(l_sp_2 >= l_bs) l_sp_2 = 0;
              }

            this.m_count       = 0;
            this.m_buffer_size = 0;
            this.m_ins         = 0;
            }
          }
        }
      }
    }

/**
 * Get the current count of stored items.
 * @return The current count of stored items.
 */

  public  final int get_count ()
    {
    synchronized(this.m_sync)
      {
      if(this.m_running) return this.m_count;
      }
    return 0;
    }

/**
 * Obtain the current buffer size.
 * @return  The size of the circular buffer.
 * @see #set_size(int)
 */

  public  final int get_size  ()
    {
    synchronized(this.m_sync)
      {
      if(this.m_running) return this.m_buffer_size;
      }

    return 0;
    }
/**
 * Obtain the current count of free slots.
 * @return  The current count of free slots.
 * @see #get_size()
 */

  public  final int get_free_slots ()
    {
    synchronized(this.m_sync)
      {
      if(this.m_running) return (this.m_buffer_size - this.m_count);
      }

    return 0;
    }
  }

File Information:

file name:CircularBuffer.java
package:org.sfc.collections
qualified name:org.sfc.collections.CircularBuffer.java
file type:Java Source File
download location:download http://dgpf.sourceforge.net/source/org/sfc/collections/CircularBuffer.java
size:11.925 KB (12212 B)
uploaded: 2018-01-07 12:03:36 GMT+0000
last update: 2006-05-12 12:45:54 GMT+0000
last access: 2018-04-26 01:39:57 GMT+0000

statistics online since 2006-01-02.   RSS Feed
Contact us by sending an email to tweise@gmx.de to receive further information, to report errors, or to join our project.
All content on this site (http://dgpf.sourceforge.net/) is LGPL-licensed.
http://dgpf.sourceforge.net/scripts/source/source.php last modified at 2018-01-07 12:03:34 GMT+0000 served at 2018-04-26 01:39:57 GMT+0000.
Valid CSS Valid XHTML 1.1
Valid RSS SourceForge.net Logo