/src/Manos.IO/Manos.IO.Managed/Context.cs

http://github.com/jacksonh/manos · C# · 230 lines · 198 code · 32 blank · 0 comment · 7 complexity · f79bef59463d35986962c561fe9ef55c MD5 · raw file

  1. using System;
  2. using System.Threading;
  3. using System.Collections.Concurrent;
  4. using System.Collections.Generic;
  5. using System.IO;
  6. using Mono.Unix.Native;
  7. namespace Manos.IO.Managed
  8. {
  9. class Context : Manos.IO.Context
  10. {
  11. private AutoResetEvent pulse;
  12. private Queue<Action> outstanding;
  13. private List<PrepareWatcher> prepares;
  14. private List<CheckWatcher> checks;
  15. private List<IdleWatcher> idles;
  16. private List<AsyncWatcher> asyncs;
  17. private List<TimerWatcher> timers;
  18. private volatile bool running;
  19. private object syncRoot = new object ();
  20. public Context ()
  21. {
  22. pulse = new AutoResetEvent (false);
  23. outstanding = new Queue<Action> ();
  24. asyncs = new List<AsyncWatcher> ();
  25. prepares = new List<PrepareWatcher> ();
  26. checks = new List<CheckWatcher> ();
  27. idles = new List<IdleWatcher> ();
  28. timers = new List<TimerWatcher> ();
  29. }
  30. internal void Enqueue (Action cb)
  31. {
  32. if (cb == null)
  33. throw new ArgumentNullException ("cb");
  34. lock (syncRoot) {
  35. outstanding.Enqueue (cb);
  36. }
  37. pulse.Set ();
  38. }
  39. internal void Remove (AsyncWatcher async)
  40. {
  41. asyncs.Remove (async);
  42. }
  43. internal void Remove (PrepareWatcher prepare)
  44. {
  45. prepares.Remove (prepare);
  46. }
  47. internal void Remove (CheckWatcher check)
  48. {
  49. checks.Remove (check);
  50. }
  51. internal void Remove (IdleWatcher check)
  52. {
  53. idles.Remove (check);
  54. }
  55. internal void Remove (TimerWatcher timer)
  56. {
  57. timers.Remove (timer);
  58. }
  59. protected override void Dispose (bool disposing)
  60. {
  61. if (pulse != null) {
  62. pulse.Dispose ();
  63. Dispose (ref checks);
  64. Dispose (ref prepares);
  65. Dispose (ref idles);
  66. Dispose (ref timers);
  67. outstanding = null;
  68. checks = null;
  69. prepares = null;
  70. idles = null;
  71. timers = null;
  72. }
  73. }
  74. static void Dispose<T> (ref List<T> items)
  75. where T : IBaseWatcher
  76. {
  77. var localItems = items;
  78. items = new List<T> ();
  79. foreach (var item in localItems) {
  80. item.Dispose ();
  81. }
  82. }
  83. public override void Start ()
  84. {
  85. running = true;
  86. while (running) {
  87. RunOnce ();
  88. }
  89. }
  90. public override void RunOnce ()
  91. {
  92. pulse.WaitOne ();
  93. RunOnceNonblocking ();
  94. }
  95. public override void RunOnceNonblocking ()
  96. {
  97. foreach (var prep in prepares.ToArray ()) {
  98. prep.Invoke ();
  99. }
  100. int count = 0;
  101. lock (this) {
  102. count = outstanding.Count;
  103. }
  104. while (count-- > 0) {
  105. Action cb;
  106. lock (this) {
  107. cb = outstanding.Dequeue ();
  108. }
  109. cb ();
  110. }
  111. foreach (var idle in idles.ToArray ()) {
  112. idle.Invoke ();
  113. pulse.Set ();
  114. }
  115. foreach (var check in checks.ToArray ()) {
  116. check.Invoke ();
  117. }
  118. }
  119. public override void Stop ()
  120. {
  121. running = false;
  122. }
  123. public override IAsyncWatcher CreateAsyncWatcher (Action cb)
  124. {
  125. var result = new AsyncWatcher (this, cb);
  126. asyncs.Add (result);
  127. return result;
  128. }
  129. public override ICheckWatcher CreateCheckWatcher (Action cb)
  130. {
  131. var result = new CheckWatcher (this, cb);
  132. checks.Add (result);
  133. return result;
  134. }
  135. public override IIdleWatcher CreateIdleWatcher (Action cb)
  136. {
  137. var result = new IdleWatcher (this, cb);
  138. idles.Add (result);
  139. return result;
  140. }
  141. public override IPrepareWatcher CreatePrepareWatcher (Action cb)
  142. {
  143. var result = new PrepareWatcher (this, cb);
  144. prepares.Add (result);
  145. return result;
  146. }
  147. public override ITimerWatcher CreateTimerWatcher (TimeSpan timeout, Action cb)
  148. {
  149. return CreateTimerWatcher (timeout, TimeSpan.Zero, cb);
  150. }
  151. public override ITimerWatcher CreateTimerWatcher (TimeSpan timeout, TimeSpan repeat, Action cb)
  152. {
  153. var result = new TimerWatcher (this, cb, timeout, repeat);
  154. timers.Add (result);
  155. return result;
  156. }
  157. public override Manos.IO.ITcpSocket CreateTcpSocket (AddressFamily addressFamily)
  158. {
  159. return new TcpSocket (this, addressFamily);
  160. }
  161. public override ITcpServerSocket CreateTcpServerSocket(AddressFamily addressFamily)
  162. {
  163. return new TcpSocket (this, addressFamily);
  164. }
  165. public override Manos.IO.ITcpSocket CreateSecureSocket (string certFile, string keyFile)
  166. {
  167. throw new NotSupportedException ();
  168. }
  169. public override IByteStream OpenFile (string fileName, OpenMode openMode, int blockSize)
  170. {
  171. FileAccess access;
  172. switch (openMode) {
  173. case OpenMode.Read:
  174. access = FileAccess.Read;
  175. break;
  176. case OpenMode.ReadWrite:
  177. access = FileAccess.ReadWrite;
  178. break;
  179. case OpenMode.Write:
  180. access = FileAccess.Write;
  181. break;
  182. default:
  183. throw new ArgumentException ("openMode");
  184. }
  185. var fs = new System.IO.FileStream (fileName, FileMode.Open, access, FileShare.ReadWrite, blockSize, true);
  186. return new FileStream (this, fs, blockSize);
  187. }
  188. public override IByteStream CreateFile (string fileName, int blockSize)
  189. {
  190. var fs = System.IO.File.Create (fileName);
  191. return new FileStream (this, fs, blockSize);
  192. }
  193. public override Manos.IO.IUdpSocket CreateUdpSocket (AddressFamily family)
  194. {
  195. return new UdpSocket (this, family);
  196. }
  197. }
  198. }