Make audio disposal thread safe on all 3 backends (#2527)

* Make audio disposal thread safe on all 3 backends

* Make OpenAL more consistent with the other backends

* Remove Window.Cursor = null, and change dummy TValue to byte
This commit is contained in:
gdkchan 2021-08-04 15:28:33 -03:00 committed by GitHub
parent 06cd3abe6c
commit a27986c311
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 45 additions and 115 deletions

View file

@ -3,7 +3,7 @@ using Ryujinx.Audio.Common;
using Ryujinx.Audio.Integration;
using Ryujinx.Memory;
using System;
using System.Collections.Generic;
using System.Collections.Concurrent;
using System.Linq;
using System.Threading;
using static Ryujinx.Audio.Integration.IHardwareDeviceDriver;
@ -12,11 +12,10 @@ namespace Ryujinx.Audio.Backends.OpenAL
{
public class OpenALHardwareDeviceDriver : IHardwareDeviceDriver
{
private object _lock = new object();
private ALDevice _device;
private ALContext _context;
private ManualResetEvent _updateRequiredEvent;
private List<OpenALHardwareDeviceSession> _sessions;
private readonly ALDevice _device;
private readonly ALContext _context;
private readonly ManualResetEvent _updateRequiredEvent;
private readonly ConcurrentDictionary<OpenALHardwareDeviceSession, byte> _sessions;
private bool _stillRunning;
private Thread _updaterThread;
@ -25,7 +24,7 @@ namespace Ryujinx.Audio.Backends.OpenAL
_device = ALC.OpenDevice("");
_context = ALC.CreateContext(_device, new ALContextAttributes());
_updateRequiredEvent = new ManualResetEvent(false);
_sessions = new List<OpenALHardwareDeviceSession>();
_sessions = new ConcurrentDictionary<OpenALHardwareDeviceSession, byte>();
_stillRunning = true;
_updaterThread = new Thread(Update)
@ -72,22 +71,16 @@ namespace Ryujinx.Audio.Backends.OpenAL
throw new ArgumentException($"{channelCount}");
}
lock (_lock)
{
OpenALHardwareDeviceSession session = new OpenALHardwareDeviceSession(this, memoryManager, sampleFormat, sampleRate, channelCount);
OpenALHardwareDeviceSession session = new OpenALHardwareDeviceSession(this, memoryManager, sampleFormat, sampleRate, channelCount);
_sessions.Add(session);
_sessions.TryAdd(session, 0);
return session;
}
return session;
}
internal void Unregister(OpenALHardwareDeviceSession session)
internal bool Unregister(OpenALHardwareDeviceSession session)
{
lock (_lock)
{
_sessions.Remove(session);
}
return _sessions.TryRemove(session, out _);
}
public ManualResetEvent GetUpdateRequiredEvent()
@ -103,14 +96,11 @@ namespace Ryujinx.Audio.Backends.OpenAL
{
bool updateRequired = false;
lock (_lock)
foreach (OpenALHardwareDeviceSession session in _sessions.Keys)
{
foreach (OpenALHardwareDeviceSession session in _sessions)
if (session.Update())
{
if (session.Update())
{
updateRequired = true;
}
updateRequired = true;
}
}
@ -135,26 +125,10 @@ namespace Ryujinx.Audio.Backends.OpenAL
{
_stillRunning = false;
int sessionCount = 0;
// NOTE: This is done in a way to avoid possible situations when the OpenALHardwareDeviceSession is already being dispose in another thread but doesn't hold the lock and tries to Unregister.
do
foreach (OpenALHardwareDeviceSession session in _sessions.Keys)
{
lock (_lock)
{
if (_sessions.Count == 0)
{
break;
}
OpenALHardwareDeviceSession session = _sessions[_sessions.Count - 1];
session.Dispose();
sessionCount = _sessions.Count;
}
session.Dispose();
}
while (sessionCount > 0);
ALC.DestroyContext(_context);
ALC.CloseDevice(_device);