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)
|
public static void InitializeReaderWriterLock(this OsState os, ref ReaderWriterLockType rwLock)
|
||||||
{
|
{
|
||||||
// Create objects.
|
// Create objects.
|
||||||
ReaderWriterLockImpl.GetLockCount(ref rwLock).Cs.Initialize();
|
ReaderWriterLockImpl.GetLockCount(ref rwLock).Cs = new InternalCriticalSection();
|
||||||
rwLock.CvReadLockWaiter.Initialize();
|
rwLock.CvReadLockWaiter = new InternalConditionVariable();
|
||||||
rwLock.CvWriteLockWaiter.Initialize();
|
rwLock.CvWriteLockWaiter = new InternalConditionVariable();
|
||||||
|
|
||||||
// Set member variables.
|
// Set member variables.
|
||||||
ReaderWriterLockImpl.ClearReadLockCount(ref ReaderWriterLockImpl.GetLockCount(ref rwLock));
|
ReaderWriterLockImpl.ClearReadLockCount(ref ReaderWriterLockImpl.GetLockCount(ref rwLock));
|
||||||
|
|
|
@ -12,6 +12,7 @@ public static class ScopedLock
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[NonCopyableDisposable]
|
||||||
public ref struct ScopedLock<TMutex> where TMutex : IBasicLockable
|
public ref struct ScopedLock<TMutex> where TMutex : IBasicLockable
|
||||||
{
|
{
|
||||||
private Ref<TMutex> _mutex;
|
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
|
public ref struct UniqueLockRef<TMutex> where TMutex : struct, ILockable
|
||||||
{
|
{
|
||||||
private Ref<TMutex> _mutex;
|
private Ref<TMutex> _mutex;
|
||||||
|
@ -63,7 +64,9 @@ public ref struct UniqueLockRef<TMutex> where TMutex : struct, ILockable
|
||||||
|
|
||||||
public UniqueLockRef(ref UniqueLockRef<TMutex> other)
|
public UniqueLockRef(ref UniqueLockRef<TMutex> other)
|
||||||
{
|
{
|
||||||
this = other;
|
_mutex = other._mutex;
|
||||||
|
_ownsLock = other._ownsLock;
|
||||||
|
|
||||||
other = default;
|
other = default;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,7 +75,12 @@ public ref struct UniqueLockRef<TMutex> where TMutex : struct, ILockable
|
||||||
if (_ownsLock)
|
if (_ownsLock)
|
||||||
_mutex.Value.Unlock();
|
_mutex.Value.Unlock();
|
||||||
|
|
||||||
this = other;
|
_mutex = default;
|
||||||
|
_ownsLock = false;
|
||||||
|
|
||||||
|
_mutex = other._mutex;
|
||||||
|
_ownsLock = other._ownsLock;
|
||||||
|
|
||||||
other = default;
|
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
|
public struct UniqueLock<TMutex> : IDisposable where TMutex : class, ILockable
|
||||||
{
|
{
|
||||||
private TMutex _mutex;
|
private TMutex _mutex;
|
||||||
|
@ -141,7 +150,9 @@ public struct UniqueLock<TMutex> : IDisposable where TMutex : class, ILockable
|
||||||
|
|
||||||
public UniqueLock(ref UniqueLock<TMutex> other)
|
public UniqueLock(ref UniqueLock<TMutex> other)
|
||||||
{
|
{
|
||||||
this = other;
|
_mutex = other._mutex;
|
||||||
|
_ownsLock = other._ownsLock;
|
||||||
|
|
||||||
other = default;
|
other = default;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -150,7 +161,12 @@ public struct UniqueLock<TMutex> : IDisposable where TMutex : class, ILockable
|
||||||
if (_ownsLock)
|
if (_ownsLock)
|
||||||
_mutex.Unlock();
|
_mutex.Unlock();
|
||||||
|
|
||||||
this = other;
|
_mutex = null;
|
||||||
|
_ownsLock = false;
|
||||||
|
|
||||||
|
_mutex = other._mutex;
|
||||||
|
_ownsLock = other._ownsLock;
|
||||||
|
|
||||||
other = default;
|
other = default;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -159,6 +175,9 @@ public struct UniqueLock<TMutex> : IDisposable where TMutex : class, ILockable
|
||||||
if (_ownsLock)
|
if (_ownsLock)
|
||||||
_mutex.Unlock();
|
_mutex.Unlock();
|
||||||
|
|
||||||
|
_mutex = null;
|
||||||
|
_ownsLock = false;
|
||||||
|
|
||||||
_mutex = mutex;
|
_mutex = mutex;
|
||||||
mutex.Lock();
|
mutex.Lock();
|
||||||
_ownsLock = true;
|
_ownsLock = true;
|
||||||
|
|
Loading…
Reference in a new issue