21
21
import java .util .AbstractQueue ;
22
22
import java .util .Iterator ;
23
23
24
- abstract class ConcurrentCircularArrayQueueL0Pad <E > extends AbstractQueue <E >{
24
+ abstract class ConcurrentCircularArrayQueueL0Pad <E > extends AbstractQueue <E > implements MessagePassingQueue < E > {
25
25
long p00 , p01 , p02 , p03 , p04 , p05 , p06 , p07 ;
26
26
long p30 , p31 , p32 , p33 , p34 , p35 , p36 , p37 ;
27
27
}
28
28
29
+ /**
30
+ * A concurrent access enabling class used by circular array based queues this class exposes an offset computation
31
+ * method along with differently memory fenced load/store methods into the underlying array. The class is pre-padded and
32
+ * the array is padded on either side to help with False sharing prvention. It is expected theat subclasses handle post
33
+ * padding.
34
+ * <p>
35
+ * Offset calculation is separate from access to enable the reuse of a give compute offset.
36
+ * <p>
37
+ * Load/Store methods using a <i>buffer</i> parameter are provided to allow the prevention of final field reload after a
38
+ * LoadLoad barrier.
39
+ * <p>
40
+ *
41
+ * @author nitsanw
42
+ *
43
+ * @param <E>
44
+ */
29
45
public abstract class ConcurrentCircularArrayQueue <E > extends ConcurrentCircularArrayQueueL0Pad <E > {
30
46
protected static final int SPARSE_SHIFT = Integer .getInteger ("sparse.shift" , 0 );
31
47
protected static final int BUFFER_PAD = 32 ;
@@ -51,87 +67,108 @@ public abstract class ConcurrentCircularArrayQueue<E> extends ConcurrentCircular
51
67
52
68
@ SuppressWarnings ("unchecked" )
53
69
public ConcurrentCircularArrayQueue (int capacity ) {
54
- this .capacity = Pow2 .findNextPositivePowerOfTwo (capacity );
70
+ this .capacity = Pow2 .roundToPowerOfTwo (capacity );
55
71
mask = this .capacity - 1 ;
56
72
// pad data on either end with some empty slots.
57
73
buffer = (E []) new Object [(this .capacity << SPARSE_SHIFT ) + BUFFER_PAD * 2 ];
58
74
}
59
75
60
- public ConcurrentCircularArrayQueue (ConcurrentCircularArrayQueue <E > c ) {
61
- this .capacity = c .capacity ;
62
- this .mask = c .mask ;
63
- // pad data on either end with some empty slots.
64
- this .buffer = c .buffer ;
65
- }
66
-
67
- protected final long calcOffset (long index ) {
76
+ /**
77
+ * @param index desirable element index
78
+ * @return the offset in bytes within the array for a given index.
79
+ */
80
+ protected final long calcElementOffset (long index ) {
68
81
return REF_ARRAY_BASE + ((index & mask ) << REF_ELEMENT_SHIFT );
69
82
}
70
83
84
+ /**
85
+ * A plain store (no ordering/fences) of an element to a given offset
86
+ *
87
+ * @param offset computed via {@link ConcurrentCircularArrayQueue#calcElementOffset(long)}
88
+ * @param e a kitty
89
+ */
71
90
protected final void spElement (long offset , E e ) {
72
- UNSAFE .putObject (buffer , offset , e );
73
- }
74
-
75
- protected final void soElement (long offset , E e ) {
76
- UNSAFE .putOrderedObject (buffer , offset , e );
77
- }
78
-
79
- protected final void svElement (long offset , E e ) {
80
- UNSAFE .putObjectVolatile (buffer , offset , e );
81
- }
82
-
83
- @ SuppressWarnings ("unchecked" )
84
- protected final E lpElement (long offset ) {
85
- return (E ) UNSAFE .getObject (buffer , offset );
86
- }
87
-
88
- @ SuppressWarnings ("unchecked" )
89
- protected final E lvElement (long offset ) {
90
- return (E ) UNSAFE .getObjectVolatile (buffer , offset );
91
+ spElement (buffer , offset , e );
91
92
}
92
93
94
+ /**
95
+ * A plain store (no ordering/fences) of an element to a given offset
96
+ *
97
+ * @param buffer this.buffer
98
+ * @param offset computed via {@link ConcurrentCircularArrayQueue#calcElementOffset(long)}
99
+ * @param e an orderly kitty
100
+ */
93
101
protected final void spElement (E [] buffer , long offset , E e ) {
94
102
UNSAFE .putObject (buffer , offset , e );
95
103
}
96
104
105
+ /**
106
+ * An ordered store(store + StoreStore barrier) of an element to a given offset
107
+ *
108
+ * @param offset computed via {@link ConcurrentCircularArrayQueue#calcElementOffset(long)}
109
+ * @param e an orderly kitty
110
+ */
111
+ protected final void soElement (long offset , E e ) {
112
+ soElement (buffer , offset , e );
113
+ }
114
+
115
+ /**
116
+ * An ordered store(store + StoreStore barrier) of an element to a given offset
117
+ *
118
+ * @param buffer this.buffer
119
+ * @param offset computed via {@link ConcurrentCircularArrayQueue#calcElementOffset(long)}
120
+ * @param e an orderly kitty
121
+ */
97
122
protected final void soElement (E [] buffer , long offset , E e ) {
98
123
UNSAFE .putOrderedObject (buffer , offset , e );
99
124
}
100
125
101
- protected final void svElement (E [] buffer , long offset , E e ) {
102
- UNSAFE .putObjectVolatile (buffer , offset , e );
126
+ /**
127
+ * A plain load (no ordering/fences) of an element from a given offset.
128
+ *
129
+ * @param offset computed via {@link ConcurrentCircularArrayQueue#calcElementOffset(long)}
130
+ * @return the element at the offset
131
+ */
132
+ protected final E lpElement (long offset ) {
133
+ return lpElement (buffer , offset );
103
134
}
104
135
136
+ /**
137
+ * A plain load (no ordering/fences) of an element from a given offset.
138
+ *
139
+ * @param buffer this.buffer
140
+ * @param offset computed via {@link ConcurrentCircularArrayQueue#calcElementOffset(long)}
141
+ * @return the element at the offset
142
+ */
105
143
@ SuppressWarnings ("unchecked" )
106
144
protected final E lpElement (E [] buffer , long offset ) {
107
145
return (E ) UNSAFE .getObject (buffer , offset );
108
146
}
109
147
148
+ /**
149
+ * A volatile load (load + LoadLoad barrier) of an element from a given offset.
150
+ *
151
+ * @param offset computed via {@link ConcurrentCircularArrayQueue#calcElementOffset(long)}
152
+ * @return the element at the offset
153
+ */
154
+ protected final E lvElement (long offset ) {
155
+ return lvElement (buffer , offset );
156
+ }
157
+
158
+ /**
159
+ * A volatile load (load + LoadLoad barrier) of an element from a given offset.
160
+ *
161
+ * @param buffer this.buffer
162
+ * @param offset computed via {@link ConcurrentCircularArrayQueue#calcElementOffset(long)}
163
+ * @return the element at the offset
164
+ */
110
165
@ SuppressWarnings ("unchecked" )
111
166
protected final E lvElement (E [] buffer , long offset ) {
112
167
return (E ) UNSAFE .getObjectVolatile (buffer , offset );
113
168
}
114
169
115
- @ Override
116
- public boolean offer (E e ) {
117
- throw new UnsupportedOperationException ();
118
- }
119
-
120
- @ Override
121
- public E poll () {
122
- throw new UnsupportedOperationException ();
123
- }
124
- @ Override
125
- public E peek () {
126
- throw new UnsupportedOperationException ();
127
- }
128
170
@ Override
129
171
public Iterator <E > iterator () {
130
172
throw new UnsupportedOperationException ();
131
173
}
132
-
133
- @ Override
134
- public int size () {
135
- throw new UnsupportedOperationException ();
136
- }
137
174
}
0 commit comments