wasSharp – Blame information for rev 10

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 {
31 [Reflection.NameAttribute("none")] [XmlEnum(Name = "none")] NONE = 0,
32 [Reflection.NameAttribute("arithmetic")] [XmlEnum(Name = "arithmetic")] ARITHMETIC = 1,
33 [Reflection.NameAttribute("geometric")] [XmlEnum(Name = "geometric")] GEOMETRIC = 2,
34 [Reflection.NameAttribute("harmonic")] [XmlEnum(Name = "harmonic")] HARMONIC = 4,
35 [Reflection.NameAttribute("weighted")] [XmlEnum(Name = "weighted")] WEIGHTED = 5
36 }
37  
38 private readonly DECAY_TYPE decay = DECAY_TYPE.NONE;
39 private readonly Stopwatch elapsed = new Stopwatch();
40 private readonly object LockObject = new object();
41 private readonly HashSet<double> times = new HashSet<double>();
42 private Timer alarm;
43  
44 /// <summary>
45 /// The default constructor using no decay.
46 /// </summary>
47 public DecayingAlarm()
48 {
49 Signal = new ManualResetEvent(false);
50 }
51  
52 /// <summary>
53 /// The constructor for the DecayingAlarm class taking as parameter a decay type.
54 /// </summary>
55 /// <param name="decay">the type of decay: arithmetic, geometric, harmonic, heronian or quadratic</param>
56 public DecayingAlarm(DECAY_TYPE decay)
57 {
58 Signal = new ManualResetEvent(false);
59 this.decay = decay;
60 }
61  
62 public ManualResetEvent Signal { get; set; }
63  
64 public void Dispose()
65 {
66 Dispose(true);
67 GC.SuppressFinalize(this);
68 }
69  
70 ~DecayingAlarm()
71 {
72 Dispose(false);
73 }
74  
75 public void Alarm(double deadline)
76 {
77 lock (LockObject)
78 {
79 switch (alarm == null)
80 {
81 case true:
82 elapsed.Start();
83 alarm = new Timer(o =>
84 {
85 lock (LockObject)
86 {
87 Signal.Set();
88 elapsed.Stop();
89 times.Clear();
90 alarm.Dispose();
91 alarm = null;
92 }
93 }, null, (int) deadline, 0);
94 return;
95 case false:
96 elapsed.Stop();
97 times.Add(elapsed.ElapsedMilliseconds);
98 switch (decay)
99 {
100 case DECAY_TYPE.ARITHMETIC:
101 alarm?.Change(
102 (int) ((deadline + times.Aggregate((a, b) => b + a))/(1f + times.Count)), 0);
103 break;
104 case DECAY_TYPE.GEOMETRIC:
105 alarm?.Change((int) Math.Pow(deadline*times.Aggregate((a, b) => b*a),
106 1f/(1f + times.Count)), 0);
107 break;
108 case DECAY_TYPE.HARMONIC:
109 alarm?.Change((int) ((1f + times.Count)/
110 (1f/deadline + times.Aggregate((a, b) => 1f/b + 1f/a))), 0);
111 break;
112 case DECAY_TYPE.WEIGHTED:
113 var d = new HashSet<double>(times) {deadline};
114 var total = d.Aggregate((a, b) => b + a);
115 alarm?.Change(
116 (int) d.Aggregate((a, b) => Math.Pow(a, 2)/total + Math.Pow(b, 2)/total), 0);
117 break;
118 default:
119 alarm?.Change((int) deadline, 0);
120 break;
121 }
122 elapsed.Reset();
123 elapsed.Start();
124 break;
125 }
126 }
127 }
128  
129 private void Dispose(bool dispose)
130 {
131 if (alarm != null)
132 {
133 alarm.Dispose();
134 alarm = null;
135 }
136 }
137  
138 public DecayingAlarm Clone()
139 {
140 return new DecayingAlarm(decay);
141 }
142 }
143 }