Универсальный пул

15 ИЮНЯ 2022

------------------------------------------------------------------------

Наш телеграм-канал: t.me/@mailsgun_online

Youtube: youtube.com/@mailsgun_online

------------------------------------------------------------------------

У нас есть ArrayPool для переиспользования массивов. Работает это так: взяли массив определенной длинны что то с ним поделали и положили обратно. Нужно это для больших объектов которые по логике программы долго не должны храниться. В предыдущей статье описана эта проблема.

Так же могут понадобиться не только массивы, поэтому попробуем написать универсальный пул.

Нам понадобится хранилище для элементов ConcurrentBag и методы для создания и очистки элемента в хранилище.

    public sealed class Pool<T>
    {
        private ConcurrentBag<T> _items =
            new ConcurrentBag<T>();
        private readonly Func<T> _itemCreator = null;
        private readonly Action<T> _itemClearer = null;
        public Pool(Func<T> itemCreator)
        {
            _itemCreator = itemCreator ?? throw new ArgumentNullException("itemCreator");
        }
        public Pool(Func<T> itemCreator, Action<T> itemClearer) : this(itemCreator)
        {
            _itemClearer = itemClearer ?? throw new ArgumentNullException("itemClearer");
        }
        public T Rent()
        {
            if (_items.TryTake(out var item))
                return item;
            return _itemCreator();
        }
        public void Return(T item)
        {
            _itemClearer?.Invoke(item);
            _items.Add(item);
        }
        public int Count()
        {
            return _items.Count;
        }
    }

Метод Rent берет элемент или создает, а метод Return возвращает в ConcurrentBag, перед этим очистив его если это требуется.

Конструктор с одним параметром означает что элементы не будут очищаться.

Приведу пример для List:

       var bigListPool = new Pool<List<long>>(Creator, Clearer);
       List<long> list = null;
       try
       {
          list = bigListPool.Rent();
          //тут работа с list
       }
       finally
       {
         if (list != null)
             bigListPool.Return(list);
       }

Создание и очистка List:

        List<long> Creator() => new List<long>(1024 * 1024);
        void Clearer(List<long> l) => l.ForEach(i => i = 0);

Если список другого размера то надо создать еще один пул. Далее можно все это дело обернуть и внедрить синглтоном через ConfigureServices.

Проект

Теги:

Похожие публикации

Source: habr1

Ну и напоследок напоминаю вам о нашем новом проекте vkserfing bot.