mirror of
https://github.com/Thealexbarney/LibHac.git
synced 2024-11-14 10:49:41 +01:00
Add a SharedLock struct
This commit is contained in:
parent
c11a1f4eca
commit
2e04bcad94
4 changed files with 250 additions and 7 deletions
|
@ -9,9 +9,9 @@ public static class ReaderWriterLockApi
|
|||
public static void InitializeReaderWriterLock(this OsState os, ref ReaderWriterLockType rwLock)
|
||||
{
|
||||
// Create objects.
|
||||
ReaderWriterLockImpl.GetLockCount(ref rwLock).Cs.Initialize();
|
||||
rwLock.CvReadLockWaiter.Initialize();
|
||||
rwLock.CvWriteLockWaiter.Initialize();
|
||||
ReaderWriterLockImpl.GetLockCount(ref rwLock).Cs = new InternalCriticalSection();
|
||||
rwLock.CvReadLockWaiter = new InternalConditionVariable();
|
||||
rwLock.CvWriteLockWaiter = new InternalConditionVariable();
|
||||
|
||||
// Set member variables.
|
||||
ReaderWriterLockImpl.ClearReadLockCount(ref ReaderWriterLockImpl.GetLockCount(ref rwLock));
|
||||
|
|
|
@ -12,6 +12,7 @@ public static class ScopedLock
|
|||
}
|
||||
}
|
||||
|
||||
[NonCopyableDisposable]
|
||||
public ref struct ScopedLock<TMutex> where TMutex : IBasicLockable
|
||||
{
|
||||
private Ref<TMutex> _mutex;
|
||||
|
|
223
src/LibHac/Os/SharedLock.cs
Normal file
223
src/LibHac/Os/SharedLock.cs
Normal file
|
@ -0,0 +1,223 @@
|
|||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Threading;
|
||||
using LibHac.Common;
|
||||
|
||||
namespace LibHac.Os;
|
||||
|
||||
public static class SharedLock
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static SharedLockRef<TMutex> Lock<TMutex>(ref TMutex lockable) where TMutex : struct, ISharedMutex
|
||||
{
|
||||
return new SharedLockRef<TMutex>(ref lockable);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static SharedLock<TMutex> Lock<TMutex>(TMutex lockable) where TMutex : class, ISharedMutex
|
||||
{
|
||||
return new SharedLock<TMutex>(lockable);
|
||||
}
|
||||
|
||||
#pragma warning disable LH0001 // DoNotCopyValue
|
||||
#pragma warning disable CS8500 // This takes the address of, gets the size of, or declares a pointer to a managed type
|
||||
public static unsafe ref SharedLockRef<T> Ref<T>(this scoped in SharedLockRef<T> value) where T : struct, ISharedMutex
|
||||
{
|
||||
fixed (SharedLockRef<T>* p = &value)
|
||||
{
|
||||
return ref *p;
|
||||
}
|
||||
}
|
||||
#pragma warning restore CS8500 // This takes the address of, gets the size of, or declares a pointer to a managed type
|
||||
#pragma warning restore LH0001 // DoNotCopyValue
|
||||
|
||||
public static ref SharedLock<T> Ref<T>(this in SharedLock<T> value) where T : class, ISharedMutex
|
||||
{
|
||||
return ref Unsafe.AsRef(in value);
|
||||
}
|
||||
}
|
||||
|
||||
[NonCopyableDisposable]
|
||||
public ref struct SharedLockRef<TMutex> where TMutex : struct, ISharedMutex
|
||||
{
|
||||
private Ref<TMutex> _mutex;
|
||||
private bool _ownsLock;
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public SharedLockRef(ref TMutex mutex)
|
||||
{
|
||||
_mutex = new Ref<TMutex>(ref mutex);
|
||||
mutex.LockShared();
|
||||
_ownsLock = true;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public SharedLockRef(ref TMutex mutex, DeferLock tag)
|
||||
{
|
||||
_mutex = new Ref<TMutex>(ref mutex);
|
||||
_ownsLock = false;
|
||||
}
|
||||
|
||||
public SharedLockRef(ref SharedLockRef<TMutex> other)
|
||||
{
|
||||
_mutex = other._mutex;
|
||||
_ownsLock = other._ownsLock;
|
||||
|
||||
other = default;
|
||||
}
|
||||
|
||||
public void Set(ref SharedLockRef<TMutex> other)
|
||||
{
|
||||
if (_ownsLock)
|
||||
_mutex.Value.UnlockShared();
|
||||
|
||||
_mutex = default;
|
||||
_ownsLock = false;
|
||||
|
||||
_mutex = other._mutex;
|
||||
_ownsLock = other._ownsLock;
|
||||
|
||||
other = default;
|
||||
}
|
||||
|
||||
public void Lock()
|
||||
{
|
||||
if (_mutex.IsNull)
|
||||
throw new SynchronizationLockException("SharedLock.Lock: References null mutex");
|
||||
|
||||
if (_ownsLock)
|
||||
throw new SynchronizationLockException("SharedLock.Lock: Already locked");
|
||||
|
||||
_mutex.Value.LockShared();
|
||||
_ownsLock = true;
|
||||
}
|
||||
|
||||
public bool TryLock()
|
||||
{
|
||||
if (_mutex.IsNull)
|
||||
throw new SynchronizationLockException("SharedLock.TryLock: References null mutex");
|
||||
|
||||
if (_ownsLock)
|
||||
throw new SynchronizationLockException("SharedLock.TryLock: Already locked");
|
||||
|
||||
_ownsLock = _mutex.Value.TryLockShared();
|
||||
return _ownsLock;
|
||||
}
|
||||
|
||||
public void Unlock()
|
||||
{
|
||||
if (_ownsLock)
|
||||
throw new SynchronizationLockException("SharedLock.Unlock: Not locked");
|
||||
|
||||
_mutex.Value.UnlockShared();
|
||||
_ownsLock = false;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void Dispose()
|
||||
{
|
||||
if (_ownsLock)
|
||||
_mutex.Value.UnlockShared();
|
||||
|
||||
this = default;
|
||||
}
|
||||
}
|
||||
|
||||
[NonCopyableDisposable]
|
||||
public struct SharedLock<TMutex> : IDisposable where TMutex : class, ISharedMutex
|
||||
{
|
||||
private TMutex _mutex;
|
||||
private bool _ownsLock;
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public SharedLock(TMutex mutex)
|
||||
{
|
||||
_mutex = mutex;
|
||||
mutex.LockShared();
|
||||
_ownsLock = true;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public SharedLock(TMutex mutex, DeferLock tag)
|
||||
{
|
||||
_mutex = mutex;
|
||||
_ownsLock = false;
|
||||
}
|
||||
|
||||
public SharedLock(ref SharedLock<TMutex> other)
|
||||
{
|
||||
_mutex = other._mutex;
|
||||
_ownsLock = other._ownsLock;
|
||||
|
||||
other = default;
|
||||
}
|
||||
|
||||
public void Set(ref SharedLock<TMutex> other)
|
||||
{
|
||||
if (_ownsLock)
|
||||
_mutex.UnlockShared();
|
||||
|
||||
_mutex = null;
|
||||
_ownsLock = false;
|
||||
|
||||
_mutex = other._mutex;
|
||||
_ownsLock = other._ownsLock;
|
||||
|
||||
other = default;
|
||||
}
|
||||
|
||||
public void Reset(TMutex mutex)
|
||||
{
|
||||
if (_ownsLock)
|
||||
_mutex.UnlockShared();
|
||||
|
||||
_mutex = null;
|
||||
_ownsLock = false;
|
||||
|
||||
_mutex = mutex;
|
||||
mutex.LockShared();
|
||||
_ownsLock = true;
|
||||
}
|
||||
|
||||
public void Lock()
|
||||
{
|
||||
if (_mutex is null)
|
||||
throw new SynchronizationLockException("SharedLock.Lock: References null mutex");
|
||||
|
||||
if (_ownsLock)
|
||||
throw new SynchronizationLockException("SharedLock.Lock: Already locked");
|
||||
|
||||
_mutex.LockShared();
|
||||
_ownsLock = true;
|
||||
}
|
||||
|
||||
public bool TryLock()
|
||||
{
|
||||
if (_mutex is null)
|
||||
throw new SynchronizationLockException("SharedLock.TryLock: References null mutex");
|
||||
|
||||
if (_ownsLock)
|
||||
throw new SynchronizationLockException("SharedLock.TryLock: Already locked");
|
||||
|
||||
_ownsLock = _mutex.TryLockShared();
|
||||
return _ownsLock;
|
||||
}
|
||||
|
||||
public void Unlock()
|
||||
{
|
||||
if (_ownsLock)
|
||||
throw new SynchronizationLockException("SharedLock.Unlock: Not locked");
|
||||
|
||||
_mutex.UnlockShared();
|
||||
_ownsLock = false;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void Dispose()
|
||||
{
|
||||
if (_ownsLock)
|
||||
_mutex.UnlockShared();
|
||||
|
||||
this = default;
|
||||
}
|
||||
}
|
|
@ -41,6 +41,7 @@ public static class UniqueLock
|
|||
}
|
||||
}
|
||||
|
||||
[NonCopyableDisposable]
|
||||
public ref struct UniqueLockRef<TMutex> where TMutex : struct, ILockable
|
||||
{
|
||||
private Ref<TMutex> _mutex;
|
||||
|
@ -63,7 +64,9 @@ public ref struct UniqueLockRef<TMutex> where TMutex : struct, ILockable
|
|||
|
||||
public UniqueLockRef(ref UniqueLockRef<TMutex> other)
|
||||
{
|
||||
this = other;
|
||||
_mutex = other._mutex;
|
||||
_ownsLock = other._ownsLock;
|
||||
|
||||
other = default;
|
||||
}
|
||||
|
||||
|
@ -72,7 +75,12 @@ public ref struct UniqueLockRef<TMutex> where TMutex : struct, ILockable
|
|||
if (_ownsLock)
|
||||
_mutex.Value.Unlock();
|
||||
|
||||
this = other;
|
||||
_mutex = default;
|
||||
_ownsLock = false;
|
||||
|
||||
_mutex = other._mutex;
|
||||
_ownsLock = other._ownsLock;
|
||||
|
||||
other = default;
|
||||
}
|
||||
|
||||
|
@ -119,6 +127,7 @@ public ref struct UniqueLockRef<TMutex> where TMutex : struct, ILockable
|
|||
}
|
||||
}
|
||||
|
||||
[NonCopyableDisposable]
|
||||
public struct UniqueLock<TMutex> : IDisposable where TMutex : class, ILockable
|
||||
{
|
||||
private TMutex _mutex;
|
||||
|
@ -141,7 +150,9 @@ public struct UniqueLock<TMutex> : IDisposable where TMutex : class, ILockable
|
|||
|
||||
public UniqueLock(ref UniqueLock<TMutex> other)
|
||||
{
|
||||
this = other;
|
||||
_mutex = other._mutex;
|
||||
_ownsLock = other._ownsLock;
|
||||
|
||||
other = default;
|
||||
}
|
||||
|
||||
|
@ -150,7 +161,12 @@ public struct UniqueLock<TMutex> : IDisposable where TMutex : class, ILockable
|
|||
if (_ownsLock)
|
||||
_mutex.Unlock();
|
||||
|
||||
this = other;
|
||||
_mutex = null;
|
||||
_ownsLock = false;
|
||||
|
||||
_mutex = other._mutex;
|
||||
_ownsLock = other._ownsLock;
|
||||
|
||||
other = default;
|
||||
}
|
||||
|
||||
|
@ -159,6 +175,9 @@ public struct UniqueLock<TMutex> : IDisposable where TMutex : class, ILockable
|
|||
if (_ownsLock)
|
||||
_mutex.Unlock();
|
||||
|
||||
_mutex = null;
|
||||
_ownsLock = false;
|
||||
|
||||
_mutex = mutex;
|
||||
mutex.Lock();
|
||||
_ownsLock = true;
|
||||
|
|
Loading…
Reference in a new issue