wasSharp – Blame information for rev 27

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