查看本类的 API文档回源码主页即时通讯网 - 即时通讯开发者社区!
1   /*
2    * Licensed under the Apache License, Version 2.0 (the "License");
3    * you may not use this file except in compliance with the License.
4    * You may obtain a copy of the License at
5    *
6    * http://www.apache.org/licenses/LICENSE-2.0
7    *
8    * Unless required by applicable law or agreed to in writing, software
9    * distributed under the License is distributed on an "AS IS" BASIS,
10   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11   * See the License for the specific language governing permissions and
12   * limitations under the License.
13   */
14  package io.netty.util.internal.shaded.org.jctools.queues;
15  
16  import io.netty.util.internal.shaded.org.jctools.queues.IndexedQueueSizeUtil.IndexedQueue;
17  import io.netty.util.internal.shaded.org.jctools.util.Pow2;
18  
19  import java.util.AbstractQueue;
20  import java.util.Iterator;
21  import java.util.NoSuchElementException;
22  
23  import static io.netty.util.internal.shaded.org.jctools.util.UnsafeRefArrayAccess.*;
24  
25  abstract class ConcurrentCircularArrayQueueL0Pad<E> extends AbstractQueue<E>
26  {
27      long p01, p02, p03, p04, p05, p06, p07;
28      long p10, p11, p12, p13, p14, p15, p16, p17;
29  }
30  
31  /**
32   * Common functionality for array backed queues. The class is pre-padded and the array is padded on either side to help
33   * with False Sharing prevention. It is expected that subclasses handle post padding.
34   */
35  abstract class ConcurrentCircularArrayQueue<E> extends ConcurrentCircularArrayQueueL0Pad<E>
36      implements MessagePassingQueue<E>, IndexedQueue, QueueProgressIndicators, SupportsIterator
37  {
38      protected final long mask;
39      protected final E[] buffer;
40  
41      ConcurrentCircularArrayQueue(int capacity)
42      {
43          int actualCapacity = Pow2.roundToPowerOfTwo(capacity);
44          mask = actualCapacity - 1;
45          buffer = allocateRefArray(actualCapacity);
46      }
47  
48      @Override
49      public int size()
50      {
51          return IndexedQueueSizeUtil.size(this);
52      }
53  
54      @Override
55      public boolean isEmpty()
56      {
57          return IndexedQueueSizeUtil.isEmpty(this);
58      }
59  
60      @Override
61      public String toString()
62      {
63          return this.getClass().getName();
64      }
65  
66      @Override
67      public void clear()
68      {
69          while (poll() != null)
70          {
71              // if you stare into the void
72          }
73      }
74  
75      @Override
76      public int capacity()
77      {
78          return (int) (mask + 1);
79      }
80  
81      @Override
82      public long currentProducerIndex()
83      {
84          return lvProducerIndex();
85      }
86  
87      @Override
88      public long currentConsumerIndex()
89      {
90          return lvConsumerIndex();
91      }
92  
93      /**
94       * Get an iterator for this queue. This method is thread safe.
95       * <p>
96       * The iterator provides a best-effort snapshot of the elements in the queue.
97       * The returned iterator is not guaranteed to return elements in queue order,
98       * and races with the consumer thread may cause gaps in the sequence of returned elements.
99       * Like {link #relaxedPoll}, the iterator may not immediately return newly inserted elements.
100      *
101      * @return The iterator.
102      */
103     @Override
104     public Iterator<E> iterator() {
105         final long cIndex = lvConsumerIndex();
106         final long pIndex = lvProducerIndex();
107 
108         return new WeakIterator(cIndex, pIndex, mask, buffer);
109     }
110 
111     private static class WeakIterator<E> implements Iterator<E> {
112         private final long pIndex;
113         private final long mask;
114         private final E[] buffer;
115         private long nextIndex;
116         private E nextElement;
117 
118         WeakIterator(long cIndex, long pIndex, long mask, E[] buffer) {
119             this.nextIndex = cIndex;
120             this.pIndex = pIndex;
121             this.mask = mask;
122             this.buffer = buffer;
123             nextElement = getNext();
124         }
125 
126         @Override
127         public void remove() {
128             throw new UnsupportedOperationException("remove");
129         }
130 
131         @Override
132         public boolean hasNext() {
133             return nextElement != null;
134         }
135 
136         @Override
137         public E next() {
138             final E e = nextElement;
139             if (e == null)
140                 throw new NoSuchElementException();
141             nextElement = getNext();
142             return e;
143         }
144 
145         private E getNext() {
146             while (nextIndex < pIndex) {
147                 long offset = calcCircularRefElementOffset(nextIndex++, mask);
148                 E e = lvRefElement(buffer, offset);
149                 if (e != null) {
150                     return e;
151                 }
152             }
153             return null;
154         }
155     }
156 }