/*
* 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);
}
}