20
20
import java .lang .reflect .Method ;
21
21
import java .util .Queue ;
22
22
import java .util .concurrent .ArrayBlockingQueue ;
23
+ import java .util .function .Supplier ;
23
24
import org .jctools .queues .MpmcArrayQueue ;
24
25
import org .jctools .queues .SpscArrayQueue ;
25
26
26
27
/**
27
- * Provides {@link QueueFactory} and {@link Queue} instances for different use cases.
28
+ * Provides {@link QueueFactory} instances for different use cases.
28
29
* <p>
29
30
* Implementations provided by <a href="https://jctools.github.io/JCTools/">JCTools</a> will be preferred, if available at runtime.
30
31
* Otherwise, {@link ArrayBlockingQueue} will be used.
33
34
* @since 3.0.0
34
35
*/
35
36
@ InternalApi
36
- public enum QueueFactories {
37
+ public enum QueueFactories implements QueueFactory {
37
38
38
39
/**
39
40
* Provides a bounded queue for single-producer/single-consumer usage.
40
41
*/
41
- SPSC (Lazy . lazy ( JCToolsQueueFactory . SPSC :: load ) ),
42
+ SPSC (() -> SpscArrayQueue :: new ),
42
43
43
44
/**
44
45
* Provides a bounded queue for multi-producer/multi-consumer usage.
45
46
*/
46
- MPMC (Lazy . lazy ( JCToolsQueueFactory . MPMC :: load ) );
47
+ MPMC (() -> MpmcArrayQueue :: new );
47
48
48
- private final Lazy < BoundedQueueFactory > queueFactory ;
49
+ private final QueueFactory queueFactory ;
49
50
50
- QueueFactories (final Lazy < BoundedQueueFactory > queueFactory ) {
51
- this .queueFactory = queueFactory ;
51
+ QueueFactories (final Supplier < QueueFactory > queueFactoryProvider ) {
52
+ this .queueFactory = getOrReplaceQueueFactory ( queueFactoryProvider ) ;
52
53
}
53
54
54
- public QueueFactory factory (final int capacity ) {
55
- return new ProxyQueueFactory (queueFactory .get (), capacity );
55
+ private static QueueFactory getOrReplaceQueueFactory (final Supplier <QueueFactory > queueFactoryProvider ) {
56
+ try {
57
+ final QueueFactory queueFactory = queueFactoryProvider .get ();
58
+ // Test with a large enough capacity to avoid any `IllegalArgumentExceptions` from trivial queues
59
+ queueFactory .create (16 );
60
+ return queueFactory ;
61
+ } catch (final LinkageError ignored ) {
62
+ return ArrayBlockingQueueFactory .INSTANCE ;
63
+ }
56
64
}
57
65
66
+ @ Override
58
67
public <E > Queue <E > create (final int capacity ) {
59
- return queueFactory .get ().create (capacity );
68
+ return queueFactory .create (capacity );
69
+ }
70
+
71
+ private static final class ArrayBlockingQueueFactory implements QueueFactory {
72
+
73
+ private static final ArrayBlockingQueueFactory INSTANCE = new ArrayBlockingQueueFactory ();
74
+
75
+ private ArrayBlockingQueueFactory () {}
76
+
77
+ @ Override
78
+ public <E > Queue <E > create (final int capacity ) {
79
+ return new ArrayBlockingQueue <>(capacity );
80
+ }
60
81
}
61
82
62
83
/**
63
- * Creates a {@link QueueFactory} producing queues of provided capacity from the provided supplier.
84
+ * Creates a {@link QueueFactory} using the provided supplier.
64
85
* <p>
65
86
* A supplier path must be formatted as follows:
66
87
* <ul>
@@ -70,10 +91,9 @@ public <E> Queue<E> create(final int capacity) {
70
91
* </p>
71
92
*
72
93
* @param supplierPath a queue supplier path (e.g., {@code org.jctools.queues.MpmcArrayQueue.new}, {@code com.acme.Queues.createBoundedQueue})
73
- * @param capacity the capacity that will be passed to the queue supplier
74
94
* @return a new {@link QueueFactory} instance
75
95
*/
76
- public static QueueFactory createQueueFactory (final String supplierPath , final int capacity ) {
96
+ public static QueueFactory ofSupplier (final String supplierPath ) {
77
97
final int supplierPathSplitterIndex = supplierPath .lastIndexOf ('.' );
78
98
if (supplierPathSplitterIndex < 0 ) {
79
99
final String message = String .format ("invalid queue factory supplier path: `%s`" , supplierPath );
@@ -83,84 +103,21 @@ public static QueueFactory createQueueFactory(final String supplierPath, final i
83
103
final String supplierMethodName = supplierPath .substring (supplierPathSplitterIndex + 1 );
84
104
try {
85
105
final Class <?> supplierClass = LoaderUtil .loadClass (supplierClassName );
86
- final BoundedQueueFactory queueFactory ;
87
106
if ("new" .equals (supplierMethodName )) {
88
107
final Constructor <?> supplierCtor = supplierClass .getDeclaredConstructor (int .class );
89
- queueFactory = new ConstructorProvidedQueueFactory (supplierCtor );
108
+ return new ConstructorProvidedQueueFactory (supplierCtor );
90
109
} else {
91
110
final Method supplierMethod = supplierClass .getMethod (supplierMethodName , int .class );
92
- queueFactory = new StaticMethodProvidedQueueFactory (supplierMethod );
111
+ return new StaticMethodProvidedQueueFactory (supplierMethod );
93
112
}
94
- return new ProxyQueueFactory (queueFactory , capacity );
95
113
} catch (final ReflectiveOperationException | LinkageError | SecurityException error ) {
96
114
final String message =
97
115
String .format ("failed to create the queue factory using the supplier path `%s`" , supplierPath );
98
116
throw new RuntimeException (message , error );
99
117
}
100
118
}
101
119
102
- private static final class ProxyQueueFactory implements QueueFactory {
103
-
104
- private final BoundedQueueFactory factory ;
105
-
106
- private final int capacity ;
107
-
108
- private ProxyQueueFactory (final BoundedQueueFactory factory , final int capacity ) {
109
- this .factory = factory ;
110
- this .capacity = capacity ;
111
- }
112
-
113
- @ Override
114
- public <E > Queue <E > create () {
115
- return factory .create (capacity );
116
- }
117
- }
118
-
119
- @ FunctionalInterface
120
- private interface BoundedQueueFactory {
121
-
122
- <E > Queue <E > create (final int capacity );
123
- }
124
-
125
- private static final class ArrayBlockingQueueFactory implements BoundedQueueFactory {
126
-
127
- private static final ArrayBlockingQueueFactory INSTANCE = new ArrayBlockingQueueFactory ();
128
-
129
- private ArrayBlockingQueueFactory () {}
130
-
131
- @ Override
132
- public <E > Queue <E > create (final int capacity ) {
133
- return new ArrayBlockingQueue <>(capacity );
134
- }
135
- }
136
-
137
- private enum JCToolsQueueFactory implements BoundedQueueFactory {
138
- SPSC {
139
- @ Override
140
- public <E > Queue <E > create (final int capacity ) {
141
- return new SpscArrayQueue <>(capacity );
142
- }
143
- },
144
-
145
- MPMC {
146
- @ Override
147
- public <E > Queue <E > create (final int capacity ) {
148
- return new MpmcArrayQueue <>(capacity );
149
- }
150
- };
151
-
152
- private BoundedQueueFactory load () {
153
- try {
154
- // Test with a large enough capacity to avoid any `IllegalArgumentExceptions` from trivial queues
155
- create (16 );
156
- return this ;
157
- } catch (final LinkageError ignored ) {
158
- return ArrayBlockingQueueFactory .INSTANCE ;
159
- }
160
- }
161
- }
162
-
163
- private static final class ConstructorProvidedQueueFactory implements BoundedQueueFactory {
120
+ private static final class ConstructorProvidedQueueFactory implements QueueFactory {
164
121
165
122
private final Constructor <?> constructor ;
166
123
@@ -179,7 +136,7 @@ public <E> Queue<E> create(final int capacity) {
179
136
}
180
137
}
181
138
182
- private static final class StaticMethodProvidedQueueFactory implements BoundedQueueFactory {
139
+ private static final class StaticMethodProvidedQueueFactory implements QueueFactory {
183
140
184
141
private final Method method ;
185
142
0 commit comments