corrade-vassal – Diff between revs 13 and 14

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