changed the return code of mio_gettmrtmout() from -1/0 to 0/1 respectively to avoid unneeded error message manipulation

added mio_add_ntime() and mio_sub_ntime()
This commit is contained in:
hyung-hwan 2020-09-03 03:56:32 +00:00
parent 6f0b17e2e9
commit 5a05a6e9cd
6 changed files with 158 additions and 11 deletions

View File

@ -478,11 +478,18 @@ struct mio_ptl_t
#define MIO_SEC_TO_USEC(sec) ((sec) * MIO_USECS_PER_SEC)
#define MIO_USEC_TO_SEC(usec) ((usec) / MIO_USECS_PER_SEC)
#if defined(MIO_SIZEOF_INT64_T) && (MIO_SIZEOF_INT64_T > 0)
typedef mio_int64_t mio_ntime_sec_t;
#else
typedef mio_int32_t mio_ntime_sec_t;
#endif
typedef mio_int32_t mio_ntime_nsec_t;
typedef struct mio_ntime_t mio_ntime_t;
struct mio_ntime_t
{
mio_intptr_t sec;
mio_int32_t nsec; /* nanoseconds */
mio_ntime_sec_t sec;
mio_ntime_nsec_t nsec; /* nanoseconds */
};
#define MIO_INIT_NTIME(c,s,ns) (((c)->sec = (s)), ((c)->nsec = (ns)))

View File

@ -130,9 +130,15 @@ void mio_firetmrjobs (
);
/**
* The mio_gettmrtmout() function gets the remaining time until the first
* scheduled job is to be triggered. It stores in \a tmout the difference between
* the given time \a tm and the scheduled time and returns 1. If there is no
* job scheduled, it returns 0.
*/
int mio_gettmrtmout (
mio_t* mio,
const mio_ntime_t* tmbase,
const mio_ntime_t* tm,
mio_ntime_t* tmout
);

View File

@ -763,6 +763,35 @@ MIO_EXPORT mio_oow_t mio_utf8_to_uc (
mio_uch_t* uc
);
/* =========================================================================
* TIME CALCULATION WITH OVERFLOW/UNDERFLOW DETECTION
* ========================================================================= */
/**
* The mio_add_ntime() function adds two time structures pointed to by \a x and \a y
* and stores the result in the structure pointed to by \a z. If it detects overflow/
* underflow, it stores the largest/least possible value respectively.
* You may use the MIO_ADD_NTIME() macro if overflow/underflow check isn't needed.
*/
MIO_EXPORT void mio_add_ntime (
mio_ntime_t* z,
const mio_ntime_t* x,
const mio_ntime_t* y
);
/**
* The mio_sub_ntime() function subtracts the time value \a y from the time value \a x
* and stores the result in the structure pointed to by \a z. If it detects overflow/
* underflow, it stores the largest/least possible value respectively.
* You may use the MIO_SUB_NTIME() macro if overflow/underflow check isn't needed.
*/
MIO_EXPORT void mio_sub_ntime (
mio_ntime_t* z,
const mio_ntime_t* x,
const mio_ntime_t* y
);
/* =========================================================================
* BIT SWAP
* ========================================================================= */

View File

@ -757,7 +757,7 @@ int mio_exec (mio_t* mio)
/* wait on the multiplexer only if there is at least 1 active device */
mio_ntime_t tmout;
if (mio_gettmrtmout(mio, MIO_NULL, &tmout) <= -1)
if (mio_gettmrtmout(mio, MIO_NULL, &tmout) <= 0)
{
/* defaults to 0 or 1 second if timeout can't be acquired.
* if this timeout affects how fast the halted device will get killed.

View File

@ -190,11 +190,7 @@ int mio_gettmrtmout (mio_t* mio, const mio_ntime_t* tm, mio_ntime_t* tmout)
mio_ntime_t now;
/* time-out can't be calculated when there's no job scheduled */
if (mio->tmr.size <= 0)
{
mio_seterrbfmt (mio, MIO_ENOENT, "unable to compute timeout as no job is scheduled");
return -1;
}
if (mio->tmr.size <= 0) return 0; /* no scheduled job */
/* if the current time is not specified, get it from the system */
if (tm) now = *tm;
@ -202,8 +198,7 @@ int mio_gettmrtmout (mio_t* mio, const mio_ntime_t* tm, mio_ntime_t* tmout)
MIO_SUB_NTIME (tmout, &mio->tmr.jobs[0].when, &now);
if (tmout->sec < 0) MIO_CLEAR_NTIME (tmout);
return 0;
return 1; /* tmout is set */
}
mio_tmrjob_t* mio_gettmrjob (mio_t* mio, mio_tmridx_t index)

View File

@ -2103,3 +2103,113 @@ mio_bch_t* mio_dupbcstrs (mio_t* mio, const mio_bch_t* bcs[], mio_oow_t* bcslen)
return ptr;
}
/* ========================================================================= */
void mio_add_ntime (mio_ntime_t* z, const mio_ntime_t* x, const mio_ntime_t* y)
{
mio_ntime_sec_t xs, ys;
mio_ntime_nsec_t ns;
/*MIO_ASSERT (x->nsec >= 0 && x->nsec < MIO_NSECS_PER_SEC);
MIO_ASSERT (y->nsec >= 0 && y->nsec < MIO_NSECS_PER_SEC);*/
ns = x->nsec + y->nsec;
if (ns >= MIO_NSECS_PER_SEC)
{
ns = ns - MIO_NSECS_PER_SEC;
if (x->sec == MIO_TYPE_MAX(mio_ntime_sec_t))
{
if (y->sec >= 0) goto overflow;
xs = x->sec;
ys = y->sec + 1; /* this won't overflow */
}
else
{
xs = x->sec + 1; /* this won't overflow */
ys = y->sec;
}
}
else
{
xs = x->sec;
ys = y->sec;
}
if ((ys >= 1 && xs > MIO_TYPE_MAX(mio_ntime_sec_t) - ys) ||
(ys <= -1 && xs < MIO_TYPE_MIN(mio_ntime_sec_t) - ys))
{
if (xs >= 0)
{
overflow:
xs = MIO_TYPE_MAX(mio_ntime_sec_t);
ns = MIO_NSECS_PER_SEC - 1;
}
else
{
xs = MIO_TYPE_MIN(mio_ntime_sec_t);
ns = 0;
}
}
else
{
xs = xs + ys;
}
z->sec = xs;
z->nsec = ns;
}
void mio_sub_ntime (mio_ntime_t* z, const mio_ntime_t* x, const mio_ntime_t* y)
{
mio_ntime_sec_t xs, ys;
mio_ntime_nsec_t ns;
/*MIO_ASSERT (x->nsec >= 0 && x->nsec < MIO_NSECS_PER_SEC);
MIO_ASSERT (y->nsec >= 0 && y->nsec < MIO_NSECS_PER_SEC);*/
ns = x->nsec - y->nsec;
if (ns < 0)
{
ns = ns + MIO_NSECS_PER_SEC;
if (x->sec == MIO_TYPE_MIN(mio_ntime_sec_t))
{
if (y->sec <= 0) goto underflow;
xs = x->sec;
ys = y->sec - 1; /* this won't underflow */
}
else
{
xs = x->sec - 1; /* this won't underflow */
ys = y->sec;
}
}
else
{
xs = x->sec;
ys = y->sec;
}
if ((ys >= 1 && xs < MIO_TYPE_MIN(mio_ntime_sec_t) + ys) ||
(ys <= -1 && xs > MIO_TYPE_MAX(mio_ntime_sec_t) + ys))
{
if (xs >= 0)
{
xs = MIO_TYPE_MAX(mio_ntime_sec_t);
ns = MIO_NSECS_PER_SEC - 1;
}
else
{
underflow:
xs = MIO_TYPE_MIN(mio_ntime_sec_t);
ns = 0;
}
}
else
{
xs = xs - ys;
}
z->sec = xs;
z->nsec = ns;
}
/* ========================================================================= */