1
0
Fork 0
libreoffice/net_ure/source/bridge/native/WeakIndexTable.cs
Daniel Baumann 8e63e14cf6
Adding upstream version 4:25.2.3.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
2025-06-22 16:20:04 +02:00

103 lines
3.2 KiB
C#

/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Threading;
namespace com.sun.star.uno.native
{
internal class WeakIndexTable
{
private readonly Dictionary<int, WeakReference<object>> _objectByIndex;
private readonly Dictionary<WeakReference<object>, int> _indexByObject;
private readonly List<int> _cleanupIndices;
private readonly object _lock;
private int _counter;
private int _updateOps;
public WeakIndexTable()
{
_objectByIndex = new Dictionary<int, WeakReference<object>>();
_indexByObject = new Dictionary<WeakReference<object>, int>(new WeakReferenceComparer());
_cleanupIndices = new List<int>();
_lock = new object();
_counter = 1; // index 0 is reserved for null
_updateOps = 0;
}
public object Lookup(int index)
{
if (index == 0)
return null;
if (_objectByIndex.TryGetValue(index, out WeakReference<object> weakRef))
if (weakRef.TryGetTarget(out object obj))
return obj;
throw new RuntimeException($"no object was found at index {index}", null);
}
public int Register(object obj)
{
if (obj == null)
return 0;
WeakReference<object> weakRef = new WeakReference<object>(obj);
if (_indexByObject.TryGetValue(weakRef, out int index))
return index;
lock (_lock)
{
_objectByIndex.Add(_counter, weakRef);
_indexByObject.Add(weakRef, _counter);
_updateOps++;
AutoClean();
return _counter++;
}
}
private void AutoClean()
{
if (_updateOps >= _objectByIndex.Count)
{
_updateOps = 0;
foreach (int key in _objectByIndex.Keys)
{
WeakReference<object> weakRef = _objectByIndex[key];
if (!weakRef.TryGetTarget(out _))
_cleanupIndices.Add(key);
}
foreach (int key in _cleanupIndices)
_objectByIndex.Remove(key);
_cleanupIndices.Clear();
}
}
private class WeakReferenceComparer : IEqualityComparer<WeakReference<object>>
{
public bool Equals(WeakReference<object> x, WeakReference<object> y)
{
if (x.TryGetTarget(out object first))
if (y.TryGetTarget(out object second))
return ReferenceEquals(first, second);
return false;
}
public int GetHashCode(WeakReference<object> obj)
=> obj.TryGetTarget(out object target) ? target.GetHashCode() : 0;
}
}
}