2020import java .lang .reflect .Method ;
2121import java .util .Queue ;
2222import java .util .concurrent .ArrayBlockingQueue ;
23+ import java .util .function .Supplier ;
2324import org .jctools .queues .MpmcArrayQueue ;
2425import org .jctools .queues .SpscArrayQueue ;
2526
2627/**
27- * Provides {@link QueueFactory} and {@link Queue} instances for different use cases.
28+ * Provides {@link QueueFactory} instances for different use cases.
2829 * <p>
2930 * Implementations provided by <a href="https://jctools.github.io/JCTools/">JCTools</a> will be preferred, if available at runtime.
3031 * Otherwise, {@link ArrayBlockingQueue} will be used.
3334 * @since 3.0.0
3435 */
3536@ InternalApi
36- public enum QueueFactories {
37+ public enum QueueFactories implements QueueFactory {
3738
3839 /**
3940 * Provides a bounded queue for single-producer/single-consumer usage.
4041 */
41- SPSC (Lazy . lazy ( JCToolsQueueFactory . SPSC :: load ) ),
42+ SPSC (() -> SpscArrayQueue :: new ),
4243
4344 /**
4445 * Provides a bounded queue for multi-producer/multi-consumer usage.
4546 */
46- MPMC (Lazy . lazy ( JCToolsQueueFactory . MPMC :: load ) );
47+ MPMC (() -> MpmcArrayQueue :: new );
4748
48- private final Lazy < BoundedQueueFactory > queueFactory ;
49+ private final QueueFactory queueFactory ;
4950
50- QueueFactories (final Lazy < BoundedQueueFactory > queueFactory ) {
51- this .queueFactory = queueFactory ;
51+ QueueFactories (final Supplier < QueueFactory > queueFactoryProvider ) {
52+ this .queueFactory = getOrReplaceQueueFactory ( queueFactoryProvider ) ;
5253 }
5354
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+ }
5664 }
5765
66+ @ Override
5867 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+ }
6081 }
6182
6283 /**
63- * Creates a {@link QueueFactory} producing queues of provided capacity from the provided supplier.
84+ * Creates a {@link QueueFactory} using the provided supplier.
6485 * <p>
6586 * A supplier path must be formatted as follows:
6687 * <ul>
@@ -70,10 +91,9 @@ public <E> Queue<E> create(final int capacity) {
7091 * </p>
7192 *
7293 * @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
7494 * @return a new {@link QueueFactory} instance
7595 */
76- public static QueueFactory createQueueFactory (final String supplierPath , final int capacity ) {
96+ public static QueueFactory ofSupplier (final String supplierPath ) {
7797 final int supplierPathSplitterIndex = supplierPath .lastIndexOf ('.' );
7898 if (supplierPathSplitterIndex < 0 ) {
7999 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
83103 final String supplierMethodName = supplierPath .substring (supplierPathSplitterIndex + 1 );
84104 try {
85105 final Class <?> supplierClass = LoaderUtil .loadClass (supplierClassName );
86- final BoundedQueueFactory queueFactory ;
87106 if ("new" .equals (supplierMethodName )) {
88107 final Constructor <?> supplierCtor = supplierClass .getDeclaredConstructor (int .class );
89- queueFactory = new ConstructorProvidedQueueFactory (supplierCtor );
108+ return new ConstructorProvidedQueueFactory (supplierCtor );
90109 } else {
91110 final Method supplierMethod = supplierClass .getMethod (supplierMethodName , int .class );
92- queueFactory = new StaticMethodProvidedQueueFactory (supplierMethod );
111+ return new StaticMethodProvidedQueueFactory (supplierMethod );
93112 }
94- return new ProxyQueueFactory (queueFactory , capacity );
95113 } catch (final ReflectiveOperationException | LinkageError | SecurityException error ) {
96114 final String message =
97115 String .format ("failed to create the queue factory using the supplier path `%s`" , supplierPath );
98116 throw new RuntimeException (message , error );
99117 }
100118 }
101119
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 {
164121
165122 private final Constructor <?> constructor ;
166123
@@ -179,7 +136,7 @@ public <E> Queue<E> create(final int capacity) {
179136 }
180137 }
181138
182- private static final class StaticMethodProvidedQueueFactory implements BoundedQueueFactory {
139+ private static final class StaticMethodProvidedQueueFactory implements QueueFactory {
183140
184141 private final Method method ;
185142
0 commit comments