mirror of
				https://github.com/Ryujinx/Ryujinx.git
				synced 2025-10-25 04:32:34 -07:00 
			
		
		
		
	* Added support for offline invalidation, via PPTC, of low cq translations replaced by high cq translations; both on a single run and between runs. Added invalidation of .cache files in the event of reuse on a different user operating system. Added .info and .cache files invalidation in case of a failed stream decompression. Nits. * InternalVersion = 1712; * Nits. * Address comment. * Get rid of BinaryFormatter. Nits. * Move Ptc.LoadTranslations(). Nits. * Nits. * Fixed corner cases (in case backup copies have to be used). Added save logs. * Not core fixes. * Complement to the previous commit. Added load logs. Removed BinaryFormatter leftovers. * Add LoadTranslations log. * Nits. * Removed the search and management of LowCq overlapping functions. * Final increment of .info and .cache flags. * Nit. * Free up memory allocated by Pools during any PPTC translations at boot time. * Nit due to rebase.
		
			
				
	
	
		
			124 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			124 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
| using System;
 | |
| using System.Collections.Concurrent;
 | |
| using System.Collections.Generic;
 | |
| using System.Threading;
 | |
| 
 | |
| namespace ARMeilleure.Common
 | |
| {
 | |
|     class ThreadStaticPool<T> where T : class, new()
 | |
|     {
 | |
|         private const int PoolSizeIncrement = 200;
 | |
| 
 | |
|         [ThreadStatic]
 | |
|         private static ThreadStaticPool<T> _instance;
 | |
| 
 | |
|         public static ThreadStaticPool<T> Instance
 | |
|         {
 | |
|             get
 | |
|             {
 | |
|                 if (_instance == null)
 | |
|                 {
 | |
|                     PreparePool(0); // So that we can still use a pool when blindly initializing one.
 | |
|                 }
 | |
| 
 | |
|                 return _instance;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         private static ConcurrentDictionary<int, Stack<ThreadStaticPool<T>>> _pools = new ConcurrentDictionary<int, Stack<ThreadStaticPool<T>>>();
 | |
| 
 | |
|         private static Stack<ThreadStaticPool<T>> GetPools(int groupId)
 | |
|         {
 | |
|             return _pools.GetOrAdd(groupId, x => new Stack<ThreadStaticPool<T>>());
 | |
|         }
 | |
| 
 | |
|         public static void PreparePool(int groupId)
 | |
|         {
 | |
|             // Prepare the pool for this thread, ideally using an existing one from the specified group.
 | |
| 
 | |
|             if (_instance == null)
 | |
|             {
 | |
|                 var pools = GetPools(groupId);
 | |
|                 lock (pools)
 | |
|                 {
 | |
|                     _instance = (pools.Count != 0) ? pools.Pop() : new ThreadStaticPool<T>(PoolSizeIncrement * 2);
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         public static void ReturnPool(int groupId)
 | |
|         {
 | |
|             // Reset and return the pool for this thread to the specified group.
 | |
| 
 | |
|             var pools = GetPools(groupId);
 | |
|             lock (pools)
 | |
|             {
 | |
|                 _instance.Clear();
 | |
|                 pools.Push(_instance);
 | |
| 
 | |
|                 _instance = null;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         public static void ResetPools()
 | |
|         {
 | |
|             // Resets any static references to the pools used by threads for each group, allowing them to be garbage collected.
 | |
| 
 | |
|             foreach (var pools in _pools.Values)
 | |
|             {
 | |
|                 pools.Clear();
 | |
|             }
 | |
| 
 | |
|             _pools.Clear();
 | |
|         }
 | |
| 
 | |
|         private T[] _pool;
 | |
|         private int _poolUsed = -1;
 | |
|         private int _poolSize;
 | |
| 
 | |
|         public ThreadStaticPool(int initialSize)
 | |
|         {
 | |
|             _pool = new T[initialSize];
 | |
| 
 | |
|             for (int i = 0; i < initialSize; i++)
 | |
|             {
 | |
|                 _pool[i] = new T();
 | |
|             }
 | |
| 
 | |
|             _poolSize = initialSize;
 | |
|         }
 | |
| 
 | |
|         public T Allocate()
 | |
|         {
 | |
|             int index = Interlocked.Increment(ref _poolUsed);
 | |
| 
 | |
|             if (index >= _poolSize)
 | |
|             {
 | |
|                 IncreaseSize();
 | |
|             }
 | |
| 
 | |
|             return _pool[index];
 | |
|         }
 | |
| 
 | |
|         private void IncreaseSize()
 | |
|         {
 | |
|             _poolSize += PoolSizeIncrement;
 | |
| 
 | |
|             T[] newArray = new T[_poolSize];
 | |
|             Array.Copy(_pool, 0, newArray, 0, _pool.Length);
 | |
| 
 | |
|             for (int i = _pool.Length; i < _poolSize; i++)
 | |
|             {
 | |
|                 newArray[i] = new T();
 | |
|             }
 | |
| 
 | |
|             Interlocked.Exchange(ref _pool, newArray);
 | |
|         }
 | |
| 
 | |
|         public void Clear()
 | |
|         {
 | |
|             _poolUsed = -1;
 | |
|         }
 | |
|     }
 | |
| }
 |