]> sigrok.org Git - libserialport.git/commitdiff
Move repetitive timeout code into helper functions.
authorMartin Ling <redacted>
Fri, 3 Jan 2020 22:42:00 +0000 (22:42 +0000)
committerMartin Ling <redacted>
Mon, 20 Jan 2020 04:31:59 +0000 (04:31 +0000)
serialport.c

index 781bd279d80208f33a1f93d511ff5bbb0cb3b99f..1a9b4415438422afebc989a6b20cc6f6767a32a7 100644 (file)
@@ -63,9 +63,18 @@ struct time {
        struct timeval tv;
 };
 
+struct timeout {
+       unsigned int ms;
+       struct time start, delta, now, end;
+       struct timeval delta_tv;
+       bool overflow;
+};
+
 #define TIME_ZERO {.tv = {0, 0}}
 #define TIME_MS(ms) {.tv = {ms / 1000, (ms % 1000) * 1000}}
 
+const struct time max_delta = TIME_MS(INT_MAX);
+
 static void time_get(struct time *time)
 {
 #ifdef HAVE_CLOCK_GETTIME
@@ -119,6 +128,53 @@ static unsigned int time_as_ms(const struct time *time)
        return time->tv.tv_sec * 1000 + time->tv.tv_usec / 1000;
 }
 
+static void timeout_start(struct timeout *timeout, unsigned int timeout_ms)
+{
+       timeout->ms = timeout_ms;
+
+       timeout->overflow = (timeout->ms > INT_MAX);
+
+       /* Get time at start of operation. */
+       time_get(&timeout->start);
+       /* Define duration of timeout. */
+       time_set_ms(&timeout->delta, timeout_ms);
+       /* Calculate time at which we should give up. */
+       time_add(&timeout->start, &timeout->delta, &timeout->end);
+}
+
+static bool timeout_check(struct timeout *timeout)
+{
+       if (timeout->ms == 0)
+               return false;
+
+       time_get(&timeout->now);
+       time_sub(&timeout->end, &timeout->now, &timeout->delta);
+       if ((timeout->overflow = time_greater(&timeout->delta, &max_delta)))
+               timeout->delta = max_delta;
+
+       return time_greater(&timeout->now, &timeout->end);
+}
+
+static struct timeval *timeout_timeval(struct timeout *timeout)
+{
+       if (timeout->ms == 0)
+               return NULL;
+
+       time_as_timeval(&timeout->delta, &timeout->delta_tv);
+
+       return &timeout->delta_tv;
+}
+
+static unsigned int timeout_remaining_ms(struct timeout *timeout)
+{
+       if (timeout->ms == 0)
+               return -1;
+       else if (timeout->overflow)
+               return INT_MAX;
+       else
+               return time_as_ms(&timeout->delta);
+}
+
 #endif
 
 SP_API enum sp_return sp_get_port_by_name(const char *portname, struct sp_port **port_ptr)
@@ -887,19 +943,12 @@ SP_API enum sp_return sp_blocking_write(struct sp_port *port, const void *buf,
 #else
        size_t bytes_written = 0;
        unsigned char *ptr = (unsigned char *) buf;
-       struct time start, delta, now, end = TIME_ZERO;
+       struct timeout timeout;
        int started = 0;
        fd_set fds;
        int result;
 
-       if (timeout_ms) {
-               /* Get time at start of operation. */
-               time_get(&start);
-               /* Define duration of timeout. */
-               time_set_ms(&delta, timeout_ms);
-               /* Calculate time at which we should give up. */
-               time_add(&start, &delta, &end);
-       }
+       timeout_start(&timeout, timeout_ms);
 
        FD_ZERO(&fds);
        FD_SET(port->fd, &fds);
@@ -911,16 +960,10 @@ SP_API enum sp_return sp_blocking_write(struct sp_port *port, const void *buf,
                 * to avoid any issues if a short timeout is reached before
                 * select() is even run.
                 */
-               struct timeval tv;
-               if (timeout_ms && started) {
-                       time_get(&now);
-                       if (time_greater(&now, &end))
-                               /* Timeout has expired. */
-                               break;
-                       time_sub(&end, &now, &delta);
-                       time_as_timeval(&delta, &tv);
-               }
-               result = select(port->fd + 1, NULL, &fds, NULL, timeout_ms ? &tv : NULL);
+               if (started && timeout_check(&timeout))
+                       break;
+
+               result = select(port->fd + 1, NULL, &fds, NULL, timeout_timeval(&timeout));
                started = 1;
                if (result < 0) {
                        if (errno == EINTR) {
@@ -1108,19 +1151,12 @@ SP_API enum sp_return sp_blocking_read(struct sp_port *port, void *buf,
 #else
        size_t bytes_read = 0;
        unsigned char *ptr = (unsigned char *) buf;
-       struct time start, delta, now, end = TIME_ZERO;
+       struct timeout timeout;
        int started = 0;
        fd_set fds;
        int result;
 
-       if (timeout_ms) {
-               /* Get time at start of operation. */
-               time_get(&start);
-               /* Define duration of timeout. */
-               time_set_ms(&delta, timeout_ms);
-               /* Calculate time at which we should give up. */
-               time_add(&start, &delta, &end);
-       }
+       timeout_start(&timeout, timeout_ms);
 
        FD_ZERO(&fds);
        FD_SET(port->fd, &fds);
@@ -1132,16 +1168,11 @@ SP_API enum sp_return sp_blocking_read(struct sp_port *port, void *buf,
                 * to avoid any issues if a short timeout is reached before
                 * select() is even run.
                 */
-               struct timeval tv;
-               if (timeout_ms && started) {
-                       time_get(&now);
-                       if (time_greater(&now, &end))
-                               /* Timeout has expired. */
-                               break;
-                       time_sub(&end, &now, &delta);
-                       time_as_timeval(&delta, &tv);
-               }
-               result = select(port->fd + 1, &fds, NULL, NULL, timeout_ms ? &tv : NULL);
+               if (started && timeout_check(&timeout))
+                       /* Timeout has expired. */
+                       break;
+
+               result = select(port->fd + 1, &fds, NULL, NULL, timeout_timeval(&timeout));
                started = 1;
                if (result < 0) {
                        if (errno == EINTR) {
@@ -1246,19 +1277,12 @@ SP_API enum sp_return sp_blocking_read_next(struct sp_port *port, void *buf,
 
 #else
        size_t bytes_read = 0;
-       struct time start, delta, now, end = TIME_ZERO;
+       struct timeout timeout;
        int started = 0;
        fd_set fds;
        int result;
 
-       if (timeout_ms) {
-               /* Get time at start of operation. */
-               time_get(&start);
-               /* Define duration of timeout. */
-               time_set_ms(&delta, timeout_ms);
-               /* Calculate time at which we should give up. */
-               time_add(&start, &delta, &end);
-       }
+       timeout_start(&timeout, timeout_ms);
 
        FD_ZERO(&fds);
        FD_SET(port->fd, &fds);
@@ -1270,16 +1294,11 @@ SP_API enum sp_return sp_blocking_read_next(struct sp_port *port, void *buf,
                 * to avoid any issues if a short timeout is reached before
                 * select() is even run.
                 */
-               struct timeval tv;
-               if (timeout_ms && started) {
-                       time_get(&now);
-                       if (time_greater(&now, &end))
-                               /* Timeout has expired. */
-                               break;
-                       time_sub(&end, &now, &delta);
-                       time_as_timeval(&delta, &tv);
-               }
-               result = select(port->fd + 1, &fds, NULL, NULL, timeout_ms ? &tv : NULL);
+               if (started && timeout_check(&timeout))
+                       /* Timeout has expired. */
+                       break;
+
+               result = select(port->fd + 1, &fds, NULL, NULL, timeout_timeval(&timeout));
                started = 1;
                if (result < 0) {
                        if (errno == EINTR) {
@@ -1530,10 +1549,8 @@ SP_API enum sp_return sp_wait(struct sp_event_set *event_set,
 
        RETURN_OK();
 #else
-       struct time start, delta, now, end = TIME_ZERO;
-       const struct time max_delta = TIME_MS(INT_MAX);
-       int started = 0, timeout_overflow = 0;
-       int result, timeout_remaining_ms;
+       struct timeout timeout;
+       int started = 0, result;
        struct pollfd *pollfds;
        unsigned int i;
 
@@ -1552,14 +1569,7 @@ SP_API enum sp_return sp_wait(struct sp_event_set *event_set,
                        pollfds[i].events |= POLLERR;
        }
 
-       if (timeout_ms) {
-               /* Get time at start of operation. */
-               time_get(&start);
-               /* Define duration of timeout. */
-               time_set_ms(&delta, timeout_ms);
-               /* Calculate time at which we should give up. */
-               time_add(&start, &delta, &end);
-       }
+       timeout_start(&timeout, timeout_ms);
 
        /* Loop until an event occurs. */
        while (1) {
@@ -1568,24 +1578,12 @@ SP_API enum sp_return sp_wait(struct sp_event_set *event_set,
                 * to avoid any issues if a short timeout is reached before
                 * poll() is even run.
                 */
-               if (!timeout_ms) {
-                       timeout_remaining_ms = -1;
-               } else if (!started) {
-                       timeout_overflow = (timeout_ms > INT_MAX);
-                       timeout_remaining_ms = timeout_overflow ? INT_MAX : timeout_ms;
-               } else {
-                       time_get(&now);
-                       if (time_greater(&now, &end)) {
-                               DEBUG("Wait timed out");
-                               break;
-                       }
-                       time_sub(&end, &now, &delta);
-                       if ((timeout_overflow = time_greater(&delta, &max_delta)))
-                               delta = max_delta;
-                       timeout_remaining_ms = time_as_ms(&delta);
+               if (started && timeout_check(&timeout)) {
+                       DEBUG("Wait timed out");
+                       break;
                }
 
-               result = poll(pollfds, event_set->count, timeout_remaining_ms);
+               result = poll(pollfds, event_set->count, timeout_remaining_ms(&timeout));
                started = 1;
 
                if (result < 0) {
@@ -1598,7 +1596,7 @@ SP_API enum sp_return sp_wait(struct sp_event_set *event_set,
                        }
                } else if (result == 0) {
                        DEBUG("poll() timed out");
-                       if (!timeout_overflow)
+                       if (!timeout.overflow)
                                break;
                } else {
                        DEBUG("poll() completed");