AverageRoller.c 3.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  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 <http://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. struct EventBase* 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_memcpyConst(roller, (&(struct AverageRoller_pvt) {
  28. .windowSeconds = windowSeconds,
  29. .eventBase = eventBase,
  30. .lastUpdateTime = (uint32_t) Time_currentTimeSeconds(eventBase)
  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. struct AverageRoller_pvt* roller = Identity_check((struct AverageRoller_pvt*) averageRoller);
  76. return AverageRoller_updateAtTime(averageRoller,
  77. Time_currentTimeSeconds(roller->eventBase),
  78. newEntry);
  79. }