d53a771e50ad054312abff78f3ba8372f5bf9854
[jalview.git] / srcjar2 / org / apache / log4j / helpers / BoundedFIFO.java
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
18 // Contributors:     Mathias Bogaert
19 //                   joelr@viair.com
20
21 package org.apache.log4j.helpers;
22
23 import org.apache.log4j.spi.LoggingEvent;
24
25 /**
26    <code>BoundedFIFO</code> serves as the bounded first-in-first-out
27    buffer heavily used by the {@link org.apache.log4j.AsyncAppender}.
28    
29    @author Ceki G&uuml;lc&uuml; 
30    @since version 0.9.1 */
31 public class BoundedFIFO {
32   
33   LoggingEvent[] buf;
34   int numElements = 0;
35   int first = 0;
36   int next = 0;
37   int maxSize;
38
39   /**
40      Instantiate a new BoundedFIFO with a maximum size passed as argument.
41    */
42   public
43   BoundedFIFO(int maxSize) {
44    if(maxSize < 1) {
45       throw new IllegalArgumentException("The maxSize argument ("+maxSize+
46                             ") is not a positive integer.");
47     }
48     this.maxSize = maxSize;
49     buf = new LoggingEvent[maxSize];
50   }
51   
52   /**
53      Get the first element in the buffer. Returns <code>null</code> if
54      there are no elements in the buffer.  */
55   public
56   LoggingEvent get() {
57     if(numElements == 0) {
58         return null;
59     }
60     
61     LoggingEvent r = buf[first];
62     buf[first] = null; // help garbage collection
63
64     if(++first == maxSize) {
65         first = 0;
66     }
67     numElements--;    
68     return r;    
69   }
70
71   /**
72      Place a {@link LoggingEvent} in the buffer. If the buffer is full
73      then the event is <b>silently dropped</b>. It is the caller's
74      responsability to make sure that the buffer has free space.  */
75   public 
76   void put(LoggingEvent o) {
77     if(numElements != maxSize) {      
78       buf[next] = o;    
79       if(++next == maxSize) {
80         next = 0;
81       }
82       numElements++;
83     }
84   }
85
86   /**
87      Get the maximum size of the buffer.
88    */
89   public 
90   int getMaxSize() {
91     return maxSize;
92   }
93
94   /**
95      Return <code>true</code> if the buffer is full, that is, whether
96      the number of elements in the buffer equals the buffer size. */
97   public 
98   boolean isFull() {
99     return numElements == maxSize;
100   }
101
102   /**
103      Get the number of elements in the buffer. This number is
104      guaranteed to be in the range 0 to <code>maxSize</code>
105      (inclusive).
106   */
107   public
108   int length() {
109     return numElements;
110   } 
111
112
113   int min(int a, int b) {
114     return a < b ? a : b;
115   }
116
117
118   /**
119      Resize the buffer to a new size. If the new size is smaller than
120      the old size events might be lost.
121      
122      @since 1.1
123    */
124   synchronized
125   public 
126   void resize(int newSize) {
127     if(newSize == maxSize) {
128         return;
129     }
130
131
132    LoggingEvent[] tmp = new LoggingEvent[newSize];
133
134    // we should not copy beyond the buf array
135    int len1 = maxSize - first;
136
137    // we should not copy beyond the tmp array
138    len1 = min(len1, newSize);
139
140    // er.. how much do we actually need to copy?
141    // We should not copy more than the actual number of elements.
142    len1 = min(len1, numElements);
143
144    // Copy from buf starting a first, to tmp, starting at position 0, len1 elements.
145    System.arraycopy(buf, first, tmp, 0, len1);
146    
147    // Are there any uncopied elements and is there still space in the new array?
148    int len2 = 0;
149    if((len1 < numElements) && (len1 < newSize)) {
150      len2 = numElements - len1;
151      len2 = min(len2, newSize - len1);
152      System.arraycopy(buf, 0, tmp, len1, len2);
153    }
154    
155    this.buf = tmp;
156    this.maxSize = newSize;    
157    this.first=0;   
158    this.numElements = len1+len2;
159    this.next = this.numElements;
160    if(this.next == this.maxSize) {
161     this.next = 0;
162 }
163   }
164
165   
166   /**
167      Returns <code>true</code> if there is just one element in the
168      buffer. In other words, if there were no elements before the last
169      {@link #put} operation completed.  */
170   public
171   boolean wasEmpty() {
172     return numElements == 1;
173   }
174
175   /**
176       Returns <code>true</code> if the number of elements in the
177       buffer plus 1 equals the maximum buffer size, returns
178       <code>false</code> otherwise. */
179   public
180   boolean wasFull() {
181     return (numElements+1 == maxSize);
182   }
183
184 }