You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

49 lines
1.4 KiB

  1. using System;
  2. using System.Threading;
  3. using System.Threading.Tasks;
  4. namespace MQTTnet.Internal
  5. {
  6. // From Stephen Toub (https://blogs.msdn.microsoft.com/pfxteam/2012/02/12/building-async-coordination-primitives-part-6-asynclock/)
  7. public class AsyncLock : IDisposable
  8. {
  9. private readonly SemaphoreSlim _semaphore = new SemaphoreSlim(1, 1);
  10. private readonly Task<IDisposable> _releaser;
  11. public AsyncLock()
  12. {
  13. _releaser = Task.FromResult((IDisposable)new Releaser(this));
  14. }
  15. public Task<IDisposable> LockAsync(CancellationToken cancellationToken)
  16. {
  17. Task wait = _semaphore.WaitAsync(cancellationToken);
  18. return wait.IsCompleted ?
  19. _releaser :
  20. wait.ContinueWith((_, state) => (IDisposable)state,
  21. _releaser.Result, cancellationToken,
  22. TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default);
  23. }
  24. public void Dispose()
  25. {
  26. _semaphore?.Dispose();
  27. }
  28. private class Releaser : IDisposable
  29. {
  30. private readonly AsyncLock _toRelease;
  31. internal Releaser(AsyncLock toRelease)
  32. {
  33. _toRelease = toRelease;
  34. }
  35. public void Dispose()
  36. {
  37. _toRelease._semaphore.Release();
  38. }
  39. }
  40. }
  41. }