This is an automated email from the ASF dual-hosted git repository. florianhockmann pushed a commit to branch TINKERPOP-2135 in repository https://gitbox.apache.org/repos/asf/tinkerpop.git
commit eb137abced0103ed966e073da9da6f9223956c61 Author: Florian Hockmann <[email protected]> AuthorDate: Sun Mar 3 12:33:22 2019 +0100 TINKERPOP-2135 Wrap ConcurrentDictionary A dedicated ConcurrentConnectionCollection is used to wrap ConcurrentDictionary as we don't really need a dictionary in ConnectionPool. Using the dictionary there directly leads to strange looking API calls that could be distracting. Our own collection class provides exactly the API we need. --- .../Driver/ConcurrentConnectionCollection.cs | 51 ++++++++++++++++++++++ .../src/Gremlin.Net/Driver/ConnectionPool.cs | 13 +++--- 2 files changed, 57 insertions(+), 7 deletions(-) diff --git a/gremlin-dotnet/src/Gremlin.Net/Driver/ConcurrentConnectionCollection.cs b/gremlin-dotnet/src/Gremlin.Net/Driver/ConcurrentConnectionCollection.cs new file mode 100644 index 0000000..c68e0e9 --- /dev/null +++ b/gremlin-dotnet/src/Gremlin.Net/Driver/ConcurrentConnectionCollection.cs @@ -0,0 +1,51 @@ +#region License + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#endregion + +using System.Collections; +using System.Collections.Concurrent; +using System.Collections.Generic; + +namespace Gremlin.Net.Driver +{ + internal class ConcurrentConnectionCollection : IEnumerable<Connection> + { + private const int DefaultValue = 0; + + // We use a ConcurrentDictionary because we need a concurrent collection with a TryRemove() method. + // Only the keys are used here, the values just contain a dummy DefaultValue. + private readonly ConcurrentDictionary<Connection, int> _connections = + new ConcurrentDictionary<Connection, int>(); + + public int Count => _connections.Count; + + public bool IsEmpty => _connections.IsEmpty; + + public void Add(Connection connection) => _connections.TryAdd(connection, DefaultValue); + + public bool TryRemove(Connection connection) => _connections.TryRemove(connection, out _); + + public IEnumerator<Connection> GetEnumerator() => _connections.Keys.GetEnumerator(); + + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + } +} \ No newline at end of file diff --git a/gremlin-dotnet/src/Gremlin.Net/Driver/ConnectionPool.cs b/gremlin-dotnet/src/Gremlin.Net/Driver/ConnectionPool.cs index 40aa99b..130d6fd 100644 --- a/gremlin-dotnet/src/Gremlin.Net/Driver/ConnectionPool.cs +++ b/gremlin-dotnet/src/Gremlin.Net/Driver/ConnectionPool.cs @@ -34,8 +34,7 @@ namespace Gremlin.Net.Driver internal class ConnectionPool : IDisposable { private readonly ConnectionFactory _connectionFactory; - private readonly ConcurrentDictionary<Connection, object> _connections = - new ConcurrentDictionary<Connection, object>(); + private readonly ConcurrentConnectionCollection _connections = new ConcurrentConnectionCollection(); private readonly int _poolSize; private readonly int _maxInProcessPerConnection; private int _poolState; @@ -90,7 +89,7 @@ namespace Gremlin.Net.Driver var createdConnections = await Task.WhenAll(connectionCreationTasks).ConfigureAwait(false); foreach (var c in createdConnections) { - _connections.TryAdd(c, null); + _connections.Add(c); } } @@ -120,7 +119,7 @@ namespace Gremlin.Net.Driver var nrMinInFlightConnections = int.MaxValue; Connection leastBusy = null; - foreach (var connection in _connections.Keys) + foreach (var connection in _connections) { var nrInFlight = connection.NrRequestsInFlight; if (nrInFlight >= nrMinInFlightConnections) continue; @@ -138,7 +137,7 @@ namespace Gremlin.Net.Driver private void RemoveConnectionFromPool(Connection connection) { - if (_connections.TryRemove(connection, out _)) + if (_connections.TryRemove(connection)) DefinitelyDestroyConnection(connection); } @@ -160,9 +159,9 @@ namespace Gremlin.Net.Driver private async Task CloseAndRemoveAllConnectionsAsync() { - foreach (var connection in _connections.Keys) + foreach (var connection in _connections) { - _connections.TryRemove(connection, out _); + _connections.TryRemove(connection); await connection.CloseAsync().ConfigureAwait(false); DefinitelyDestroyConnection(connection); }
