Commit 07d3df22 authored by Jordan Sissel's avatar Jordan Sissel

- switch from usleep/useconds_t to nanosleep/struct timespec.

  This was done because trying to get useconds_t/usleep to compile
  cleanly on OSX and Linux was a pain in the ass.
  Switching to struct timespec required writing a few math/compare
  functions for the timespec stuff. I don't know why POSIX didn't
  define any of these :(
parent 5625a023
#define _XOPEN_SOURCE 500 /* for useconds_t */
#include <stdio.h>
#include <unistd.h>
#include "backoff.h"
inline void backoff_init(struct backoff *b, useconds_t min, useconds_t max) {
b->max = max;
b->min = min;
#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 */
inline void backoff_init(struct backoff *b, struct timespec *min,
struct timespec *max) {
timespec_copy(min, &b->min);
timespec_copy(max, &b->max);
backoff_clear(b);
} /* backoff_init */
inline void backoff(struct backoff *b) {
//printf("Sleeping %f seconds\n", b->time / 1000000.0);
usleep(b->time);
//printf("Sleeping %ld.%09ld\n", b->sleep.tv_sec, b->sleep.tv_nsec);
nanosleep(&b->sleep, NULL);
/* Exponential backoff */
b->time <<= 1;
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);
/* Cap at 'max' time sleep */
if (b->time > b->max) {
b->time = b->max;
/* Cap at 'max' if sleep time exceeds it */
if (timespec_compare(&b->sleep, &b->max) > 0) {
timespec_copy(&b->max, &b->sleep);
}
} /* backoff_sleep */
inline void backoff_clear(struct backoff *b) {
b->time = b->min; /* 1000 microseconds == 1ms */
timespec_copy(&b->min, &b->sleep);
} /* backoff_clear */
#ifndef _BACKOFF_H_
#define _BACKOFF_H_
#define _XOPEN_SOURCE 500 /* for useconds_t */
#define _BSD_SOURCE /* also for useconds_t ? */
#include <unistd.h>
#include <sys/types.h>
#include <time.h>
struct backoff {
useconds_t max;
useconds_t min;
useconds_t time;
struct timespec max;
struct timespec min;
struct timespec sleep;
};
/* Initialize a backoff struct with a max value */
void backoff_init(struct backoff *b, useconds_t min, useconds_t max);
void backoff_init(struct backoff *b, struct timespec *min, struct timespec *max);
/* Execute a backoff. This will sleep for a time.
* The next backoff() call will sleep twice as long (or the max value,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment