RingBuffer.java
001 /*
002  * Java Genetic Algorithm Library (jenetics-7.1.0).
003  * Copyright (c) 2007-2022 Franz Wilhelmstötter
004  *
005  * Licensed under the Apache License, Version 2.0 (the "License");
006  * you may not use this file except in compliance with the License.
007  * You may obtain a copy of the License at
008  *
009  *      http://www.apache.org/licenses/LICENSE-2.0
010  *
011  * Unless required by applicable law or agreed to in writing, software
012  * distributed under the License is distributed on an "AS IS" BASIS,
013  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014  * See the License for the specific language governing permissions and
015  * limitations under the License.
016  *
017  * Author:
018  *    Franz Wilhelmstötter (franz.wilhelmstoetter@gmail.com)
019  */
020 package io.jenetics.prog.regression;
021 
022 import java.util.Arrays;
023 import java.util.Collection;
024 import java.util.Iterator;
025 
026 /**
027  @author <a href="mailto:franz.wilhelmstoetter@gmail.com">Franz Wilhelmstötter</a>
028  @version 6.0
029  @since 6.0
030  */
031 final class RingBuffer {
032 
033     private final Object[] _buffer;
034 
035     private int _cursor = -1;
036     private int _size = 0;
037 
038     private Object[] _snapshot = null;
039 
040     RingBuffer(final int capacity) {
041         if (capacity < 1) {
042             throw new IllegalArgumentException(
043                 "Buffer size must be a positive: " + capacity
044             );
045         }
046 
047         _buffer = new Object[capacity];
048     }
049 
050     synchronized void add(final Object element) {
051         _buffer[next()] = element;
052         _snapshot = null;
053     }
054 
055     private int next() {
056         if (_size < _buffer.length) {
057             ++_size;
058         }
059         return _cursor = (_cursor + < _buffer.length? _cursor + 0;
060     }
061 
062     synchronized void addAll(final Collection<?> elements) {
063         final Iterator<?> it = elements.iterator();
064         if (elements.size() > capacity()) {
065             for (int i = capacity(); i < elements.size(); ++i) {
066                 it.next();
067             }
068         }
069 
070         while (it.hasNext()) {
071             _buffer[next()] = it.next();
072         }
073         _snapshot = null;
074     }
075 
076     synchronized Object[] snapshot() {
077         if (_snapshot != null) {
078             return _snapshot;
079         }
080 
081         final Object[] result = new Object[_size];
082         if (_size < _buffer.length) {
083             System.arraycopy(_buffer, 0, result, 0, _size);
084         else {
085             System.arraycopy(
086                 _buffer, _cursor + 1,
087                 result, 0, _buffer.length - _cursor - 1
088             );
089             System.arraycopy(
090                 _buffer, 0,
091                 result, _buffer.length - _cursor - 1, _cursor + 1
092             );
093         }
094 
095         return _snapshot = result;
096     }
097 
098     /**
099      * Removes all the elements from {@code this} ring-buffer. The buffer
100      * will be empty after this method returns.
101      */
102     void clear() {
103         Arrays.fill(_buffer, null);
104         _cursor = -1;
105         _size = 0;
106         _snapshot = null;
107     }
108 
109     /**
110      * Return the capacity of {@code this} ring-buffer.
111      *
112      @return the capacity of {@code this} ring-buffers
113      */
114     int capacity() {
115         return _buffer.length;
116     }
117 
118     /**
119      * Return the size of {@code this} ring-buffer, where {@code size <= capacity}
120      * is always true.
121      *
122      @return the capacity of {@code this} ring-buffers
123      */
124     int size() {
125         return _size;
126     }
127 }