|
// 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
}
|