IAsyncGate.cs 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263
  1. // Licensed to the .NET Foundation under one or more agreements.
  2. // The .NET Foundation licenses this file to you under the MIT License.
  3. // See the LICENSE file in the project root for more information.
  4. using System.Reactive.Linq;
  5. using System.Threading.Tasks;
  6. namespace System.Reactive.Threading
  7. {
  8. /// <summary>
  9. /// Synchronization primitive that provides <see cref="System.Threading.Monitor"/>-style
  10. /// exclusive access semantics, but with an asynchronous API.
  11. /// </summary>
  12. /// <remarks>
  13. /// <para>
  14. /// This enables <see cref="AsyncObservable.Synchronize{TSource}(IAsyncObservable{TSource}, IAsyncGate)"/>
  15. /// and <see cref="AsyncObserver.Synchronize{TSource}(IAsyncObserver{TSource}, IAsyncGate)"/>
  16. /// to be used to synchronize access to an observer with a custom synchronization primitive.
  17. /// </para>
  18. /// <para>
  19. /// These methods model the equivalents for <see cref="IObservable{T}"/> and <see cref="IObserver{T}"/>
  20. /// in <c>System.Reactive</c>. Those offer overloads accepting a 'gate' parameter, and if you pass
  21. /// the same object to multiple calls to these methods, they will all synchronize their operation
  22. /// through that same gate object. The <c>gate</c> parameter in those methods is of type
  23. /// <see cref="System.Object"/>, which works because all .NET objects have an associated monitor.
  24. /// (It's created on demand when you first use <c>lock</c> or something equivalent.)
  25. /// </para>
  26. /// <para>
  27. /// That approach is problematic in an async world, because this built-in monitor blocks the
  28. /// calling thread when contention occurs. The basic idea of AsyncRx.NET is to avoid such
  29. /// blocking. It can't always be avoided, and in cases where we can be certain that lock
  30. /// acquisition times will be short, the conventional .NET monitor is still a good choice.
  31. /// But since these <c>Synchronize</c> operators allow the caller to pass a gate which the
  32. /// application code itself might lock, we have no control over how long the lock might be
  33. /// held. So it would be inappropriate to use a monitor here.
  34. /// </para>
  35. /// <para>
  36. /// Since the .NET runtime does not currently offer any asynchronous direct equivalent to
  37. /// monitor, this interface defines the required API. The <see cref="AsyncGate"/> class
  38. /// provide a basic implementation. If applications require additional features, (e.g.
  39. /// if they want cancellation support when the application tries to acquire the lock)
  40. /// they can provide their own implementation.
  41. /// </para>
  42. /// </remarks>
  43. public interface IAsyncGate
  44. {
  45. /// <summary>
  46. /// Acquires the lock.
  47. /// </summary>
  48. /// <returns>
  49. /// A task that completes when the lock has been acquired, returning an <see cref="IAsyncGateReleaser"/>
  50. /// with which to release the lock.
  51. /// </returns>
  52. /// <remarks>
  53. /// <para>
  54. /// Applications release the lock by calling <see cref="IAsyncGateReleaser.Release"/> on the object
  55. /// returned by this method. Typically this is done with a <c>using</c> statement or declaration by
  56. /// using the <see cref="AsyncGateExtensions.LockAsync(IAsyncGate)"/> extension method.
  57. /// </para>
  58. /// </remarks>
  59. public ValueTask<IAsyncGateReleaser> AcquireAsync();
  60. }
  61. }