mirror of
https://github.com/wjwwood/serial.git
synced 2026-01-23 04:04:54 +08:00
Create key operator/manipulation functions for timespecs, add them to new unix-timespec.h helper header.
This commit is contained in:
parent
10f2fc60fb
commit
7a61d4545b
122
include/serial/impl/unix-timespec.h
Normal file
122
include/serial/impl/unix-timespec.h
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
/*!
|
||||||
|
* \file serial/impl/unit-timespec.h
|
||||||
|
* \author Mike Purvis <mpurvis@clearpathrobotics.com>
|
||||||
|
* \version 0.1
|
||||||
|
*
|
||||||
|
* \section LICENSE
|
||||||
|
*
|
||||||
|
* The MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013 William Woodall
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
* Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
* DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* \section DESCRIPTION
|
||||||
|
*
|
||||||
|
* Provides helper and operator functions for concisely and reliably handling
|
||||||
|
* timespec instances on unix platforms.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SERIAL_IMPL_UNIX_TIMESPEC_H
|
||||||
|
#define SERIAL_IMPL_UNIX_TIMESPEC_H
|
||||||
|
|
||||||
|
/*! Smooth over platform variances in getting an accurate timespec
|
||||||
|
* representing the present moment. */
|
||||||
|
static inline void
|
||||||
|
get_time_now (struct timespec &time)
|
||||||
|
{
|
||||||
|
# ifdef __MACH__ // OS X does not have clock_gettime, use clock_get_time
|
||||||
|
clock_serv_t cclock;
|
||||||
|
mach_timespec_t mts;
|
||||||
|
host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock);
|
||||||
|
clock_get_time(cclock, &mts);
|
||||||
|
mach_port_deallocate(mach_task_self(), cclock);
|
||||||
|
time.tv_sec = mts.tv_sec;
|
||||||
|
time.tv_nsec = mts.tv_nsec;
|
||||||
|
# else
|
||||||
|
clock_gettime(CLOCK_REALTIME, &time);
|
||||||
|
# endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Simple function to normalize the tv_nsec field to [0..1e9), carrying
|
||||||
|
* the remainder into the tv_sec field. This will not protect against the
|
||||||
|
* possibility of an overflow in the nsec field--proceed with caution. */
|
||||||
|
static inline void
|
||||||
|
normalize(struct timespec* ts) {
|
||||||
|
while (ts->tv_nsec < 0) {
|
||||||
|
ts->tv_nsec += 1e9;
|
||||||
|
ts->tv_sec -= 1;
|
||||||
|
}
|
||||||
|
while (ts->tv_nsec >= 1e9) {
|
||||||
|
ts->tv_nsec -= 1e9;
|
||||||
|
ts->tv_sec += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Return a timespec which is the sum of two other timespecs. */
|
||||||
|
static inline struct timespec
|
||||||
|
operator+ (const struct timespec &a, const struct timespec &b) {
|
||||||
|
struct timespec result = { a.tv_sec + b.tv_sec,
|
||||||
|
a.tv_nsec + b.tv_nsec };
|
||||||
|
normalize(&result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Return a timespec which is the difference of two other timespecs. */
|
||||||
|
static inline struct timespec
|
||||||
|
operator- (const struct timespec &a, const struct timespec &b) {
|
||||||
|
struct timespec result = { a.tv_sec - b.tv_sec,
|
||||||
|
a.tv_nsec - b.tv_nsec };
|
||||||
|
normalize(&result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Return a timespec which is a multiplication of a timespec and a positive
|
||||||
|
* integer. No overflow protection-- not suitable for multiplications with
|
||||||
|
* large carries, eg a <1s timespec multiplied by a large enough integer
|
||||||
|
* that the result is muliple seconds. */
|
||||||
|
static inline struct timespec
|
||||||
|
operator* (const struct timespec &ts, const size_t mul) {
|
||||||
|
struct timespec result = { ts.tv_sec * mul,
|
||||||
|
ts.tv_nsec * mul };
|
||||||
|
normalize(&result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Return whichever of two timespecs represents the shortest or most
|
||||||
|
* negative duration. */
|
||||||
|
static inline struct timespec
|
||||||
|
min (const struct timespec &a, const struct timespec &b) {
|
||||||
|
if (a.tv_sec < b.tv_sec
|
||||||
|
|| (a.tv_sec == b.tv_sec && a.tv_nsec < b.tv_nsec)) {
|
||||||
|
return a;
|
||||||
|
} else {
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Return a timespec set from a provided number of milliseconds. */
|
||||||
|
static struct timespec
|
||||||
|
timespec_from_millis(const size_t millis) {
|
||||||
|
struct timespec result = { 0, millis * 1000000 };
|
||||||
|
normalize(&result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@ -122,7 +122,7 @@ public:
|
|||||||
getPort () const;
|
getPort () const;
|
||||||
|
|
||||||
void
|
void
|
||||||
setTimeout (Timeout &timeout);
|
setTimeout (const Timeout &timeout);
|
||||||
|
|
||||||
Timeout
|
Timeout
|
||||||
getTimeout () const;
|
getTimeout () const;
|
||||||
@ -180,7 +180,13 @@ private:
|
|||||||
bool xonxoff_;
|
bool xonxoff_;
|
||||||
bool rtscts_;
|
bool rtscts_;
|
||||||
|
|
||||||
Timeout timeout_; // Timeout for read operations
|
Timeout timeout_; // Timeouts for read/write operations
|
||||||
|
struct timespec inter_byte_timeout_;
|
||||||
|
struct timespec read_timeout_constant_;
|
||||||
|
struct timespec read_timeout_multiplier_;
|
||||||
|
struct timespec write_timeout_constant_;
|
||||||
|
struct timespec write_timeout_multiplier_;
|
||||||
|
|
||||||
unsigned long baudrate_; // Baudrate
|
unsigned long baudrate_; // Baudrate
|
||||||
|
|
||||||
parity_t parity_; // Parity
|
parity_t parity_; // Parity
|
||||||
|
|||||||
@ -27,6 +27,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "serial/impl/unix.h"
|
#include "serial/impl/unix.h"
|
||||||
|
#include "serial/impl/unix-timespec.h"
|
||||||
|
|
||||||
#ifndef TIOCINQ
|
#ifndef TIOCINQ
|
||||||
#ifdef FIONREAD
|
#ifdef FIONREAD
|
||||||
@ -396,74 +397,6 @@ Serial::SerialImpl::available ()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void
|
|
||||||
get_time_now (struct timespec &time)
|
|
||||||
{
|
|
||||||
# ifdef __MACH__ // OS X does not have clock_gettime, use clock_get_time
|
|
||||||
clock_serv_t cclock;
|
|
||||||
mach_timespec_t mts;
|
|
||||||
host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock);
|
|
||||||
clock_get_time(cclock, &mts);
|
|
||||||
mach_port_deallocate(mach_task_self(), cclock);
|
|
||||||
time.tv_sec = mts.tv_sec;
|
|
||||||
time.tv_nsec = mts.tv_nsec;
|
|
||||||
# else
|
|
||||||
clock_gettime(CLOCK_REALTIME, &time);
|
|
||||||
# endif
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void
|
|
||||||
diff_timespec (timespec &start, timespec &end, timespec &result) {
|
|
||||||
if (start.tv_sec > end.tv_sec) {
|
|
||||||
throw SerialException ("Timetravel, start time later than end time.");
|
|
||||||
}
|
|
||||||
result.tv_sec = end.tv_sec - start.tv_sec;
|
|
||||||
result.tv_nsec = end.tv_nsec - start.tv_nsec;
|
|
||||||
if (result.tv_nsec < 0) {
|
|
||||||
result.tv_nsec = 1e9 - result.tv_nsec;
|
|
||||||
result.tv_sec -= 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! Simple function to normalize the tv_nsec field to [0..1e9), carrying
|
|
||||||
* the remainder into the tv_sec field. */
|
|
||||||
void normalize(timespec* ts) {
|
|
||||||
while (ts->tv_nsec < 0) {
|
|
||||||
ts->tv_nsec += 1e9;
|
|
||||||
ts->tv_sec -= 1;
|
|
||||||
}
|
|
||||||
while (ts->tv_nsec >= 1e9) {
|
|
||||||
ts->tv_nsec -= 1e9;
|
|
||||||
ts->tv_sec += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inline struct timespec
|
|
||||||
operator+ (const struct timespec &a, const struct timespec &b) {
|
|
||||||
struct timespec result = { a.tv_sec + b.tv_sec,
|
|
||||||
a.tv_nsec + b.tv_nsec };
|
|
||||||
normalize(&result);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline struct timespec
|
|
||||||
operator- (const struct timespec &a, const struct timespec &b) {
|
|
||||||
struct timespec result = { a.tv_sec - b.tv_sec,
|
|
||||||
a.tv_nsec - b.tv_nsec };
|
|
||||||
normalize(&result);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline struct timespec
|
|
||||||
min (const struct timespec &a, const struct timespec &b) {
|
|
||||||
if (a.tv_sec < b.tv_sec
|
|
||||||
|| (a.tv_sec == b.tv_sec && a.tv_nsec < b.tv_nsec)) {
|
|
||||||
return a;
|
|
||||||
} else {
|
|
||||||
return b;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t
|
size_t
|
||||||
Serial::SerialImpl::read (uint8_t *buf, size_t size)
|
Serial::SerialImpl::read (uint8_t *buf, size_t size)
|
||||||
{
|
{
|
||||||
@ -611,8 +544,7 @@ Serial::SerialImpl::write (const uint8_t *data, size_t length)
|
|||||||
// Calculate difference and update the structure
|
// Calculate difference and update the structure
|
||||||
get_time_now(end);
|
get_time_now(end);
|
||||||
// Calculate the time select took
|
// Calculate the time select took
|
||||||
struct timespec diff;
|
struct timespec diff(end - start);
|
||||||
diff_timespec(start, end, diff);
|
|
||||||
// Update the timeout
|
// Update the timeout
|
||||||
if (timeout.tv_sec <= diff.tv_sec) {
|
if (timeout.tv_sec <= diff.tv_sec) {
|
||||||
timeout.tv_sec = 0;
|
timeout.tv_sec = 0;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user