2 つの入力ソケットの FIFO キューを維持するソケット プログラムを作成しています。サービスするキューを決定するとき、プログラムは各キューから最新のタイムスタンプを取得します。
2 つの構造体を比較するための信頼できる方法が必要timeval
です。を使用してみtimercmp()
ましたが、使用している gcc のバージョンではサポートされておらず、ドキュメントには関数が POSIX に準拠していないと記載されています。
私は何をすべきか?
timercmp()
libc(sys/time.h)の単なるマクロです:
# define timercmp(a, b, CMP) \
(((a)->tv_sec == (b)->tv_sec) ? \
((a)->tv_usec CMP (b)->tv_usec) : \
((a)->tv_sec CMP (b)->tv_sec))
必要な場合timersub()
:
# define timersub(a, b, result) \
do { \
(result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \
(result)->tv_usec = (a)->tv_usec - (b)->tv_usec; \
if ((result)->tv_usec < 0) { \
--(result)->tv_sec; \
(result)->tv_usec += 1000000; \
} \
} while (0)
グーグルはこの最初の結果timeval
を与えます。そのページから:
struct timeval または struct timespec 型の 2 つの値を減算する必要があることがよくあります。これを行う最良の方法は次のとおりです。tv_sec メンバーが unsigned 型である特殊なオペレーティング システムでも動作します。
/* Subtract the `struct timeval' values X and Y,
storing the result in RESULT.
Return 1 if the difference is negative, otherwise 0. */
int
timeval_subtract (result, x, y)
struct timeval *result, *x, *y;
{
/* Perform the carry for the later subtraction by updating y. */
if (x->tv_usec < y->tv_usec) {
int nsec = (y->tv_usec - x->tv_usec) / 1000000 + 1;
y->tv_usec -= 1000000 * nsec;
y->tv_sec += nsec;
}
if (x->tv_usec - y->tv_usec > 1000000) {
int nsec = (x->tv_usec - y->tv_usec) / 1000000;
y->tv_usec += 1000000 * nsec;
y->tv_sec -= nsec;
}
/* Compute the time remaining to wait.
tv_usec is certainly positive. */
result->tv_sec = x->tv_sec - y->tv_sec;
result->tv_usec = x->tv_usec - y->tv_usec;
/* Return 1 if result is negative. */
return x->tv_sec < y->tv_sec;
}
これは少し異なりますが、関連するロジックを明確に示していると思います。私は C でいくつかの MSP430 コードに取り組んでおり、timeval に非常によく似たタイムスタンプ構造体を持っていますが、usecs ではなく nsecs を使用しています。
このコードはすべてを正に保つので、unsigned int は正常に機能し、オーバーフローを回避します (私はそう思います)。もちろん、結果を除いて、渡されるタイムスタンプ/タイムバルも変更しません。
typedef struct timestamp {
int32_t secs;
int32_t nsecs;
} timestamp_t;
int timestamp_sub(timestamp_t * x, timestamp_t * y, timestamp_t * result){
// returns 1 if difference is negative, 0 otherwise
// result is the absolute value of the difference between x and y
negative = 0;
if( x->secs > y->secs ){
if( x->nsecs > y->nsecs ){
result->secs = x->secs - y->secs;
result->nsecs = x->nsecs - y->nsecs;
}else{
result->secs = x->secs - y->secs - 1;
result->nsecs = (1000*1000*1000) - y->nsecs + x->nsecs;
}
}else{
if( x->secs == y->secs ){
result->secs = 0;
if( x->nsecs > y->nsecs ){
result->nsecs = x->nsecs - y->nsecs;
}else{
negative = 1;
result->nsecs = y->nsecs - x->nsecs;
}
}else{
negative = 1;
if( x->nsecs > y->nsecs ){
result->secs = y->secs - x->secs - 1;
result->nsecs = (1000*1000*1000) - x->nsecs + y->nsecs;
}else{
result->secs = y->secs - x->secs;
result->nsecs = y->nsecs - x->nsecs;
}
}
}
return negative;
}