PageRenderTime 8ms CodeModel.GetById 2ms app.highlight 4ms RepoModel.GetById 1ms app.codeStats 0ms

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