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.

SocketAwaitable.cs 1.9 KiB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. using System;
  2. using System.Diagnostics;
  3. using System.IO.Pipelines;
  4. using System.Net.Sockets;
  5. using System.Runtime.CompilerServices;
  6. using System.Threading;
  7. using System.Threading.Tasks;
  8. namespace MQTTnet.AspNetCore.Client.Tcp
  9. {
  10. public class SocketAwaitable : ICriticalNotifyCompletion
  11. {
  12. private static readonly Action _callbackCompleted = () => { };
  13. private readonly PipeScheduler _ioScheduler;
  14. private Action _callback;
  15. private int _bytesTransferred;
  16. private SocketError _error;
  17. public SocketAwaitable(PipeScheduler ioScheduler)
  18. {
  19. _ioScheduler = ioScheduler;
  20. }
  21. public bool IsCompleted => ReferenceEquals(_callback, _callbackCompleted);
  22. public SocketAwaitable GetAwaiter() => this;
  23. public int GetResult()
  24. {
  25. Debug.Assert(ReferenceEquals(_callback, _callbackCompleted));
  26. _callback = null;
  27. if (_error != SocketError.Success)
  28. {
  29. throw new SocketException((int)_error);
  30. }
  31. return _bytesTransferred;
  32. }
  33. public void OnCompleted(Action continuation)
  34. {
  35. if (ReferenceEquals(_callback, _callbackCompleted) ||
  36. ReferenceEquals(Interlocked.CompareExchange(ref _callback, continuation, null), _callbackCompleted))
  37. {
  38. Task.Run(continuation);
  39. }
  40. }
  41. public void UnsafeOnCompleted(Action continuation)
  42. {
  43. OnCompleted(continuation);
  44. }
  45. public void Complete(int bytesTransferred, SocketError socketError)
  46. {
  47. _error = socketError;
  48. _bytesTransferred = bytesTransferred;
  49. var continuation = Interlocked.Exchange(ref _callback, _callbackCompleted);
  50. if (continuation != null)
  51. {
  52. _ioScheduler.Schedule(state => ((Action)state)(), continuation);
  53. }
  54. }
  55. }
  56. }