Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

- 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 :(
  • Loading branch information...
commit 07d3df22257e612f4949e12d2b417e58b58611f9 1 parent 5625a02
@jordansissel jordansissel authored
Showing with 50 additions and 20 deletions.
  1. +45 −12 backoff.c
  2. +5 −8 backoff.h
View
57 backoff.c
@@ -1,27 +1,60 @@
-#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 */
View
13 backoff.h
@@ -1,19 +1,16 @@
#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,
Please sign in to comment.
Something went wrong with that request. Please try again.