1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache license, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the license for the specific language governing permissions and 15 * limitations under the license. 16 */ 17 package org.apache.logging.log4j.core.util; 18 19 import java.lang.reflect.Array; 20 21 /** 22 * A bounded buffer containing elements of type T. When the number of elements to be added will exceed the 23 * size of the buffer the oldest element will be overwritten. Access to the buffer is thread safe. 24 * @param <T> The type of object stored in the buffer. 25 */ 26 public final class CyclicBuffer<T> { 27 private final T[] ring; 28 private int first = 0; 29 private int last = 0; 30 private int numElems = 0; 31 private final Class<T> clazz; 32 33 /** 34 * Instantiate a new CyclicBuffer of at most <code>maxSize</code> events. 35 * @param clazz The Class associate with the type of object in the buffer. 36 * @param size The number of items in the buffer. 37 * @throws IllegalArgumentException if the size is negative. 38 */ 39 public CyclicBuffer(final Class<T> clazz, final int size) throws IllegalArgumentException { 40 if (size < 1) { 41 throw new IllegalArgumentException("The maxSize argument (" + size + ") is not a positive integer."); 42 } 43 this.ring = makeArray(clazz, size); 44 this.clazz = clazz; 45 } 46 47 @SuppressWarnings("unchecked") 48 private T[] makeArray(final Class<T> cls, final int size) { 49 return (T[]) Array.newInstance(cls, size); 50 } 51 52 /** 53 * Add an item as the last event in the buffer. 54 * @param item The item to add to the buffer. 55 */ 56 public synchronized void add(final T item) { 57 ring[last] = item; 58 if (++last == ring.length) { 59 last = 0; 60 } 61 62 if (numElems < ring.length) { 63 numElems++; 64 } else if (++first == ring.length) { 65 first = 0; 66 } 67 } 68 69 /** 70 * Removes all the elements from the buffer and returns them. 71 * @return An array of the elements in the buffer. 72 */ 73 public synchronized T[] removeAll() { 74 final T[] array = makeArray(clazz, numElems); 75 int index = 0; 76 while (numElems > 0) { 77 numElems--; 78 array[index++] = ring[first]; 79 ring[first] = null; 80 if (++first == ring.length) { 81 first = 0; 82 } 83 } 84 return array; 85 } 86 87 /** 88 * Determines if the buffer contains elements. 89 * @return true if the buffer is empty, false otherwise. 90 */ 91 public boolean isEmpty() { 92 return 0 == numElems; 93 } 94 }