FixAntenna/NetCore/Common/Pool/SynchronizedPoolableStack.cs (104 lines of code) (raw):
// Copyright (c) 2021 EPAM Systems
//
// Licensed 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.
using System;
using Epam.FixAntenna.NetCore.Common.Pool.Provider;
namespace Epam.FixAntenna.NetCore.Common.Pool
{
internal class SynchronizedPoolableStack<T> : IPool<T> where T : class
{
private readonly int _initSize;
private readonly int _maxSize;
private readonly IPoolableProvider<T> _poolableProvider;
private int _created;
private int _index;
private T[] _items;
private readonly object _sync = new object();
public SynchronizedPoolableStack(int initSize, int maxSize, IPoolableProvider<T> poolableProvider)
{
_initSize = initSize;
_maxSize = maxSize;
_poolableProvider = poolableProvider;
_items = new T[_initSize];
_index = -1;
_created = 0;
}
public T Object
{
get
{
T @object;
lock (_sync)
{
if (_index >= 0)
{
@object = _items[_index];
_items[_index--] = default;
_poolableProvider.Activate(@object);
}
else
{
@object = _poolableProvider.Create();
_created++;
}
}
return @object;
}
}
public virtual void ReturnObject(T @object)
{
if (@object == null)
{
return;
}
if (_poolableProvider.Validate(@object))
{
_poolableProvider.Passivate(@object);
var toDestroy = false;
lock (_sync)
{
if (_index == _items.Length - 1)
{
if (_maxSize == 0 || _items.Length < _maxSize)
{
var newLength = _maxSize == 0 ? _items.Length * 2 : Math.Min(_items.Length * 2, _maxSize);
Array.Resize(ref _items, newLength);
_items[++_index] = @object;
}
else
{
toDestroy = true;
}
}
else
{
_items[++_index] = @object;
}
}
if (toDestroy)
{
_poolableProvider.Destroy(@object);
}
}
else
{
_poolableProvider.Destroy(@object);
}
}
public virtual int ObjectsCreated => _created;
public virtual void Clean()
{
lock (_sync)
{
for (var i = 0; i < _items.Length; i++)
{
_items[i] = default;
}
_items = new T[_initSize];
_index = -1;
_created = 0;
}
}
public virtual string GetInfo()
{
return $"size: {_items.Length:D}; _index: {_index:D}; _created: {_created:D}";
}
}
}