File: src\Workspaces\SharedUtilitiesAndExtensions\Compiler\Core\ObjectPools\PooledObject.cs
Web Access
Project: src\src\CodeStyle\Core\Analyzers\Microsoft.CodeAnalysis.CodeStyle.csproj (Microsoft.CodeAnalysis.CodeStyle)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
 
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.CodeAnalysis.Collections;
using Microsoft.CodeAnalysis.PooledObjects;
using Roslyn.Utilities;
 
namespace Microsoft.CodeAnalysis;
 
/// <summary>
/// this is RAII object to automatically release pooled object when its owning pool
/// </summary>
internal struct PooledObject<T> : IDisposable where T : class
{
    private readonly Action<ObjectPool<T>, T> _releaser;
    private readonly ObjectPool<T> _pool;
 
    public PooledObject(ObjectPool<T> pool, Func<ObjectPool<T>, T> allocator, Action<ObjectPool<T>, T> releaser) : this()
    {
        _pool = pool;
        Object = allocator(pool);
        _releaser = releaser;
    }
 
    public T Object { get; private set; }
 
    public void Dispose()
    {
        if (Object != null)
        {
            _releaser(_pool, Object);
            Object = null!;
        }
    }
 
    #region factory
    public static PooledObject<StringBuilder> Create(ObjectPool<StringBuilder> pool)
    {
        return new PooledObject<StringBuilder>(
            pool,
            static p => Allocator(p),
            static (p, v) => Releaser(p, v));
    }
 
    public static PooledObject<Stack<TItem>> Create<TItem>(ObjectPool<Stack<TItem>> pool)
    {
        return new PooledObject<Stack<TItem>>(
            pool,
            static p => Allocator(p),
            static (p, v) => Releaser(p, v));
    }
 
    public static PooledObject<Queue<TItem>> Create<TItem>(ObjectPool<Queue<TItem>> pool)
    {
        return new PooledObject<Queue<TItem>>(
            pool,
            static p => Allocator(p),
            static (p, v) => Releaser(p, v));
    }
 
    public static PooledObject<HashSet<TItem>> Create<TItem>(ObjectPool<HashSet<TItem>> pool)
    {
        return new PooledObject<HashSet<TItem>>(
            pool,
            static p => Allocator(p),
            static (p, v) => Releaser(p, v));
    }
 
    public static PooledObject<ConcurrentSet<TItem>> Create<TItem>(ObjectPool<ConcurrentSet<TItem>> pool) where TItem : notnull
    {
        return new PooledObject<ConcurrentSet<TItem>>(
            pool,
            static p => Allocator(p),
            static (p, v) => Releaser(p, v));
    }
 
    public static PooledObject<Dictionary<TKey, TValue>> Create<TKey, TValue>(ObjectPool<Dictionary<TKey, TValue>> pool)
        where TKey : notnull
    {
        return new PooledObject<Dictionary<TKey, TValue>>(
            pool,
            static p => Allocator(p),
            static (p, v) => Releaser(p, v));
    }
 
    public static PooledObject<List<TItem>> Create<TItem>(ObjectPool<List<TItem>> pool)
    {
        return new PooledObject<List<TItem>>(
            pool,
            static p => Allocator(p),
            static (p, v) => Releaser(p, v));
    }
 
    public static PooledObject<SegmentedList<TItem>> Create<TItem>(ObjectPool<SegmentedList<TItem>> pool)
    {
        return new PooledObject<SegmentedList<TItem>>(
            pool,
            static p => Allocator(p),
            static (p, v) => Releaser(p, v));
    }
 
    #endregion
 
    #region allocators and releasers
    private static StringBuilder Allocator(ObjectPool<StringBuilder> pool)
        => pool.AllocateAndClear();
 
    private static void Releaser(ObjectPool<StringBuilder> pool, StringBuilder sb)
        => pool.ClearAndFree(sb);
 
    private static Stack<TItem> Allocator<TItem>(ObjectPool<Stack<TItem>> pool)
        => pool.AllocateAndClear();
 
    private static void Releaser<TItem>(ObjectPool<Stack<TItem>> pool, Stack<TItem> obj)
        => pool.ClearAndFree(obj);
 
    private static Queue<TItem> Allocator<TItem>(ObjectPool<Queue<TItem>> pool)
        => pool.AllocateAndClear();
 
    private static void Releaser<TItem>(ObjectPool<Queue<TItem>> pool, Queue<TItem> obj)
        => pool.ClearAndFree(obj);
 
    private static HashSet<TItem> Allocator<TItem>(ObjectPool<HashSet<TItem>> pool)
        => pool.AllocateAndClear();
 
    private static ConcurrentSet<TItem> Allocator<TItem>(ObjectPool<ConcurrentSet<TItem>> pool) where TItem : notnull
        => pool.AllocateAndClear();
 
    private static void Releaser<TItem>(ObjectPool<HashSet<TItem>> pool, HashSet<TItem> obj)
        => pool.ClearAndFree(obj);
 
    private static void Releaser<TItem>(ObjectPool<ConcurrentSet<TItem>> pool, ConcurrentSet<TItem> obj) where TItem : notnull
        => pool.ClearAndFree(obj);
 
    private static Dictionary<TKey, TValue> Allocator<TKey, TValue>(ObjectPool<Dictionary<TKey, TValue>> pool)
        where TKey : notnull
        => pool.AllocateAndClear();
 
    private static void Releaser<TKey, TValue>(ObjectPool<Dictionary<TKey, TValue>> pool, Dictionary<TKey, TValue> obj)
        where TKey : notnull
        => pool.ClearAndFree(obj);
 
    private static List<TItem> Allocator<TItem>(ObjectPool<List<TItem>> pool)
        => pool.AllocateAndClear();
 
    private static void Releaser<TItem>(ObjectPool<List<TItem>> pool, List<TItem> obj)
        => pool.ClearAndFree(obj, pool.TrimOnFree);
 
    private static SegmentedList<TItem> Allocator<TItem>(ObjectPool<SegmentedList<TItem>> pool)
        => pool.AllocateAndClear();
 
    private static void Releaser<TItem>(ObjectPool<SegmentedList<TItem>> pool, SegmentedList<TItem> obj)
        => pool.ClearAndFree(obj, pool.TrimOnFree);
    #endregion
}