wasSharp – Diff between revs 6 and 7

Subversion Repositories:
Rev:
Only display areas with differencesIgnore whitespace
Rev 6 Rev 7
1 /////////////////////////////////////////////////////////////////////////// 1 ///////////////////////////////////////////////////////////////////////////
2 // Copyright (C) Wizardry and Steamworks 2013 - License: GNU GPLv3 // 2 // Copyright (C) Wizardry and Steamworks 2013 - License: GNU GPLv3 //
3 // Please see: http://www.gnu.org/licenses/gpl.html for legal details, // 3 // Please see: http://www.gnu.org/licenses/gpl.html for legal details, //
4 // rights of fair usage, the disclaimer and warranty conditions. // 4 // rights of fair usage, the disclaimer and warranty conditions. //
5 /////////////////////////////////////////////////////////////////////////// 5 ///////////////////////////////////////////////////////////////////////////
6   6  
7 using System; 7 using System;
8 using System.Collections.Generic; 8 using System.Collections.Generic;
9 using System.Diagnostics; 9 using System.Diagnostics;
10 using System.Linq; 10 using System.Linq;
11 using System.Threading; 11 using System.Threading;
12 using System.Threading.Tasks; 12 using System.Threading.Tasks;
13 using System.Xml.Serialization; 13 using System.Xml.Serialization;
14   14  
15 namespace wasSharp 15 namespace wasSharp
16 { 16 {
17 public class Time 17 public static class Time
18 { 18 {
19 public delegate void TimerCallback(object state); 19 public delegate void TimerCallback(object state);
20   20  
21 /// <summary> 21 /// <summary>
22 /// Convert an Unix timestamp to a DateTime structure. 22 /// Convert an Unix timestamp to a DateTime structure.
23 /// </summary> 23 /// </summary>
24 /// <param name="unixTimestamp">the Unix timestamp to convert</param> 24 /// <param name="unixTimestamp">the Unix timestamp to convert</param>
25 /// <returns>the DateTime structure</returns> 25 /// <returns>the DateTime structure</returns>
26 /// <remarks>the function assumes UTC time</remarks> 26 /// <remarks>the function assumes UTC time</remarks>
27 public static DateTime UnixTimestampToDateTime(uint unixTimestamp) 27 public static DateTime UnixTimestampToDateTime(uint unixTimestamp)
28 { 28 {
29 return new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc).AddSeconds(unixTimestamp).ToUniversalTime(); 29 return new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc).AddSeconds(unixTimestamp).ToUniversalTime();
30 } 30 }
31   31  
32 /// <summary> 32 /// <summary>
33 /// Convert a DateTime structure to a Unix timestamp. 33 /// Convert a DateTime structure to a Unix timestamp.
34 /// </summary> 34 /// </summary>
35 /// <param name="dateTime">the DateTime structure to convert</param> 35 /// <param name="dateTime">the DateTime structure to convert</param>
36 /// <returns>the Unix timestamp</returns> 36 /// <returns>the Unix timestamp</returns>
37 /// <remarks>the function assumes UTC time</remarks> 37 /// <remarks>the function assumes UTC time</remarks>
38 public static uint DateTimeToUnixTimestamp(DateTime dateTime) 38 public static uint DateTimeToUnixTimestamp(DateTime dateTime)
39 { 39 {
40 return (uint) (DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc)).TotalSeconds; 40 return (uint) (DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc)).TotalSeconds;
41 } 41 }
42   42  
43 public sealed class Timer : IDisposable 43 public sealed class Timer : IDisposable
44 { 44 {
45 private static readonly Task CompletedTask = Task.FromResult(false); 45 private static readonly Task CompletedTask = Task.FromResult(false);
46 private readonly TimerCallback Callback; 46 private readonly TimerCallback Callback;
47 private readonly object State; 47 private readonly object State;
48 private Task Delay; 48 private Task Delay;
49 private bool Disposed; 49 private bool Disposed;
50 private int Period; 50 private int Period;
51 private CancellationTokenSource TokenSource; 51 private CancellationTokenSource TokenSource;
52   52  
53 public Timer(TimerCallback callback, object state, int dueTime, int period) 53 public Timer(TimerCallback callback, object state, int dueTime, int period)
54 { 54 {
55 Callback = callback; 55 Callback = callback;
56 State = state; 56 State = state;
57 Period = period; 57 Period = period;
58 Reset(dueTime); 58 Reset(dueTime);
59 } 59 }
60   60  
61 public Timer(TimerCallback callback, object state, TimeSpan dueTime, TimeSpan period) 61 public Timer(TimerCallback callback, object state, TimeSpan dueTime, TimeSpan period)
62 : this(callback, state, (int) dueTime.TotalMilliseconds, (int) period.TotalMilliseconds) 62 : this(callback, state, (int) dueTime.TotalMilliseconds, (int) period.TotalMilliseconds)
63 { 63 {
64 } 64 }
-   65  
-   66 public Timer(TimerCallback callback) : this(callback, null, TimeSpan.Zero, TimeSpan.Zero)
-   67 {
-   68 }
65   69  
66 public void Dispose() 70 public void Dispose()
67 { 71 {
68 Dispose(true); 72 Dispose(true);
69 GC.SuppressFinalize(this); 73 GC.SuppressFinalize(this);
70 } 74 }
71   75  
72 ~Timer() 76 ~Timer()
73 { 77 {
74 Dispose(false); 78 Dispose(false);
75 } 79 }
76   80  
77 private void Dispose(bool cleanUpManagedObjects) 81 private void Dispose(bool cleanUpManagedObjects)
78 { 82 {
79 if (cleanUpManagedObjects) 83 if (cleanUpManagedObjects)
80 Cancel(); 84 Cancel();
81 Disposed = true; 85 Disposed = true;
82 } 86 }
83   87  
84 public void Change(int dueTime, int period) 88 public void Change(int dueTime, int period)
85 { 89 {
86 Period = period; 90 Period = period;
87 Reset(dueTime); 91 Reset(dueTime);
88 } 92 }
-   93  
-   94 public void Change(uint dueTime, int period)
-   95 {
-   96 Period = period;
-   97 Change((int) dueTime, period);
-   98 }
89   99  
90 public void Change(TimeSpan dueTime, TimeSpan period) 100 public void Change(TimeSpan dueTime, TimeSpan period)
91 { 101 {
92 Change((int) dueTime.TotalMilliseconds, (int) period.TotalMilliseconds); 102 Change((int) dueTime.TotalMilliseconds, (int) period.TotalMilliseconds);
93 } 103 }
94   104  
95 private void Reset(int due) 105 private void Reset(int due)
96 { 106 {
97 Cancel(); 107 Cancel();
98 if (due >= 0) 108 if (due <= 0)
-   109 return;
-   110 TokenSource = new CancellationTokenSource();
-   111 Action tick = null;
-   112 tick = () =>
99 { 113 {
100 TokenSource = new CancellationTokenSource(); 114 Task.Run(() => Callback(State));
101 Action tick = null; -  
102 tick = () => 115 if (Disposed)
103 { 116 return;
104 Task.Run(() => Callback(State)); -  
105 if (Disposed || Period < 0) return; -  
106 Delay = Period > 0 ? Task.Delay(Period, TokenSource.Token) : CompletedTask; 117 Delay = Period > 0 ? Task.Delay(Period, TokenSource.Token) : CompletedTask;
107 Delay.ContinueWith(t => tick(), TokenSource.Token); 118 if (Delay.IsCompleted)
108 }; 119 return;
109 Delay = due > 0 ? Task.Delay(due, TokenSource.Token) : CompletedTask; -  
110 Delay.ContinueWith(t => tick(), TokenSource.Token); 120 Delay.ContinueWith(t => tick(), TokenSource.Token);
111 } 121 };
-   122 Delay = due > 0 ? Task.Delay(due, TokenSource.Token) : CompletedTask;
-   123 if (Delay.IsCompleted)
-   124 return;
-   125 Delay.ContinueWith(t => tick(), TokenSource.Token);
-   126 }
-   127  
-   128 public void Stop()
-   129 {
-   130 Change(0, 0);
112 } 131 }
113   132  
114 private void Cancel() 133 private void Cancel()
115 { 134 {
116 if (TokenSource != null) 135 if (TokenSource == null)
117 { 136 return;
118 TokenSource.Cancel(); 137 TokenSource.Cancel();
119 TokenSource.Dispose(); 138 TokenSource.Dispose();
120 TokenSource = null; 139 TokenSource = null;
121 } -  
122 } 140 }
123 } 141 }
124   142  
125 /////////////////////////////////////////////////////////////////////////// 143 ///////////////////////////////////////////////////////////////////////////
126 // Copyright (C) Wizardry and Steamworks 2015 - License: GNU GPLv3 // 144 // Copyright (C) Wizardry and Steamworks 2015 - License: GNU GPLv3 //
127 /////////////////////////////////////////////////////////////////////////// 145 ///////////////////////////////////////////////////////////////////////////
128 /// <summary> 146 /// <summary>
129 /// Given a number of allowed events per seconds, this class allows you 147 /// Given a number of allowed events per seconds, this class allows you
130 /// to determine via the IsSafe property whether it is safe to trigger 148 /// to determine via the IsSafe property whether it is safe to trigger
131 /// another lined-up event. This is mostly used to check that throttles 149 /// another lined-up event. This is mostly used to check that throttles
132 /// are being respected. 150 /// are being respected.
133 /// </summary> 151 /// </summary>
134 public class TimedThrottle : IDisposable 152 public sealed class TimedThrottle : IDisposable
135 { 153 {
136 private readonly uint EventsAllowed; 154 private readonly uint EventsAllowed;
137 private readonly object LockObject = new object(); 155 private readonly object LockObject = new object();
138 private Timer timer; 156 private Timer timer;
139 private uint TriggeredEvents; 157 public uint TriggeredEvents;
140   158  
141 public TimedThrottle(uint events, uint seconds) 159 public TimedThrottle(uint events, uint seconds)
142 { 160 {
143 EventsAllowed = events; 161 EventsAllowed = events;
144 if (timer == null) 162 if (timer == null)
145 { 163 {
146 timer = new Timer(o => 164 timer = new Timer(o =>
147 { 165 {
148 lock (LockObject) 166 lock (LockObject)
149 { 167 {
150 TriggeredEvents = 0; 168 TriggeredEvents = 0;
151 } 169 }
152 }, null, (int) seconds, (int) seconds); 170 }, null, (int) seconds, (int) seconds);
153 } 171 }
154 } 172 }
155   173  
156 public bool IsSafe 174 public bool IsSafe
157 { 175 {
158 get 176 get
159 { 177 {
160 lock (LockObject) 178 lock (LockObject)
161 { 179 {
162 return ++TriggeredEvents <= EventsAllowed; 180 return ++TriggeredEvents <= EventsAllowed;
163 } 181 }
164 } 182 }
165 } 183 }
166   184  
167 public void Dispose() 185 public void Dispose()
168 { 186 {
169 Dispose(true); 187 Dispose(true);
170 GC.SuppressFinalize(this); 188 GC.SuppressFinalize(this);
171 } 189 }
-   190  
-   191 ~TimedThrottle()
-   192 {
-   193 Dispose(false);
-   194 }
172   195  
173 protected virtual void Dispose(bool dispose) 196 private void Dispose(bool dispose)
174 { 197 {
175 if (timer != null) 198 if (timer != null)
176 { 199 {
177 timer.Dispose(); 200 timer.Dispose();
178 timer = null; 201 timer = null;
179 } 202 }
180 } 203 }
181 } 204 }
182   205  
183 /////////////////////////////////////////////////////////////////////////// 206 ///////////////////////////////////////////////////////////////////////////
184 // Copyright (C) Wizardry and Steamworks 2013 - License: GNU GPLv3 // 207 // Copyright (C) Wizardry and Steamworks 2013 - License: GNU GPLv3 //
185 /////////////////////////////////////////////////////////////////////////// 208 ///////////////////////////////////////////////////////////////////////////
186 /// <summary> 209 /// <summary>
187 /// An alarm class similar to the UNIX alarm with the added benefit 210 /// An alarm class similar to the UNIX alarm with the added benefit
188 /// of a decaying timer that tracks the time between rescheduling. 211 /// of a decaying timer that tracks the time between rescheduling.
189 /// </summary> 212 /// </summary>
190 /// <remarks> 213 /// <remarks>
191 /// (C) Wizardry and Steamworks 2013 - License: GNU GPLv3 214 /// (C) Wizardry and Steamworks 2013 - License: GNU GPLv3
192 /// </remarks> 215 /// </remarks>
193 public class DecayingAlarm : IDisposable 216 public sealed class DecayingAlarm : IDisposable
194 { 217 {
195 [Flags] 218 [Flags]
196 public enum DECAY_TYPE 219 public enum DECAY_TYPE
197 { 220 {
198 [XmlEnum(Name = "none")] NONE = 0, 221 [Reflection.NameAttribute("none")] [XmlEnum(Name = "none")] NONE = 0,
199 [XmlEnum(Name = "arithmetic")] ARITHMETIC = 1, 222 [Reflection.NameAttribute("arithmetic")] [XmlEnum(Name = "arithmetic")] ARITHMETIC = 1,
200 [XmlEnum(Name = "geometric")] GEOMETRIC = 2, 223 [Reflection.NameAttribute("geometric")] [XmlEnum(Name = "geometric")] GEOMETRIC = 2,
201 [XmlEnum(Name = "harmonic")] HARMONIC = 4, 224 [Reflection.NameAttribute("harmonic")] [XmlEnum(Name = "harmonic")] HARMONIC = 4,
202 [XmlEnum(Name = "weighted")] WEIGHTED = 5 225 [Reflection.NameAttribute("weighted")] [XmlEnum(Name = "weighted")] WEIGHTED = 5
203 } 226 }
204   227  
205 private readonly DECAY_TYPE decay = DECAY_TYPE.NONE; 228 private readonly DECAY_TYPE decay = DECAY_TYPE.NONE;
206 private readonly Stopwatch elapsed = new Stopwatch(); 229 private readonly Stopwatch elapsed = new Stopwatch();
207 private readonly object LockObject = new object(); 230 private readonly object LockObject = new object();
208 private readonly HashSet<double> times = new HashSet<double>(); 231 private readonly HashSet<double> times = new HashSet<double>();
209 private Timer alarm; 232 private Timer alarm;
210   233  
211 /// <summary> 234 /// <summary>
212 /// The default constructor using no decay. 235 /// The default constructor using no decay.
213 /// </summary> 236 /// </summary>
214 public DecayingAlarm() 237 public DecayingAlarm()
215 { 238 {
216 Signal = new ManualResetEvent(false); 239 Signal = new ManualResetEvent(false);
217 } 240 }
218   241  
219 /// <summary> 242 /// <summary>
220 /// The constructor for the DecayingAlarm class taking as parameter a decay type. 243 /// The constructor for the DecayingAlarm class taking as parameter a decay type.
221 /// </summary> 244 /// </summary>
222 /// <param name="decay">the type of decay: arithmetic, geometric, harmonic, heronian or quadratic</param> 245 /// <param name="decay">the type of decay: arithmetic, geometric, harmonic, heronian or quadratic</param>
223 public DecayingAlarm(DECAY_TYPE decay) 246 public DecayingAlarm(DECAY_TYPE decay)
224 { 247 {
225 Signal = new ManualResetEvent(false); 248 Signal = new ManualResetEvent(false);
226 this.decay = decay; 249 this.decay = decay;
227 } 250 }
228   251  
229 public ManualResetEvent Signal { get; set; } 252 public ManualResetEvent Signal { get; set; }
230   253  
231 public void Dispose() 254 public void Dispose()
232 { 255 {
233 Dispose(true); 256 Dispose(true);
234 GC.SuppressFinalize(this); 257 GC.SuppressFinalize(this);
235 } 258 }
-   259  
-   260 ~DecayingAlarm()
-   261 {
-   262 Dispose(false);
-   263 }
236   264  
237 public void Alarm(double deadline) 265 public void Alarm(double deadline)
238 { 266 {
239 lock (LockObject) 267 lock (LockObject)
240 { 268 {
241 switch (alarm == null) 269 switch (alarm == null)
242 { 270 {
243 case true: 271 case true:
244 elapsed.Start(); 272 elapsed.Start();
245 alarm = new Timer(o => 273 alarm = new Timer(o =>
246 { 274 {
247 lock (LockObject) 275 lock (LockObject)
248 { 276 {
249 Signal.Set(); 277 Signal.Set();
250 elapsed.Stop(); 278 elapsed.Stop();
251 times.Clear(); 279 times.Clear();
252 alarm.Dispose(); 280 alarm.Dispose();
253 alarm = null; 281 alarm = null;
254 } 282 }
255 }, null, (int) deadline, 0); 283 }, null, (int) deadline, 0);
256 return; 284 return;
257 case false: 285 case false:
258 elapsed.Stop(); 286 elapsed.Stop();
259 times.Add(elapsed.ElapsedMilliseconds); 287 times.Add(elapsed.ElapsedMilliseconds);
260 switch (decay) 288 switch (decay)
261 { 289 {
262 case DECAY_TYPE.ARITHMETIC: 290 case DECAY_TYPE.ARITHMETIC:
263 alarm?.Change( 291 alarm?.Change(
264 (int) ((deadline + times.Aggregate((a, b) => b + a))/(1f + times.Count)), 0); 292 (int) ((deadline + times.Aggregate((a, b) => b + a))/(1f + times.Count)), 0);
265 break; 293 break;
266 case DECAY_TYPE.GEOMETRIC: 294 case DECAY_TYPE.GEOMETRIC:
267 alarm?.Change((int) (Math.Pow(deadline*times.Aggregate((a, b) => b*a), 295 alarm?.Change((int) Math.Pow(deadline*times.Aggregate((a, b) => b*a),
268 1f/(1f + times.Count))), 0); 296 1f/(1f + times.Count)), 0);
269 break; 297 break;
270 case DECAY_TYPE.HARMONIC: 298 case DECAY_TYPE.HARMONIC:
271 alarm?.Change((int) ((1f + times.Count)/ 299 alarm?.Change((int) ((1f + times.Count)/
272 (1f/deadline + times.Aggregate((a, b) => 1f/b + 1f/a))), 0); 300 (1f/deadline + times.Aggregate((a, b) => 1f/b + 1f/a))), 0);
273 break; 301 break;
274 case DECAY_TYPE.WEIGHTED: 302 case DECAY_TYPE.WEIGHTED:
275 HashSet<double> d = new HashSet<double>(times) {deadline}; 303 var d = new HashSet<double>(times) {deadline};
276 double total = d.Aggregate((a, b) => b + a); 304 var total = d.Aggregate((a, b) => b + a);
277 alarm?.Change( 305 alarm?.Change(
278 (int) (d.Aggregate((a, b) => Math.Pow(a, 2)/total + Math.Pow(b, 2)/total)), 0); 306 (int) d.Aggregate((a, b) => Math.Pow(a, 2)/total + Math.Pow(b, 2)/total), 0);
279 break; 307 break;
280 default: 308 default:
281 alarm?.Change((int) deadline, 0); 309 alarm?.Change((int) deadline, 0);
282 break; 310 break;
283 } 311 }
284 elapsed.Reset(); 312 elapsed.Reset();
285 elapsed.Start(); 313 elapsed.Start();
286 break; 314 break;
287 } 315 }
288 } 316 }
289 } 317 }
290   318  
291 protected virtual void Dispose(bool dispose) 319 private void Dispose(bool dispose)
292 { 320 {
293 if (alarm != null) 321 if (alarm != null)
294 { 322 {
295 alarm.Dispose(); 323 alarm.Dispose();
296 alarm = null; 324 alarm = null;
297 } 325 }
298 } 326 }
-   327  
-   328 public DecayingAlarm Clone()
-   329 {
-   330 return new DecayingAlarm(decay);
-   331 }
299 } 332 }
300 } 333 }
301 } 334 }
302   335  
303
Generated by GNU Enscript 1.6.5.90.
336
Generated by GNU Enscript 1.6.5.90.
304   337  
305   338  
306   339