backoff.c 1.84 KB
Newer Older
Jordan Sissel's avatar
Jordan Sissel committed
1
//#define _POSIX_C_SOURCE 199309L /* for struct timespec */
2
#include <stdio.h>
3
#include "backoff.h"
4

5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
#define MAX_TV_NSEC 999999999L

static inline void timespec_double(struct timespec *t) {
  /* Exponential backoff */
  t->tv_sec <<= 1;
  t->tv_nsec <<= 1;
  if (t->tv_nsec > MAX_TV_NSEC) {
    /* handle carry/overflow of tv_nsec */
    t->tv_nsec -= (MAX_TV_NSEC + 1);
    t->tv_sec += 1;
  }
} /* timespec_double */

static inline long timespec_compare(struct timespec *a, struct timespec *b) {
  time_t val;
  val = a->tv_sec - b->tv_sec;
  if (val != 0) {
    return val;
  } 
  return a->tv_nsec - b->tv_nsec;
} /* timespec_compare */

static inline void timespec_copy(struct timespec *source, struct timespec *dest) {
  /* TODO(sissel): Could use memcpy here instead... */
  dest->tv_sec = source->tv_sec;
  dest->tv_nsec = source->tv_nsec;
} /* timespec_copy */

33 34 35 36
inline void backoff_clear(struct backoff *b) {
  timespec_copy(&b->min, &b->sleep);
} /* backoff_clear */

37 38 39 40
inline void backoff_init(struct backoff *b, struct timespec *min,
                         struct timespec *max) {
  timespec_copy(min, &b->min);
  timespec_copy(max, &b->max);
41 42 43 44
  backoff_clear(b);
} /* backoff_init */

inline void backoff(struct backoff *b) {
45 46
  //printf("Sleeping %ld.%09ld\n", b->sleep.tv_sec, b->sleep.tv_nsec);
  nanosleep(&b->sleep, NULL);
47 48

  /* Exponential backoff */
49 50 51 52 53 54 55
  timespec_double(&b->sleep);
  //printf("Candidate vs max: %ld.%09ld vs %ld.%09ld: %ld\n",
         //b->sleep.tv_sec, b->sleep.tv_nsec,
         //b->max.tv_sec, b->max.tv_nsec,
         //timespec_compare(&b->sleep, &b->max));
  //printf("tv_sec: %ld\n", b->sleep.tv_sec - b->max.tv_sec);
  //printf("tv_nsec: %ld\n", b->sleep.tv_nsec - b->max.tv_nsec);
56

57 58 59
  /* Cap at 'max' if sleep time exceeds it */
  if (timespec_compare(&b->sleep, &b->max) > 0) {
    timespec_copy(&b->max, &b->sleep);
60 61
  }
} /* backoff_sleep */