123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123 |
- using System;
- using System.Collections.Concurrent;
- using System.Collections.Generic;
- using System.Runtime.CompilerServices;
- using System.Runtime.InteropServices;
- using System.Threading;
- namespace Cysharp.Threading.Tasks
- {
- // internally used but public, allow to user create custom operator with pooling.
- public static class TaskPool
- {
- internal static int MaxPoolSize;
- // avoid to use ConcurrentDictionary for safety of WebGL build.
- static Dictionary<Type, Func<int>> sizes = new Dictionary<Type, Func<int>>();
- static TaskPool()
- {
- try
- {
- var value = Environment.GetEnvironmentVariable("UNITASK_MAX_POOLSIZE");
- if (value != null)
- {
- if (int.TryParse(value, out var size))
- {
- MaxPoolSize = size;
- return;
- }
- }
- }
- catch { }
- MaxPoolSize = int.MaxValue;
- }
- public static void SetMaxPoolSize(int maxPoolSize)
- {
- MaxPoolSize = maxPoolSize;
- }
- public static IEnumerable<(Type, int)> GetCacheSizeInfo()
- {
- lock (sizes)
- {
- foreach (var item in sizes)
- {
- yield return (item.Key, item.Value());
- }
- }
- }
- public static void RegisterSizeGetter(Type type, Func<int> getSize)
- {
- lock (sizes)
- {
- sizes[type] = getSize;
- }
- }
- }
- public interface ITaskPoolNode<T>
- {
- ref T NextNode { get; }
- }
- // mutable struct, don't mark readonly.
- [StructLayout(LayoutKind.Auto)]
- public struct TaskPool<T>
- where T : class, ITaskPoolNode<T>
- {
- int gate;
- int size;
- T root;
- public int Size => size;
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public bool TryPop(out T result)
- {
- if (Interlocked.CompareExchange(ref gate, 1, 0) == 0)
- {
- var v = root;
- if (!(v is null))
- {
- ref var nextNode = ref v.NextNode;
- root = nextNode;
- nextNode = null;
- size--;
- result = v;
- Volatile.Write(ref gate, 0);
- return true;
- }
- Volatile.Write(ref gate, 0);
- }
- result = default;
- return false;
- }
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public bool TryPush(T item)
- {
- if (Interlocked.CompareExchange(ref gate, 1, 0) == 0)
- {
- if (size < TaskPool.MaxPoolSize)
- {
- item.NextNode = root;
- root = item;
- size++;
- Volatile.Write(ref gate, 0);
- return true;
- }
- else
- {
- Volatile.Write(ref gate, 0);
- }
- }
- return false;
- }
- }
- }
|