wasSharp – Diff between revs 27 and 54

Subversion Repositories:
Rev:
Only display areas with differencesIgnore whitespace
Rev 27 Rev 54
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.Xml.Serialization; 12 using System.Xml.Serialization;
13   13  
14 namespace wasSharp.Timers 14 namespace wasSharp.Timers
15 { 15 {
16 /////////////////////////////////////////////////////////////////////////// 16 ///////////////////////////////////////////////////////////////////////////
17 // Copyright (C) Wizardry and Steamworks 2013 - License: GNU GPLv3 // 17 // Copyright (C) Wizardry and Steamworks 2013 - License: GNU GPLv3 //
18 /////////////////////////////////////////////////////////////////////////// 18 ///////////////////////////////////////////////////////////////////////////
19 /// <summary> 19 /// <summary>
20 /// An alarm class similar to the UNIX alarm with the added benefit 20 /// An alarm class similar to the UNIX alarm with the added benefit
21 /// of a decaying timer that tracks the time between rescheduling. 21 /// of a decaying timer that tracks the time between rescheduling.
22 /// </summary> 22 /// </summary>
23 /// <remarks> 23 /// <remarks>
24 /// (C) Wizardry and Steamworks 2013 - License: GNU GPLv3 24 /// (C) Wizardry and Steamworks 2013 - License: GNU GPLv3
25 /// </remarks> 25 /// </remarks>
26 public class DecayingAlarm : IDisposable 26 public class DecayingAlarm : IDisposable
27 { 27 {
28 [Flags] 28 [Flags]
29 public enum DECAY_TYPE 29 public enum DECAY_TYPE
30 { 30 {
31 [Reflection.NameAttribute("none")] 31 [Reflection.NameAttribute("none")]
32 [XmlEnum(Name = "none")] 32 [XmlEnum(Name = "none")]
33 NONE = 0, 33 NONE = 0,
34   34  
35 [Reflection.NameAttribute("arithmetic")] 35 [Reflection.NameAttribute("arithmetic")]
36 [XmlEnum(Name = "arithmetic")] 36 [XmlEnum(Name = "arithmetic")]
37 ARITHMETIC = 1, 37 ARITHMETIC = 1,
38   38  
39 [Reflection.NameAttribute("geometric")] 39 [Reflection.NameAttribute("geometric")]
40 [XmlEnum(Name = "geometric")] 40 [XmlEnum(Name = "geometric")]
41 GEOMETRIC = 2, 41 GEOMETRIC = 2,
42   42  
43 [Reflection.NameAttribute("harmonic")] 43 [Reflection.NameAttribute("harmonic")]
44 [XmlEnum(Name = "harmonic")] 44 [XmlEnum(Name = "harmonic")]
45 HARMONIC = 4, 45 HARMONIC = 4,
46   46  
47 [Reflection.NameAttribute("weighted")] 47 [Reflection.NameAttribute("weighted")]
48 [XmlEnum(Name = "weighted")] 48 [XmlEnum(Name = "weighted")]
49 WEIGHTED = 5 49 WEIGHTED = 5
50 } 50 }
51   51  
52 private readonly DECAY_TYPE decay = DECAY_TYPE.NONE; 52 private readonly DECAY_TYPE decay = DECAY_TYPE.NONE;
53 private readonly Stopwatch elapsed = new Stopwatch(); 53 private readonly Stopwatch elapsed = new Stopwatch();
54 private readonly object LockObject = new object(); 54 private readonly object LockObject = new object();
55 private readonly HashSet<double> times = new HashSet<double>(); 55 private readonly HashSet<double> times = new HashSet<double>();
56 private Timer alarm; 56 private Timer alarm;
57   57  
58 /// <summary> 58 /// <summary>
59 /// The default constructor using no decay. 59 /// The default constructor using no decay.
60 /// </summary> 60 /// </summary>
61 public DecayingAlarm() 61 public DecayingAlarm()
62 { 62 {
63 Signal = new ManualResetEvent(false); 63 Signal = new ManualResetEvent(false);
64 } 64 }
65   65  
66 /// <summary> 66 /// <summary>
67 /// The constructor for the DecayingAlarm class taking as parameter a decay type. 67 /// The constructor for the DecayingAlarm class taking as parameter a decay type.
68 /// </summary> 68 /// </summary>
69 /// <param name="decay">the type of decay: arithmetic, geometric, harmonic, heronian or quadratic</param> 69 /// <param name="decay">the type of decay: arithmetic, geometric, harmonic, heronian or quadratic</param>
70 public DecayingAlarm(DECAY_TYPE decay) 70 public DecayingAlarm(DECAY_TYPE decay)
71 { 71 {
72 Signal = new ManualResetEvent(false); 72 Signal = new ManualResetEvent(false);
73 this.decay = decay; 73 this.decay = decay;
74 } 74 }
75   75  
76 public ManualResetEvent Signal { get; set; } 76 public ManualResetEvent Signal { get; set; }
77   77  
78 public void Dispose() 78 public void Dispose()
79 { 79 {
80 Dispose(true); 80 Dispose(true);
81 GC.SuppressFinalize(this); 81 GC.SuppressFinalize(this);
82 } 82 }
83   83  
84 ~DecayingAlarm() 84 ~DecayingAlarm()
85 { 85 {
86 Dispose(false); 86 Dispose(false);
87 } 87 }
88   88  
89 public void Alarm(double deadline) 89 public void Alarm(double deadline)
90 { 90 {
91 lock (LockObject) 91 lock (LockObject)
92 { 92 {
93 switch (alarm == null) 93 switch (alarm == null)
94 { 94 {
95 case true: 95 case true:
96 elapsed.Start(); 96 elapsed.Start();
97 alarm = new Timer(() => 97 alarm = new Timer(() =>
98 { 98 {
99 lock (LockObject) 99 lock (LockObject)
100 { 100 {
101 Signal.Set(); 101 Signal.Set();
102 elapsed.Stop(); 102 elapsed.Stop();
103 times.Clear(); 103 times.Clear();
104 alarm.Dispose(); 104 alarm.Dispose();
105 alarm = null; 105 alarm = null;
106 } 106 }
107 }, deadline, 0); 107 }, deadline, 0);
108 return; 108 return;
109   109  
110 case false: 110 case false:
111 elapsed.Stop(); 111 elapsed.Stop();
112 times.Add(elapsed.ElapsedMilliseconds); 112 times.Add(elapsed.ElapsedMilliseconds);
113 switch (decay) 113 switch (decay)
114 { 114 {
115 case DECAY_TYPE.ARITHMETIC: 115 case DECAY_TYPE.ARITHMETIC:
116 alarm?.Change( 116 alarm?.Change(
117 (int)((deadline + times.Aggregate((a, b) => b + a)) / (1f + times.Count)), 0); 117 (int)((deadline + times.Aggregate((a, b) => b + a)) / (1f + times.Count())), 0);
118 break; 118 break;
119   119  
120 case DECAY_TYPE.GEOMETRIC: 120 case DECAY_TYPE.GEOMETRIC:
121 alarm?.Change((int)Math.Pow(deadline * times.Aggregate((a, b) => b * a), 121 alarm?.Change((int)Math.Pow(deadline * times.Aggregate((a, b) => b * a),
122 1f / (1f + times.Count)), 0); 122 1f / (1f + times.Count())), 0);
123 break; 123 break;
124   124  
125 case DECAY_TYPE.HARMONIC: 125 case DECAY_TYPE.HARMONIC:
126 alarm?.Change((int)((1f + times.Count) / 126 alarm?.Change((int)((1f + times.Count()) /
127 (1f / deadline + times.Aggregate((a, b) => 1f / b + 1f / a))), 0); 127 (1f / deadline + times.Aggregate((a, b) => 1f / b + 1f / a))), 0);
128 break; 128 break;
129   129  
130 case DECAY_TYPE.WEIGHTED: 130 case DECAY_TYPE.WEIGHTED:
131 var d = new HashSet<double>(times) { deadline }; 131 var d = new HashSet<double>(times) { deadline };
132 var total = d.Aggregate((a, b) => b + a); 132 var total = d.Aggregate((a, b) => b + a);
133 alarm?.Change( 133 alarm?.Change(
134 (int)d.Aggregate((a, b) => Math.Pow(a, 2) / total + Math.Pow(b, 2) / total), 0); 134 (int)d.Aggregate((a, b) => Math.Pow(a, 2) / total + Math.Pow(b, 2) / total), 0);
135 break; 135 break;
136   136  
137 default: 137 default:
138 alarm?.Change((int)deadline, 0); 138 alarm?.Change((int)deadline, 0);
139 break; 139 break;
140 } 140 }
141 elapsed.Reset(); 141 elapsed.Reset();
142 elapsed.Start(); 142 elapsed.Start();
143 break; 143 break;
144 } 144 }
145 } 145 }
146 } 146 }
147   147  
148 private void Dispose(bool dispose) 148 private void Dispose(bool dispose)
149 { 149 {
150 if (alarm != null) 150 if (alarm != null)
151 { 151 {
152 alarm.Dispose(); 152 alarm.Dispose();
153 alarm = null; 153 alarm = null;
154 } 154 }
155 } 155 }
156   156  
157 public DecayingAlarm Clone() 157 public DecayingAlarm Clone()
158 { 158 {
159 return new DecayingAlarm(decay); 159 return new DecayingAlarm(decay);
160 } 160 }
161 } 161 }
162 } 162 }
163   163