/* * Copyright (c) Meta Platforms, Inc. and affiliates. * All rights reserved. * * Licensed under the Oculus SDK License Agreement (the "License"); * you may not use the Oculus SDK except in compliance with the License, * which is provided at the time of installation or download, or which * otherwise accompanies this software in either electronic or hard copy form. * * You may obtain a copy of the License at * * https://developer.oculus.com/licenses/oculussdk/ * * Unless required by applicable law or agreed to in writing, the Oculus SDK * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ using System; using System.Collections; using System.Collections.Generic; /// /// Helper class to handle generic class object pools and avoid allocations in the SDK that would lead to garbage collection. /// internal static class OVRObjectPool { private static class Storage where T : class, new() { public static readonly HashSet HashSet = new HashSet(); } /// /// Gets an object of type T from it's respective pool. If none is available a new one is created. /// /// Object of type T public static T Get() where T : class, new() { using var enumerator = Storage.HashSet.GetEnumerator(); if (!enumerator.MoveNext()) return new T(); var item = enumerator.Current; Storage.HashSet.Remove(item); if (item is IList list) list.Clear(); else if (item is IDictionary dict) dict.Clear(); return item; } public static List List() => Get>(); public static Dictionary Dictionary() => Get>(); public static HashSet HashSet() { var item = Get>(); item.Clear(); return item; } public static Stack Stack() { var item = Get>(); item.Clear(); return item; } public static Queue Queue() { var item = Get>(); item.Clear(); return item; } /// /// Returns an object of type T to it's respective pool. If the object is null or already present in the pool no changes are made. /// /// /// After returning an object to the object pool using it is not allowed and leads to undefined behaviour, please another object from the pool instead. /// public static void Return(T obj) where T : class, new() { switch (obj) { case null: return; case IList list: list.Clear(); break; case IDictionary dict: dict.Clear(); break; } Storage.HashSet.Add(obj); } public static void Return(HashSet set) { set?.Clear(); Return>(set); } public static void Return(Stack stack) { stack?.Clear(); Return>(stack); } public static void Return(Queue queue) { queue?.Clear(); Return>(queue); } public struct ListScope : IDisposable { List _list; public ListScope(out List list) => _list = list = List(); public void Dispose() => Return(_list); } public readonly struct DictionaryScope : IDisposable { readonly Dictionary _dictionary; public DictionaryScope(out Dictionary dictionary) => _dictionary = dictionary = Dictionary(); public void Dispose() => Return(_dictionary); } public readonly struct HashSetScope : IDisposable { readonly HashSet _set; public HashSetScope(out HashSet set) => _set = set = HashSet(); public void Dispose() => Return(_set); } public readonly struct StackScope : IDisposable { readonly Stack _stack; public StackScope(out Stack stack) => _stack = stack = Stack(); public void Dispose() => Return(_stack); } public readonly struct QueueScope : IDisposable { readonly Queue _queue; public QueueScope(out Queue queue) => _queue = queue = Queue(); public void Dispose() => Return(_queue); } public readonly struct ItemScope : IDisposable where T : class, new() { readonly T _item; public ItemScope(out T item) => _item = item = Get(); public void Dispose() => Return(_item); } }