AverageRoller.c 3.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  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. #include "util/platform/libc/string.h"
  20. /** @see AverageRoller.h */
  21. struct AverageRoller* AverageRoller_new(const uint32_t windowSeconds,
  22. struct EventBase* eventBase,
  23. struct Allocator* allocator)
  24. {
  25. size_t size = sizeof(struct AverageRoller_pvt)
  26. + (sizeof(struct AverageRoller_SumAndEntryCount) * (windowSeconds - 1));
  27. struct AverageRoller_pvt* roller = Allocator_calloc(allocator, size, 1);
  28. Bits_memcpyConst(roller, (&(struct AverageRoller_pvt) {
  29. .windowSeconds = windowSeconds,
  30. .eventBase = eventBase,
  31. .lastUpdateTime = (uint32_t) Time_currentTimeSeconds(eventBase)
  32. }), sizeof(struct AverageRoller_pvt));
  33. Identity_set(roller);
  34. return &roller->pub;
  35. }
  36. /** @see AverageRoller.h */
  37. uint32_t AverageRoller_getAverage(struct AverageRoller* averageRoller)
  38. {
  39. struct AverageRoller_pvt* roller = Identity_check((struct AverageRoller_pvt*) averageRoller);
  40. return roller->average;
  41. }
  42. /**
  43. * Update the roller with a new entry.
  44. *
  45. * @param averageRoller the roller to update.
  46. * @param now the number of seconds since the epoch.
  47. * @param newEntry the a new number to be factored into the average.
  48. * @return the average over the last windowSeconds seconds.
  49. */
  50. uint32_t AverageRoller_updateAtTime(struct AverageRoller* averageRoller,
  51. const uint64_t now,
  52. const uint32_t newEntry)
  53. {
  54. struct AverageRoller_pvt* roller = Identity_check((struct AverageRoller_pvt*) averageRoller);
  55. uint32_t index =
  56. (now - roller->lastUpdateTime + roller->lastUpdateIndex) % roller->windowSeconds;
  57. if (((uint32_t) now) > roller->lastUpdateTime) {
  58. roller->sum -= roller->seconds[index].sum;
  59. roller->entryCount -= roller->seconds[index].entryCount;
  60. roller->seconds[index].sum = newEntry;
  61. roller->seconds[index].entryCount = 1;
  62. } else {
  63. roller->seconds[index].sum += newEntry;
  64. roller->seconds[index].entryCount++;
  65. }
  66. roller->sum += newEntry;
  67. roller->entryCount++;
  68. roller->average = roller->sum / roller->entryCount;
  69. roller->lastUpdateTime = now;
  70. roller->lastUpdateIndex = index;
  71. return roller->average;
  72. }
  73. /** @see AverageRoller.h */
  74. uint32_t AverageRoller_update(struct AverageRoller* averageRoller, const uint32_t newEntry)
  75. {
  76. struct AverageRoller_pvt* roller = Identity_check((struct AverageRoller_pvt*) averageRoller);
  77. return AverageRoller_updateAtTime(averageRoller,
  78. Time_currentTimeSeconds(roller->eventBase),
  79. newEntry);
  80. }