Skip to content

Commit 4b4c699

Browse files
committed
Cache constant CompletableFutures
Added static final instances of `CompletableFuture` completed with `null` and `false`. This is done to reduce object allocation.
1 parent 91f5f06 commit 4b4c699

File tree

12 files changed

+78
-53
lines changed

12 files changed

+78
-53
lines changed

driver/src/main/java/org/neo4j/driver/internal/ExplicitTransaction.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747

4848
import static java.util.Collections.emptyMap;
4949
import static java.util.concurrent.CompletableFuture.completedFuture;
50+
import static org.neo4j.driver.internal.util.Futures.completedWithNull;
5051
import static org.neo4j.driver.internal.util.Futures.failedFuture;
5152
import static org.neo4j.driver.v1.Values.value;
5253

@@ -163,7 +164,7 @@ else if ( state == State.ACTIVE || state == State.MARKED_FAILED || state == Stat
163164
}
164165
else
165166
{
166-
return completedFuture( null );
167+
return completedWithNull();
167168
}
168169
}
169170

@@ -172,7 +173,7 @@ public CompletionStage<Void> commitAsync()
172173
{
173174
if ( state == State.COMMITTED )
174175
{
175-
return completedFuture( null );
176+
return completedWithNull();
176177
}
177178
else if ( state == State.ROLLED_BACK )
178179
{
@@ -200,13 +201,13 @@ public CompletionStage<Void> rollbackAsync()
200201
}
201202
else if ( state == State.ROLLED_BACK )
202203
{
203-
return completedFuture( null );
204+
return completedWithNull();
204205
}
205206
else if ( state == State.TERMINATED )
206207
{
207208
// transaction has been terminated by RESET and should be rolled back by the database
208209
state = State.ROLLED_BACK;
209-
return completedFuture( null );
210+
return completedWithNull();
210211
}
211212
else
212213
{

driver/src/main/java/org/neo4j/driver/internal/InternalDriver.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
import org.neo4j.driver.v1.Logging;
3030
import org.neo4j.driver.v1.Session;
3131

32-
import static java.util.concurrent.CompletableFuture.completedFuture;
32+
import static org.neo4j.driver.internal.util.Futures.completedWithNull;
3333

3434
public class InternalDriver implements Driver
3535
{
@@ -116,7 +116,7 @@ public CompletionStage<Void> closeAsync()
116116
log.info( "Closing driver instance %s", this );
117117
return sessionFactory.close();
118118
}
119-
return completedFuture( null );
119+
return completedWithNull();
120120
}
121121

122122
public CompletionStage<Void> verifyConnectivity()

driver/src/main/java/org/neo4j/driver/internal/NetworkSession.java

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,8 @@
4646
import org.neo4j.driver.v1.exceptions.ClientException;
4747
import org.neo4j.driver.v1.types.TypeSystem;
4848

49-
import static java.util.concurrent.CompletableFuture.completedFuture;
49+
import static org.neo4j.driver.internal.util.Futures.completedWithFalse;
50+
import static org.neo4j.driver.internal.util.Futures.completedWithNull;
5051
import static org.neo4j.driver.internal.util.Futures.failedFuture;
5152
import static org.neo4j.driver.v1.Values.value;
5253

@@ -60,9 +61,9 @@ public class NetworkSession implements Session
6061
protected final Logger logger;
6162

6263
private volatile Bookmark bookmark = Bookmark.empty();
63-
private volatile CompletionStage<ExplicitTransaction> transactionStage = completedFuture( null );
64-
private volatile CompletionStage<Connection> connectionStage = completedFuture( null );
65-
private volatile CompletionStage<InternalStatementResultCursor> resultCursorStage = completedFuture( null );
64+
private volatile CompletionStage<ExplicitTransaction> transactionStage = completedWithNull();
65+
private volatile CompletionStage<Connection> connectionStage = completedWithNull();
66+
private volatile CompletionStage<InternalStatementResultCursor> resultCursorStage = completedWithNull();
6667

6768
private final AtomicBoolean open = new AtomicBoolean( true );
6869

@@ -168,7 +169,7 @@ public CompletionStage<Void> closeAsync()
168169
{
169170
if ( cursor == null )
170171
{
171-
return completedFuture( null );
172+
return completedWithNull();
172173
}
173174
return cursor.failureAsync();
174175
} ).thenCompose( error -> releaseResources().thenApply( ignore ->
@@ -186,7 +187,7 @@ public CompletionStage<Void> closeAsync()
186187
}
187188
} ) );
188189
}
189-
return completedFuture( null );
190+
return completedWithNull();
190191
}
191192

192193
@Override
@@ -276,7 +277,7 @@ CompletionStage<Boolean> currentConnectionIsOpen()
276277
{
277278
if ( connectionStage == null )
278279
{
279-
return completedFuture( false );
280+
return completedWithFalse();
280281
}
281282
return connectionStage.handle( ( connection, error ) ->
282283
error == null && // no acquisition error
@@ -363,7 +364,7 @@ private <T> CompletionStage<T> safeExecuteWork( ExplicitTransaction tx, Transact
363364
CompletionStage<T> result = work.execute( tx );
364365

365366
// protect from given transaction function returning null
366-
return result == null ? completedFuture( null ) : result;
367+
return result == null ? completedWithNull() : result;
367368
}
368369
catch ( Throwable workError )
369370
{
@@ -459,7 +460,7 @@ private CompletionStage<Connection> acquireConnection( AccessMode mode )
459460
{
460461
if ( cursor == null )
461462
{
462-
return completedFuture( null );
463+
return completedWithNull();
463464
}
464465
// make sure previous result is fully consumed and connection is released back to the pool
465466
return cursor.failureAsync();
@@ -508,7 +509,7 @@ private CompletionStage<Void> rollbackTransaction()
508509
{
509510
return tx.rollbackAsync();
510511
}
511-
return completedFuture( null );
512+
return completedWithNull();
512513
} ).exceptionally( error ->
513514
{
514515
Throwable cause = Futures.completionExceptionCause( error );
@@ -525,7 +526,7 @@ private CompletionStage<Void> releaseConnection()
525526
{
526527
return connection.release();
527528
}
528-
return completedFuture( null );
529+
return completedWithNull();
529530
} );
530531
}
531532

driver/src/main/java/org/neo4j/driver/internal/async/ResultCursorsHolder.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import org.neo4j.driver.internal.InternalStatementResultCursor;
2727

2828
import static java.util.concurrent.CompletableFuture.completedFuture;
29+
import static org.neo4j.driver.internal.util.Futures.completedWithNull;
2930

3031
public class ResultCursorsHolder
3132
{
@@ -41,14 +42,14 @@ public CompletionStage<Throwable> retrieveNotConsumedError()
4142
{
4243
return cursorStages.stream()
4344
.map( this::retrieveFailure )
44-
.reduce( completedFuture( null ), this::nonNullFailureFromEither );
45+
.reduce( completedWithNull(), this::nonNullFailureFromEither );
4546
}
4647

4748
private CompletionStage<Throwable> retrieveFailure( CompletionStage<InternalStatementResultCursor> cursorStage )
4849
{
4950
return cursorStage
5051
.exceptionally( cursor -> null )
51-
.thenCompose( cursor -> cursor == null ? completedFuture( null ) : cursor.failureAsync() );
52+
.thenCompose( cursor -> cursor == null ? completedWithNull() : cursor.failureAsync() );
5253
}
5354

5455
private CompletionStage<Throwable> nonNullFailureFromEither( CompletionStage<Throwable> stage1,

driver/src/main/java/org/neo4j/driver/internal/cluster/Rediscovery.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838

3939
import static java.lang.String.format;
4040
import static java.util.concurrent.CompletableFuture.completedFuture;
41+
import static org.neo4j.driver.internal.util.Futures.completedWithNull;
4142

4243
public class Rediscovery
4344
{
@@ -178,7 +179,7 @@ private CompletionStage<ClusterComposition> lookupOnKnownRouters( RoutingTable r
178179
{
179180
BoltServerAddress[] addresses = routingTable.routers().toArray();
180181

181-
CompletableFuture<ClusterComposition> result = completedFuture( null );
182+
CompletableFuture<ClusterComposition> result = completedWithNull();
182183
for ( BoltServerAddress address : addresses )
183184
{
184185
result = result.thenCompose( composition ->
@@ -203,7 +204,7 @@ private CompletionStage<ClusterComposition> lookupOnInitialRouter( RoutingTable
203204
Set<BoltServerAddress> addresses = hostNameResolver.resolve( initialRouter );
204205
addresses.removeAll( seenServers );
205206

206-
CompletableFuture<ClusterComposition> result = completedFuture( null );
207+
CompletableFuture<ClusterComposition> result = completedWithNull();
207208
for ( BoltServerAddress address : addresses )
208209
{
209210
result = result.thenCompose( composition ->

driver/src/main/java/org/neo4j/driver/internal/handlers/PullAllResponseHandler.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
import static java.util.Collections.emptyMap;
3737
import static java.util.Objects.requireNonNull;
3838
import static java.util.concurrent.CompletableFuture.completedFuture;
39+
import static org.neo4j.driver.internal.util.Futures.completedWithNull;
3940
import static org.neo4j.driver.internal.util.Futures.failedFuture;
4041

4142
public abstract class PullAllResponseHandler implements ResponseHandler
@@ -136,7 +137,7 @@ public synchronized CompletionStage<Record> peekAsync()
136137

137138
if ( finished )
138139
{
139-
return completedFuture( null );
140+
return completedWithNull();
140141
}
141142

142143
if ( recordFuture == null )
@@ -188,7 +189,7 @@ public synchronized CompletionStage<Throwable> failureAsync()
188189
}
189190
else if ( finished )
190191
{
191-
return completedFuture( null );
192+
return completedWithNull();
192193
}
193194
else
194195
{

driver/src/main/java/org/neo4j/driver/internal/util/Futures.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,28 @@
3030

3131
import org.neo4j.driver.internal.async.EventLoopGroupFactory;
3232

33+
import static java.util.concurrent.CompletableFuture.completedFuture;
34+
3335
public final class Futures
3436
{
37+
private static final CompletableFuture<?> COMPLETED_WITH_NULL = completedFuture( null );
38+
private static final CompletableFuture<Boolean> COMPLETED_WITH_FALSE = completedFuture( false );
39+
3540
private Futures()
3641
{
3742
}
3843

44+
@SuppressWarnings( "unchecked" )
45+
public static <T> CompletableFuture<T> completedWithNull()
46+
{
47+
return (CompletableFuture) COMPLETED_WITH_NULL;
48+
}
49+
50+
public static CompletableFuture<Boolean> completedWithFalse()
51+
{
52+
return COMPLETED_WITH_FALSE;
53+
}
54+
3955
public static <T> CompletionStage<T> asCompletionStage( io.netty.util.concurrent.Future<T> future )
4056
{
4157
CompletableFuture<T> result = new CompletableFuture<>();

driver/src/test/java/org/neo4j/driver/internal/DriverFactoryTest.java

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@
5656
import static org.mockito.Mockito.mock;
5757
import static org.mockito.Mockito.verify;
5858
import static org.mockito.Mockito.when;
59+
import static org.neo4j.driver.internal.util.Futures.completedWithNull;
5960
import static org.neo4j.driver.internal.util.Futures.failedFuture;
6061
import static org.neo4j.driver.v1.AccessMode.READ;
6162
import static org.neo4j.driver.v1.Config.defaultConfig;
@@ -143,8 +144,8 @@ public void usesLeakLoggingSessionFactoryWhenConfigured()
143144
public void shouldVerifyConnectivity()
144145
{
145146
SessionFactory sessionFactory = mock( SessionFactory.class );
146-
when( sessionFactory.verifyConnectivity() ).thenReturn( completedFuture( null ) );
147-
when( sessionFactory.close() ).thenReturn( completedFuture( null ) );
147+
when( sessionFactory.verifyConnectivity() ).thenReturn( completedWithNull() );
148+
when( sessionFactory.close() ).thenReturn( completedWithNull() );
148149
DriverFactoryWithSessions driverFactory = new DriverFactoryWithSessions( sessionFactory );
149150

150151
try ( Driver driver = createDriver( driverFactory ) )
@@ -160,7 +161,7 @@ public void shouldThrowWhenUnableToVerifyConnectivity()
160161
SessionFactory sessionFactory = mock( SessionFactory.class );
161162
ServiceUnavailableException error = new ServiceUnavailableException( "Hello" );
162163
when( sessionFactory.verifyConnectivity() ).thenReturn( failedFuture( error ) );
163-
when( sessionFactory.close() ).thenReturn( completedFuture( null ) );
164+
when( sessionFactory.close() ).thenReturn( completedWithNull() );
164165
DriverFactoryWithSessions driverFactory = new DriverFactoryWithSessions( sessionFactory );
165166

166167
try
@@ -191,7 +192,7 @@ private static ConnectionPool connectionPoolMock()
191192
ConnectionPool pool = mock( ConnectionPool.class );
192193
Connection connection = mock( Connection.class );
193194
when( pool.acquire( any( BoltServerAddress.class ) ) ).thenReturn( completedFuture( connection ) );
194-
when( pool.close() ).thenReturn( completedFuture( null ) );
195+
when( pool.close() ).thenReturn( completedWithNull() );
195196
return pool;
196197
}
197198

@@ -234,7 +235,7 @@ private static class SessionFactoryCapturingDriverFactory extends DriverFactory
234235
protected InternalDriver createDriver( SessionFactory sessionFactory, SecurityPlan securityPlan, Config config )
235236
{
236237
InternalDriver driver = mock( InternalDriver.class );
237-
when( driver.verifyConnectivity() ).thenReturn( completedFuture( null ) );
238+
when( driver.verifyConnectivity() ).thenReturn( completedWithNull() );
238239
return driver;
239240
}
240241

driver/src/test/java/org/neo4j/driver/internal/InternalDriverTest.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,13 @@
2424

2525
import org.neo4j.driver.internal.security.SecurityPlan;
2626

27-
import static java.util.concurrent.CompletableFuture.completedFuture;
2827
import static org.junit.Assert.assertEquals;
2928
import static org.junit.Assert.assertNull;
3029
import static org.mockito.Mockito.mock;
3130
import static org.mockito.Mockito.verify;
3231
import static org.mockito.Mockito.when;
3332
import static org.neo4j.driver.internal.logging.DevNullLogging.DEV_NULL_LOGGING;
33+
import static org.neo4j.driver.internal.util.Futures.completedWithNull;
3434
import static org.neo4j.driver.v1.util.TestUtil.await;
3535

3636
public class InternalDriverTest
@@ -62,7 +62,7 @@ public void shouldNotCloseSessionFactoryMultipleTimes()
6262
public void shouldVerifyConnectivity()
6363
{
6464
SessionFactory sessionFactory = sessionFactoryMock();
65-
CompletableFuture<Void> connectivityStage = completedFuture( null );
65+
CompletableFuture<Void> connectivityStage = completedWithNull();
6666
when( sessionFactory.verifyConnectivity() ).thenReturn( connectivityStage );
6767

6868
InternalDriver driver = newDriver( sessionFactory );
@@ -78,7 +78,7 @@ private static InternalDriver newDriver( SessionFactory sessionFactory )
7878
private static SessionFactory sessionFactoryMock()
7979
{
8080
SessionFactory sessionFactory = mock( SessionFactory.class );
81-
when( sessionFactory.close() ).thenReturn( completedFuture( null ) );
81+
when( sessionFactory.close() ).thenReturn( completedWithNull() );
8282
return sessionFactory;
8383
}
8484
}

0 commit comments

Comments
 (0)