| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252 |
- using Ryujinx.Horizon.Common;
- using System;
- using System.Collections.Generic;
- using System.Threading;
- namespace Ryujinx.Horizon.Sdk.Sf.Cmif
- {
- class ServerDomainManager
- {
- private class EntryManager
- {
- public class Entry
- {
- public int Id { get; }
- public Domain Owner { get; set; }
- public ServiceObjectHolder Obj { get; set; }
- public LinkedListNode<Entry> Node { get; set; }
- public Entry(int id)
- {
- Id = id;
- }
- }
- private readonly LinkedList<Entry> _freeList;
- private readonly Entry[] _entries;
- public EntryManager(int count)
- {
- _freeList = [];
- _entries = new Entry[count];
- for (int i = 0; i < count; i++)
- {
- _freeList.AddLast(_entries[i] = new Entry(i + 1));
- }
- }
- public Entry AllocateEntry()
- {
- lock (_freeList)
- {
- if (_freeList.Count == 0)
- {
- return null;
- }
- Entry entry = _freeList.First.Value;
- _freeList.RemoveFirst();
- return entry;
- }
- }
- public void FreeEntry(Entry entry)
- {
- lock (_freeList)
- {
- DebugUtil.Assert(entry.Owner == null);
- DebugUtil.Assert(entry.Obj == null);
- _freeList.AddFirst(entry);
- }
- }
- public Entry GetEntry(int id)
- {
- if (id == 0)
- {
- return null;
- }
- int index = id - 1;
- if ((uint)index >= (uint)_entries.Length)
- {
- return null;
- }
- return _entries[index];
- }
- }
- private class Domain : DomainServiceObject, IDisposable
- {
- private readonly ServerDomainManager _manager;
- private readonly LinkedList<EntryManager.Entry> _entries;
- public Domain(ServerDomainManager manager)
- {
- _manager = manager;
- _entries = [];
- }
- public override ServiceObjectHolder GetObject(int id)
- {
- EntryManager.Entry entry = _manager._entryManager.GetEntry(id);
- if (entry == null)
- {
- return null;
- }
- lock (_manager._entryOwnerLock)
- {
- if (entry.Owner != this)
- {
- return null;
- }
- }
- return entry.Obj.Clone();
- }
- public override ServerDomainBase GetServerDomain()
- {
- return this;
- }
- public override void RegisterObject(int id, ServiceObjectHolder obj)
- {
- EntryManager.Entry entry = _manager._entryManager.GetEntry(id);
- DebugUtil.Assert(entry != null);
- lock (_manager._entryOwnerLock)
- {
- DebugUtil.Assert(entry.Owner == null);
- entry.Owner = this;
- entry.Node = _entries.AddLast(entry);
- }
- entry.Obj = obj;
- }
- public override Result ReserveIds(Span<int> outIds)
- {
- for (int i = 0; i < outIds.Length; i++)
- {
- EntryManager.Entry entry = _manager._entryManager.AllocateEntry();
- if (entry == null)
- {
- return SfResult.OutOfDomainEntries;
- }
- DebugUtil.Assert(entry.Owner == null);
- outIds[i] = entry.Id;
- }
- return Result.Success;
- }
- public override ServiceObjectHolder UnregisterObject(int id)
- {
- EntryManager.Entry entry = _manager._entryManager.GetEntry(id);
- if (entry == null)
- {
- return null;
- }
- ServiceObjectHolder obj;
- lock (_manager._entryOwnerLock)
- {
- if (entry.Owner != this)
- {
- return null;
- }
- entry.Owner = null;
- obj = entry.Obj;
- if (obj.ServiceObject is IDisposable disposableObj)
- {
- disposableObj.Dispose();
- }
- entry.Obj = null;
- _entries.Remove(entry.Node);
- entry.Node = null;
- }
- _manager._entryManager.FreeEntry(entry);
- return obj;
- }
- public override void UnreserveIds(ReadOnlySpan<int> ids)
- {
- for (int i = 0; i < ids.Length; i++)
- {
- EntryManager.Entry entry = _manager._entryManager.GetEntry(ids[i]);
- DebugUtil.Assert(entry != null);
- DebugUtil.Assert(entry.Owner == null);
- _manager._entryManager.FreeEntry(entry);
- }
- }
- public void Dispose()
- {
- foreach (EntryManager.Entry entry in _entries)
- {
- if (entry.Obj.ServiceObject is IDisposable disposableObj)
- {
- disposableObj.Dispose();
- }
- }
- _manager.FreeDomain(this);
- }
- }
- private readonly EntryManager _entryManager;
- private readonly Lock _entryOwnerLock = new();
- private readonly HashSet<Domain> _domains;
- private readonly int _maxDomains;
- public ServerDomainManager(int entryCount, int maxDomains)
- {
- _entryManager = new EntryManager(entryCount);
- _domains = [];
- _maxDomains = maxDomains;
- }
- public DomainServiceObject AllocateDomainServiceObject()
- {
- lock (_domains)
- {
- if (_domains.Count == _maxDomains)
- {
- return null;
- }
- Domain domain = new(this);
- _domains.Add(domain);
- return domain;
- }
- }
- public static void DestroyDomainServiceObject(DomainServiceObject obj)
- {
- ((Domain)obj).Dispose();
- }
- private void FreeDomain(Domain domain)
- {
- lock (_domains)
- {
- _domains.Remove(domain);
- }
- }
- }
- }
|