/src/Manos.IO/Manos.IO.Libev/EventedStream.cs

http://github.com/jacksonh/manos · C# · 175 lines · 146 code · 28 blank · 1 comment · 24 complexity · 5367521bb4e320bc2627265efa960cfb MD5 · raw file

  1. using System;
  2. using Libev;
  3. using System.Collections.Generic;
  4. namespace Manos.IO.Libev
  5. {
  6. abstract class EventedStream<TFragment> : FragmentStream<TFragment>
  7. where TFragment : class
  8. {
  9. // readiness watchers
  10. IOWatcher readWatcher, writeWatcher;
  11. TimerWatcher readTimeoutWatcher, writeTimeoutWatcher;
  12. TimeSpan readTimeout, writeTimeout;
  13. DateTime? readTimeoutContinuation, writeTimeoutContinuation;
  14. protected EventedStream (Context context, IntPtr handle)
  15. : base (context)
  16. {
  17. if (handle == IntPtr.Zero)
  18. throw new ArgumentException ("handle");
  19. this.Handle = handle;
  20. this.readWatcher = new IOWatcher (Handle, EventTypes.Read, Context.Loop, HandleReadReady);
  21. this.writeWatcher = new IOWatcher (Handle, EventTypes.Write, Context.Loop, HandleWriteReady);
  22. }
  23. public override bool CanTimeout {
  24. get { return true; }
  25. }
  26. public override TimeSpan ReadTimeout {
  27. get { return readTimeout; }
  28. set {
  29. if (value < TimeSpan.Zero)
  30. throw new ArgumentException ("value");
  31. readTimeout = value;
  32. if (readTimeoutWatcher == null) {
  33. readTimeoutWatcher = new TimerWatcher (readTimeout, Context.Loop, HandleReadTimeout);
  34. }
  35. readTimeoutWatcher.Repeat = readTimeout;
  36. readTimeoutWatcher.Again ();
  37. }
  38. }
  39. public override TimeSpan WriteTimeout {
  40. get { return writeTimeout; }
  41. set {
  42. if (value < TimeSpan.Zero)
  43. throw new ArgumentException ("value");
  44. writeTimeout = value;
  45. if (writeTimeoutWatcher == null) {
  46. writeTimeoutWatcher = new TimerWatcher (writeTimeout, Context.Loop, HandleWriteTimeout);
  47. }
  48. writeTimeoutWatcher.Repeat = writeTimeout;
  49. writeTimeoutWatcher.Again ();
  50. }
  51. }
  52. void HandleReadTimeout (TimerWatcher watcher, EventTypes revents)
  53. {
  54. if (readTimeoutContinuation != null) {
  55. readTimeoutWatcher.Repeat = DateTime.Now - readTimeoutContinuation.Value;
  56. readTimeoutWatcher.Again ();
  57. readTimeoutContinuation = null;
  58. } else {
  59. RaiseError (new TimeoutException ());
  60. PauseReading ();
  61. }
  62. }
  63. void HandleWriteTimeout (TimerWatcher watcher, EventTypes revents)
  64. {
  65. if (writeTimeoutContinuation != null) {
  66. writeTimeoutWatcher.Repeat = DateTime.Now - writeTimeoutContinuation.Value;
  67. writeTimeoutWatcher.Again ();
  68. writeTimeoutContinuation = null;
  69. } else {
  70. RaiseError (new TimeoutException ());
  71. PauseWriting ();
  72. }
  73. }
  74. void HandleWriteReady (IOWatcher watcher, EventTypes revents)
  75. {
  76. if (writeTimeoutContinuation == null) {
  77. writeTimeoutContinuation = DateTime.Now;
  78. }
  79. HandleWrite ();
  80. }
  81. void HandleReadReady (IOWatcher watcher, EventTypes revents)
  82. {
  83. if (readTimeoutContinuation == null) {
  84. readTimeoutContinuation = DateTime.Now;
  85. }
  86. HandleRead ();
  87. }
  88. public new Context Context {
  89. get { return (Context) base.Context; }
  90. }
  91. public IntPtr Handle {
  92. get;
  93. private set;
  94. }
  95. public override void ResumeReading ()
  96. {
  97. readWatcher.Start ();
  98. }
  99. public override void ResumeWriting ()
  100. {
  101. writeWatcher.Start ();
  102. }
  103. public override void PauseReading ()
  104. {
  105. readWatcher.Stop ();
  106. }
  107. public override void PauseWriting ()
  108. {
  109. writeWatcher.Stop ();
  110. }
  111. protected override void CancelReader ()
  112. {
  113. PauseReading ();
  114. base.CancelReader ();
  115. }
  116. public override IDisposable Read (Action<TFragment> onData, Action<Exception> onError, Action onClose)
  117. {
  118. ResumeReading ();
  119. return base.Read (onData, onError, onClose);
  120. }
  121. public override void Write (IEnumerable<TFragment> data)
  122. {
  123. base.Write (data);
  124. ResumeWriting ();
  125. }
  126. protected override void Dispose(bool disposing)
  127. {
  128. if (Handle != IntPtr.Zero) {
  129. PauseReading ();
  130. PauseWriting ();
  131. readWatcher.Dispose ();
  132. writeWatcher.Dispose ();
  133. if (readTimeoutWatcher != null)
  134. readTimeoutWatcher.Dispose ();
  135. if (writeTimeoutWatcher != null)
  136. writeTimeoutWatcher.Dispose ();
  137. readWatcher = null;
  138. writeWatcher = null;
  139. readTimeoutWatcher = null;
  140. writeTimeoutWatcher = null;
  141. Handle = IntPtr.Zero;
  142. }
  143. base.Dispose (disposing);
  144. }
  145. protected abstract void HandleRead ();
  146. }
  147. }