PageRenderTime 35ms CodeModel.GetById 20ms app.highlight 12ms RepoModel.GetById 1ms app.codeStats 0ms

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