Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/NHibernate/Async/Cache/UpdateTimestampsCache.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ public Task PreInvalidateAsync(object[] spaces, CancellationToken cancellationTo
public virtual async Task PreInvalidateAsync(IReadOnlyCollection<string> spaces, CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
//TODO: to handle concurrent writes correctly, this should return a Lock to the client
if (spaces.Count == 0)
return;
cancellationToken.ThrowIfCancellationRequested();
Expand Down Expand Up @@ -87,6 +88,7 @@ public Task InvalidateAsync(object[] spaces, CancellationToken cancellationToken
public virtual async Task InvalidateAsync(IReadOnlyCollection<string> spaces, CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
//TODO: to handle concurrent writes correctly, the client should pass in a Lock
if (spaces.Count == 0)
return;
cancellationToken.ThrowIfCancellationRequested();
Expand Down
2 changes: 2 additions & 0 deletions src/NHibernate/Cache/UpdateTimestampsCache.cs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ public void PreInvalidate(object[] spaces)

public virtual void PreInvalidate(IReadOnlyCollection<string> spaces)
{
//TODO: to handle concurrent writes correctly, this should return a Lock to the client
if (spaces.Count == 0)
return;

Expand All @@ -77,6 +78,7 @@ public void Invalidate(object[] spaces)

public virtual void Invalidate(IReadOnlyCollection<string> spaces)
{
//TODO: to handle concurrent writes correctly, the client should pass in a Lock
if (spaces.Count == 0)
return;

Expand Down
27 changes: 15 additions & 12 deletions src/NHibernate/Util/AsyncReaderWriterLock.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ internal class AsyncReaderWriterLock
private readonly Releaser _readerReleaser;
private readonly Task<Releaser> _readerReleaserTask;
private SemaphoreSlim _waitingReadLockSemaphore;
private SemaphoreSlim _waitingDisposalSemaphore;
private int _readersWaiting;
private int _currentReaders;
private int _writersWaiting;
Expand Down Expand Up @@ -52,6 +53,8 @@ public Releaser WriteLock()
_readLockSemaphore.Wait();
}

DisposeWaitingSemaphore();

return _writerReleaser;
}

Expand All @@ -71,6 +74,8 @@ public async Task<Releaser> WriteLockAsync()
await _readLockSemaphore.WaitAsync().ConfigureAwait(false);
}

DisposeWaitingSemaphore();

return _writerReleaser;
}

Expand All @@ -82,7 +87,6 @@ public Releaser ReadLock()
}

_waitingReadLockSemaphore.Wait();
ReleaseWaitingReader();

return _readerReleaser;
}
Expand All @@ -94,7 +98,6 @@ public Task<Releaser> ReadLockAsync()
async Task<Releaser> ReadLockInternalAsync()
{
await _waitingReadLockSemaphore.WaitAsync().ConfigureAwait(false);
ReleaseWaitingReader();

return _readerReleaser;
}
Expand Down Expand Up @@ -137,6 +140,10 @@ private void ExitWriteLock()
{
_currentReaders += _readersWaiting;
_waitingReadLockSemaphore.Release(_readersWaiting);
_readersWaiting = 0;
// We have to dispose the waiting read lock only after all readers finished using it
_waitingDisposalSemaphore = _waitingReadLockSemaphore;
_waitingReadLockSemaphore = null;
}

_writeLockSemaphore.Release();
Expand Down Expand Up @@ -182,19 +189,15 @@ private void ExitReadLock()
}
}

private void ReleaseWaitingReader()
private void DisposeWaitingSemaphore()
{
lock (_writeLockSemaphore)
if (_waitingDisposalSemaphore == null)
{
_readersWaiting--;
if (_readersWaiting != 0)
{
return;
}

_waitingReadLockSemaphore.Dispose();
_waitingReadLockSemaphore = null;
return;
}

_waitingDisposalSemaphore.Dispose();
_waitingDisposalSemaphore = null;
}

public struct Releaser : IDisposable
Expand Down