AverageRoller.c 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. /* vim: set expandtab ts=4 sw=4: */
  2. /*
  3. * You may redistribute this program and/or modify it under the terms of
  4. * the GNU General Public License as published by the Free Software Foundation,
  5. * either version 3 of the License, or (at your option) any later version.
  6. *
  7. * This program is distributed in the hope that it will be useful,
  8. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. * GNU General Public License for more details.
  11. *
  12. * You should have received a copy of the GNU General Public License
  13. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  14. */
  15. #include "util/AverageRoller.h"
  16. #include "util/AverageRoller_pvt.h"
  17. #include "util/Bits.h"
  18. #include "util/events/Time.h"
  19. /** @see AverageRoller.h */
  20. struct AverageRoller* AverageRoller_new(const uint32_t windowSeconds,
  21. EventBase_t* eventBase,
  22. struct Allocator* allocator)
  23. {
  24. size_t size = sizeof(struct AverageRoller_pvt)
  25. + (sizeof(struct AverageRoller_SumAndEntryCount) * (windowSeconds - 1));
  26. struct AverageRoller_pvt* roller = Allocator_calloc(allocator, size, 1);
  27. Bits_memcpy(roller, (&(struct AverageRoller_pvt) {
  28. .windowSeconds = windowSeconds,
  29. .eventBase = eventBase,
  30. .lastUpdateTime = (uint32_t) Time_currentTimeSeconds()
  31. }), sizeof(struct AverageRoller_pvt));
  32. Identity_set(roller);
  33. return &roller->pub;
  34. }
  35. /** @see AverageRoller.h */
  36. uint32_t AverageRoller_getAverage(struct AverageRoller* averageRoller)
  37. {
  38. struct AverageRoller_pvt* roller = Identity_check((struct AverageRoller_pvt*) averageRoller);
  39. return roller->average;
  40. }
  41. /**
  42. * Update the roller with a new entry.
  43. *
  44. * @param averageRoller the roller to update.
  45. * @param now the number of seconds since the epoch.
  46. * @param newEntry the a new number to be factored into the average.
  47. * @return the average over the last windowSeconds seconds.
  48. */
  49. uint32_t AverageRoller_updateAtTime(struct AverageRoller* averageRoller,
  50. const uint64_t now,
  51. const uint32_t newEntry)
  52. {
  53. struct AverageRoller_pvt* roller = Identity_check((struct AverageRoller_pvt*) averageRoller);
  54. uint32_t index =
  55. (now - roller->lastUpdateTime + roller->lastUpdateIndex) % roller->windowSeconds;
  56. if (((uint32_t) now) > roller->lastUpdateTime) {
  57. roller->sum -= roller->seconds[index].sum;
  58. roller->entryCount -= roller->seconds[index].entryCount;
  59. roller->seconds[index].sum = newEntry;
  60. roller->seconds[index].entryCount = 1;
  61. } else {
  62. roller->seconds[index].sum += newEntry;
  63. roller->seconds[index].entryCount++;
  64. }
  65. roller->sum += newEntry;
  66. roller->entryCount++;
  67. roller->average = roller->sum / roller->entryCount;
  68. roller->lastUpdateTime = now;
  69. roller->lastUpdateIndex = index;
  70. return roller->average;
  71. }
  72. /** @see AverageRoller.h */
  73. uint32_t AverageRoller_update(struct AverageRoller* averageRoller, const uint32_t newEntry)
  74. {
  75. return AverageRoller_updateAtTime(averageRoller,
  76. Time_currentTimeSeconds(),
  77. newEntry);
  78. }