]> git.ipfire.org Git - thirdparty/squid.git/blob - src/FadingCounter.cc
Source Format Enforcement (#532)
[thirdparty/squid.git] / src / FadingCounter.cc
1 /*
2 * Copyright (C) 1996-2020 The Squid Software Foundation and contributors
3 *
4 * Squid software is distributed under GPLv2+ license and includes
5 * contributions from numerous individuals and organizations.
6 * Please see the COPYING and CONTRIBUTORS files for details.
7 */
8
9 #include "squid.h"
10 #include "base/TextException.h"
11 #include "Debug.h"
12 #include "FadingCounter.h"
13 #include "SquidTime.h"
14
15 #include <cmath>
16
17 FadingCounter::FadingCounter(): horizon(-1), precision(10), delta(-1),
18 lastTime(0), total(0)
19 {
20 counters.reserve(precision);
21 while (counters.size() < static_cast<unsigned int>(precision))
22 counters.push_back(0);
23 }
24
25 void FadingCounter::clear()
26 {
27 for (int i = 0; i < precision; ++i)
28 counters[i] = 0;
29 lastTime = current_dtime;
30 total = 0;
31 }
32
33 void FadingCounter::configure(double newHorizon)
34 {
35 if (fabs(newHorizon - horizon) >= 1e-3) { // diff exceeds one millisecond
36 clear(); // for simplicity
37 horizon = newHorizon;
38 delta = horizon / precision; // may become negative or zero
39 }
40 }
41
42 int FadingCounter::count(int howMany)
43 {
44 Must(howMany >= 0);
45
46 if (delta < 0)
47 return total += howMany; // forget nothing
48
49 if (horizon < 1e-3) // (e.g., zero)
50 return howMany; // remember nothing
51
52 const double deltas = (current_dtime - lastTime) / delta;
53 if (deltas >= precision || current_dtime < lastTime) {
54 clear(); // forget all values
55 } else {
56 // forget stale values, if any
57 // fmod() or "current_dtime/delta" will overflow int for small deltas
58 const int lastSlot = static_cast<int>(fmod(lastTime, horizon) / delta);
59 const int staleSlots = static_cast<int>(deltas);
60 for (int i = 0, s = lastSlot + 1; i < staleSlots; ++i, ++s) {
61 const int idx = s % precision;
62 total -= counters[idx];
63 counters[idx] = 0;
64 Must(total >= 0);
65 }
66 }
67
68 // apply new information
69 lastTime = current_dtime;
70 const int curSlot = static_cast<int>(fmod(lastTime, horizon) / delta);
71 counters[curSlot % precision] += howMany;
72 total += howMany;
73 Must(total >= 0);
74
75 return total;
76 }
77