1
0
mirror of https://github.com/stefanocasazza/ULib.git synced 2025-09-28 19:05:55 +08:00
This commit is contained in:
stefanocasazza 2015-11-25 18:28:45 +01:00
parent 7886a7954e
commit 7731ca80a0
13 changed files with 309 additions and 230 deletions

View File

@ -17,21 +17,21 @@
// Design by contract - if (expr == false) then stop
#ifdef DEBUG
# define U_ASSERT(expr) { int _status_ = UTrace::suspend(); U_INTERNAL_ASSERT(expr); UTrace::resume(_status_); }
# define U_ASSERT_MINOR(a,b) { int _status_ = UTrace::suspend(); U_INTERNAL_ASSERT_MINOR(a,b); UTrace::resume(_status_); }
# define U_ASSERT_MAJOR(a,b) { int _status_ = UTrace::suspend(); U_INTERNAL_ASSERT_MAJOR(a,b); UTrace::resume(_status_); }
# define U_ASSERT_EQUALS(a,b) { int _status_ = UTrace::suspend(); U_INTERNAL_ASSERT_EQUALS(a,b); UTrace::resume(_status_); }
# define U_ASSERT_DIFFERS(a,b) { int _status_ = UTrace::suspend(); U_INTERNAL_ASSERT_DIFFERS(a,b); UTrace::resume(_status_); }
# define U_ASSERT_POINTER(ptr) { int _status_ = UTrace::suspend(); U_INTERNAL_ASSERT_POINTER(ptr); UTrace::resume(_status_); }
# define U_ASSERT_RANGE(a,x,b) { int _status_ = UTrace::suspend(); U_INTERNAL_ASSERT_RANGE(a,x,b); UTrace::resume(_status_); }
# define U_ASSERT(expr) { UTrace::suspend(); U_INTERNAL_ASSERT(expr); UTrace::resume(); }
# define U_ASSERT_MINOR(a,b) { UTrace::suspend(); U_INTERNAL_ASSERT_MINOR(a,b); UTrace::resume(); }
# define U_ASSERT_MAJOR(a,b) { UTrace::suspend(); U_INTERNAL_ASSERT_MAJOR(a,b); UTrace::resume(); }
# define U_ASSERT_EQUALS(a,b) { UTrace::suspend(); U_INTERNAL_ASSERT_EQUALS(a,b); UTrace::resume(); }
# define U_ASSERT_DIFFERS(a,b) { UTrace::suspend(); U_INTERNAL_ASSERT_DIFFERS(a,b); UTrace::resume(); }
# define U_ASSERT_POINTER(ptr) { UTrace::suspend(); U_INTERNAL_ASSERT_POINTER(ptr); UTrace::resume(); }
# define U_ASSERT_RANGE(a,x,b) { UTrace::suspend(); U_INTERNAL_ASSERT_RANGE(a,x,b); UTrace::resume(); }
# define U_ASSERT_MSG(expr,info) { int _status_ = UTrace::suspend(); U_INTERNAL_ASSERT_MSG(expr,info); UTrace::resume(_status_); }
# define U_ASSERT_MINOR_MSG(a,b,info) { int _status_ = UTrace::suspend(); U_INTERNAL_ASSERT_MINOR_MSG(a,b,info); UTrace::resume(_status_); }
# define U_ASSERT_MAJOR_MSG(a,b,info) { int _status_ = UTrace::suspend(); U_INTERNAL_ASSERT_MAJOR_MSG(a,b,info); UTrace::resume(_status_); }
# define U_ASSERT_EQUALS_MSG(a,b,info) { int _status_ = UTrace::suspend(); U_INTERNAL_ASSERT_EQUALS_MSG(a,b,info); UTrace::resume(_status_); }
# define U_ASSERT_DIFFERS_MSG(a,b,info) { int _status_ = UTrace::suspend(); U_INTERNAL_ASSERT_DIFFERS_MSG(a,b,info); UTrace::resume(_status_); }
# define U_ASSERT_POINTER_MSG(ptr,info) { int _status_ = UTrace::suspend(); U_INTERNAL_ASSERT_POINTER_MSG(ptr,info); UTrace::resume(_status_); }
# define U_ASSERT_RANGE_MSG(a,x,b,info) { int _status_ = UTrace::suspend(); U_INTERNAL_ASSERT_RANGE_MSG(a,x,b,info); UTrace::resume(_status_); }
# define U_ASSERT_MSG(expr,info) { UTrace::suspend(); U_INTERNAL_ASSERT_MSG(expr,info); UTrace::resume(); }
# define U_ASSERT_MINOR_MSG(a,b,info) { UTrace::suspend(); U_INTERNAL_ASSERT_MINOR_MSG(a,b,info); UTrace::resume(); }
# define U_ASSERT_MAJOR_MSG(a,b,info) { UTrace::suspend(); U_INTERNAL_ASSERT_MAJOR_MSG(a,b,info); UTrace::resume(); }
# define U_ASSERT_EQUALS_MSG(a,b,info) { UTrace::suspend(); U_INTERNAL_ASSERT_EQUALS_MSG(a,b,info); UTrace::resume(); }
# define U_ASSERT_DIFFERS_MSG(a,b,info) { UTrace::suspend(); U_INTERNAL_ASSERT_DIFFERS_MSG(a,b,info); UTrace::resume(); }
# define U_ASSERT_POINTER_MSG(ptr,info) { UTrace::suspend(); U_INTERNAL_ASSERT_POINTER_MSG(ptr,info); UTrace::resume(); }
# define U_ASSERT_RANGE_MSG(a,x,b,info) { UTrace::suspend(); U_INTERNAL_ASSERT_RANGE_MSG(a,x,b,info); UTrace::resume(); }
#elif defined(U_TEST)
# define U_ASSERT(expr) U_INTERNAL_ASSERT(expr)
# define U_ASSERT_MINOR(a,b) U_INTERNAL_ASSERT_MINOR(a,b)
@ -85,20 +85,20 @@
// NB: U_DUMP, U_SYSCALL() and U_RETURN() depend on presence of U_TRACE()
# define U_INTERNAL_DUMP(args...) { if (utr.active[0]) u_trace_dump(args); }
# define U_DUMP(args...) { if (utr.active[0]) { int _status_ = UTrace::suspend(); u_trace_dump(args); UTrace::resume(_status_); } }
# define U_SYSCALL(name,format,args...) (utr.trace_syscall("::"#name"(" format ")" , ##args), \
utr.trace_sysreturn_type(::name(args)))
# define U_INTERNAL_DUMP(args...) { if (utr.active[0]) u_trace_dump(args); }
# define U_DUMP(args...) { if (utr.active[0]) { UTrace::suspend(); u_trace_dump(args); UTrace::resume(); } }
# define U_SYSCALL_NO_PARAM(name) (utr.trace_syscall("::"#name"()",0), \
utr.trace_sysreturn_type(::name()))
# define U_SYSCALL_VOID(name,format,args...) {utr.trace_syscall("::"#name"(" format ")" , ##args); \
name(args); utr.trace_sysreturn(false,0);}
# define U_SYSCALL_VOID_NO_PARAM(name) { utr.trace_syscall("::"#name"()",0); \
name(); utr.trace_sysreturn(false,0); }
# define U_SYSCALL_VOID_NO_PARAM(name) {utr.trace_syscall("::"#name"()",0); \
name(); utr.trace_sysreturn(false,0);}
# define U_SYSCALL(name,format,args...) (UTrace::suspend(), utr.trace_syscall("::"#name"(" format ")" , ##args), \
UTrace::resume(), utr.trace_sysreturn_type(::name(args)))
# define U_SYSCALL_VOID(name,format,args...) { UTrace::suspend(); utr.trace_syscall("::"#name"(" format ")" , ##args); \
UTrace::resume(); ::name(args); utr.trace_sysreturn(false,0); }
# define U_RETURN(r) return (utr.trace_return_type((r)))
# define U_RETURN_STRING(str) {U_INTERNAL_ASSERT((str).invariant()); return (utr.trace_return("%V",(str).rep),(str));}

View File

@ -51,6 +51,8 @@ typedef const unsigned char* pcuchar_t;
// typedef int (*x11error_t) (void*, void*);
// typedef int (*x11IOerror_t)(void*);
class UCrono;
class U_EXPORT UTrace {
public:
@ -121,13 +123,16 @@ public:
U_MANAGE_SYSRETURN_VALUE(tdbdata_t, "%J", false)
#endif
static int suspend() { int status = u_trace_suspend; u_trace_suspend = 1; return status; }
static void resume(int status) { u_trace_suspend = status; }
static void resume() { u_trace_suspend = status; }
static void suspend() { status = u_trace_suspend; u_trace_suspend = 1; }
private:
char buffer_trace[1019], buffer_syscall[1019];
uint32_t buffer_trace_len, buffer_syscall_len;
static int status;
static UCrono* time_syscall_read_or_write;
void set(int level) U_NO_EXPORT;
};

View File

@ -16,6 +16,8 @@
#include <ulib/timeval.h>
class UTimer;
class UNotifier;
#ifdef USE_LIBEVENT
template <class T> class UTimerEv;
#endif
@ -25,48 +27,24 @@ public:
struct timeval ctime;
void reset() { ctime.tv_sec = ctime.tv_usec = 0L; }
UEventTime(long sec = 0L, long usec = 1L);
UEventTime(long sec = 0L, long micro_sec = 1L);
virtual ~UEventTime();
bool operator<(const UEventTime& t) const __pure;
// SERVICES
void setTime(long timeoutMS)
bool isExpired() const __pure
{
U_TRACE(0, "UEventTime::setTime(%ld)", timeoutMS)
setCurrentTime();
UTimeVal::setMilliSecond(timeoutMS);
}
void setCurrentTime()
{
U_TRACE_NO_PARAM(1, "UEventTime::setCurrentTime()")
U_TRACE_NO_PARAM(0, "UEventTime::isExpired()")
U_CHECK_MEMORY
(void) U_SYSCALL(gettimeofday, "%p,%p", &ctime, 0);
U_INTERNAL_DUMP("ctime = { %ld %6ld }", ctime.tv_sec, ctime.tv_usec)
}
time_t expire() const { return (ctime.tv_sec + tv_sec); }
bool isExpired(long tolerance) const __pure
{
U_TRACE(0, "UEventTime::isExpired(%ld)", tolerance)
U_CHECK_MEMORY
long t1 = expire(),
diff1 = t1 - u_now->tv_sec,
long diff1 = ctime.tv_sec + tv_sec - u_now->tv_sec,
diff2 = ctime.tv_usec + tv_usec - u_now->tv_usec;
U_INTERNAL_DUMP("this = { %ld %6ld }, diff1 = %ld diff2 = %ld", t1, ctime.tv_usec + tv_usec, diff1, diff2)
U_INTERNAL_DUMP("this = { %ld %6ld }, diff1 = %ld diff2 = %ld", ctime.tv_sec + tv_sec,
ctime.tv_usec + tv_usec, diff1, diff2)
if ( diff1 < 0 ||
(diff1 == 0 &&
@ -75,71 +53,31 @@ public:
U_RETURN(true);
}
long diff = (diff1 * 1000L) +
(diff2 / 1000L);
ms = (diff1 * 1000L) +
(diff2 / 1000L);
U_INTERNAL_DUMP("diff = %ld", diff)
U_INTERNAL_DUMP("ms = %ld", ms)
if (diff <= tolerance) U_RETURN(true);
U_ASSERT(checkMilliSecond())
U_RETURN(false);
}
bool isOld() const __pure { return isExpired(0); }
bool isExpired() const __pure { return isExpired(UTimeVal::getTolerance()); }
void setTimerVal(struct timeval* it_value)
bool isExpiredWithTolerance() const __pure
{
U_TRACE(0, "UEventTime::setTimerVal(%p)", it_value)
U_TRACE_NO_PARAM(0, "UEventTime::isExpiredWithTolerance()")
U_CHECK_MEMORY
if (isExpired() == false)
{
U_ASSERT(checkTolerance())
it_value->tv_sec = ctime.tv_sec + tv_sec - u_now->tv_sec;
it_value->tv_usec = ctime.tv_usec + tv_usec - u_now->tv_usec;
if (ms > tolerance) U_RETURN(false);
}
UTimeVal::adjust(&(it_value->tv_sec), &(it_value->tv_usec));
U_INTERNAL_DUMP("it_value = { %ld %6ld }", it_value->tv_sec, it_value->tv_usec)
U_INTERNAL_ASSERT(it_value->tv_sec >= 0)
U_INTERNAL_ASSERT(it_value->tv_usec >= 0)
U_RETURN(true);
}
long getTimerVal()
{
U_TRACE_NO_PARAM(0, "UEventTime::getTimerVal()")
U_CHECK_MEMORY
long ms = ((ctime.tv_sec + tv_sec - u_now->tv_sec) * 1000L) +
((ctime.tv_usec + tv_usec - u_now->tv_usec) / 1000L);
U_RETURN(ms);
}
struct timespec* getTimerValSpec()
{
U_TRACE_NO_PARAM(0, "UEventTime::getTimerValSpec()")
U_CHECK_MEMORY
/**
* struct timespec {
* time_t tv_sec; // seconds
* long tv_nsec; // nanoseconds
* };
*/
long ns = ((ctime.tv_sec + tv_sec - u_now->tv_sec) * 1000000000L) +
((ctime.tv_usec + tv_usec - u_now->tv_usec) * 1000L);
timeout.tv_sec = ns / 1000000000L;
timeout.tv_nsec = ns % 1000000000L;
U_INTERNAL_DUMP("timeout = { %ld %9ld }", timeout.tv_sec, timeout.tv_nsec)
U_RETURN_POINTER(&timeout, struct timespec);
}
time_t expire() const { return (ctime.tv_sec + tv_sec); }
// -------------------------------------------
// method VIRTUAL to define
@ -158,19 +96,162 @@ public:
#ifdef U_STDCPP_ENABLE
friend U_EXPORT ostream& operator<<(ostream& os, const UEventTime& t);
# ifdef DEBUG
# ifdef DEBUG
const char* dump(bool reset) const;
# endif
# endif
#endif
private:
static struct timespec timeout;
protected:
long tolerance;
static long ms;
static struct timeval timeout1;
static struct timespec timeout2;
void setCurrentTime()
{
U_TRACE_NO_PARAM(1, "UEventTime::setCurrentTime()")
U_CHECK_MEMORY
(void) U_SYSCALL(gettimeofday, "%p,%p", &ctime, 0);
U_INTERNAL_DUMP("ctime = { %ld %6ld }", ctime.tv_sec, ctime.tv_usec)
}
void setTime(long timeoutMS)
{
U_TRACE(0, "UEventTime::setTime(%ld)", timeoutMS)
setCurrentTime();
UTimeVal::setMilliSecond(ms = timeoutMS);
}
void setMilliSecond()
{
U_TRACE_NO_PARAM(0, "UEventTime::setMilliSecond()")
ms = ((ctime.tv_sec + tv_sec - u_now->tv_sec) * 1000L) +
((ctime.tv_usec + tv_usec - u_now->tv_usec) / 1000L);
U_ASSERT(checkTolerance())
}
bool checkMilliSecond() const
{
U_TRACE_NO_PARAM(0, "UEventTime::checkMilliSecond()")
U_INTERNAL_DUMP("ms = %ld", ms)
long ms_calculated = ((ctime.tv_sec + tv_sec - u_now->tv_sec) * 1000L) +
((ctime.tv_usec + tv_usec - u_now->tv_usec) / 1000L);
if (ms == ms_calculated) U_RETURN(true);
U_INTERNAL_DUMP("ms_calculated = %ld", ms_calculated)
U_RETURN(false);
}
void setTolerance()
{
U_TRACE_NO_PARAM(0, "UEventTime::setTolerance()")
tolerance = ((tv_sec * 1000L) +
(tv_usec / 1000L)) / 128;
U_INTERNAL_DUMP("tolerance = %ld", tolerance)
}
bool checkTolerance() const
{
U_TRACE_NO_PARAM(0, "UEventTime::checkTolerance()")
U_ASSERT(checkMilliSecond())
U_INTERNAL_DUMP("tolerance = %ld", tolerance)
long tolerance_calculated = ((tv_sec * 1000L) +
(tv_usec / 1000L)) / 128;
if (tolerance == tolerance_calculated) U_RETURN(true);
U_INTERNAL_DUMP("tolerance_calculated = %ld", tolerance_calculated)
U_RETURN(false);
}
static long getMilliSecond(UEventTime* ptimeout)
{
U_TRACE(0, "UEventTime::getMilliSecond(%p)", ptimeout)
if (ptimeout == 0) U_RETURN(-1);
U_ASSERT(ptimeout->checkMilliSecond())
U_RETURN(ms);
}
static struct timeval* getTimeVal(UEventTime* ptimeout)
{
U_TRACE(0, "UEventTime::getTimeVal(%p)", ptimeout)
if (ptimeout == 0) U_RETURN_POINTER(0, struct timeval);
U_ASSERT(ptimeout->checkMilliSecond())
/**
* struct timeval {
* long tv_sec; // seconds
* long tv_usec; // microseconds
* };
*/
long us = ms * 1000L;
timeout1.tv_sec = us / 1000000L;
timeout1.tv_usec = us % 1000000L;
U_INTERNAL_DUMP("timeout1 = { %ld %9ld }", timeout1.tv_sec, timeout1.tv_usec)
U_RETURN_POINTER(&timeout1, struct timeval);
}
static struct timespec* getTimeSpec(UEventTime* ptimeout)
{
U_TRACE(0, "UEventTime::getTimeSpec(%p)", ptimeout)
if (ptimeout == 0) U_RETURN_POINTER(0, struct timespec);
U_ASSERT(ptimeout->checkMilliSecond())
/**
* struct timespec {
* time_t tv_sec; // seconds
* long tv_nsec; // nanoseconds
* };
*/
long ns = ms * 1000000L;
timeout2.tv_sec = ns / 1000000000L;
timeout2.tv_nsec = ns % 1000000000L;
U_INTERNAL_DUMP("timeout2 = { %ld %9ld }", timeout2.tv_sec, timeout2.tv_nsec)
U_RETURN_POINTER(&timeout2, struct timespec);
}
private:
#ifdef U_COMPILER_DELETE_MEMBERS
UEventTime& operator=(const UEventTime&) = delete;
#else
UEventTime& operator=(const UEventTime&) { return *this; }
#endif
friend class UTimer;
friend class UNotifier;
};
#endif

View File

@ -120,7 +120,7 @@ template <class T> inline char* U_OBJECT_TO_TRACE(T& object)
U_INTERNAL_TRACE("U_OBJECT_TO_TRACE(%p)", &object)
#ifdef DEBUG
bool status = UTrace::suspend();
UTrace::suspend();
#endif
char* str = UObject2String<T>(object);
@ -128,7 +128,7 @@ template <class T> inline char* U_OBJECT_TO_TRACE(T& object)
str = strndup(str, UObjectIO::buffer_output_len);
#ifdef DEBUG
UTrace::resume(status);
UTrace::resume();
#endif
return str;

View File

@ -85,15 +85,15 @@ public:
// run the list of timers. Your main program needs to call this every so often, or as indicated by getTimeout()
static bool run();
static void run();
static void setTimer();
static UEventTime* getTimeout() // returns a timeout indicating how long until the next timer triggers
{
U_TRACE_NO_PARAM(0, "UTimer::getTimeout()")
if (first &&
run())
if ( first &&
(run(), first))
{
U_RETURN_POINTER(first->alarm, UEventTime);
}
@ -129,12 +129,12 @@ public:
// DEBUG
# ifdef DEBUG
# ifdef DEBUG
static void printInfo(ostream& os);
void outputEntry(ostream& os) const U_NO_EXPORT;
const char* dump(bool reset) const;
# endif
# endif
#endif
protected:
@ -145,7 +145,7 @@ protected:
static UTimer* pool; // free list
static UTimer* first; // active list
static bool callHandlerTimeout();
static void callHandlerTimeout();
#ifdef DEBUG
static bool invariant();

View File

@ -149,15 +149,6 @@ public:
void setSecond(long sec) { tv_sec = sec; }
void setMicroSecond(long micro_sec) { tv_usec = micro_sec; }
void setMilliSecond(long timeoutMS)
{
U_TRACE(0, "UTimeVal::setMilliSecond(%ld)", timeoutMS)
tv_usec = timeoutMS * 1000L;
adjust();
}
long getSecond() const
{
U_TRACE_NO_PARAM(0, "UTimeVal::getSecond()")
@ -181,15 +172,6 @@ public:
U_RETURN(ms);
}
long getTolerance() const
{
U_TRACE_NO_PARAM(0, "UTimeVal::getTolerance()")
long ms = getMilliSecond() / 128;
U_RETURN(ms);
}
double getMicroSecond() const
{
U_TRACE_NO_PARAM(0, "UTimeVal::getMicroSecond()")
@ -199,6 +181,18 @@ public:
U_RETURN(micro_sec);
}
void setMilliSecond(long timeoutMS)
{
U_TRACE(0, "UTimeVal::setMilliSecond(%ld)", timeoutMS)
tv_sec = 0L;
tv_usec = timeoutMS * 1000L;
adjust();
U_ASSERT_EQUALS(timeoutMS, getMilliSecond())
}
// OPERATOR
int operator !() const { return isZero(); }

View File

@ -23,7 +23,8 @@
#include <errno.h>
static UCrono* time_syscall_read_or_write;
int UTrace::status;
UCrono* UTrace::time_syscall_read_or_write;
U_NO_EXPORT void UTrace::set(int level)
{

View File

@ -17,13 +17,18 @@
# include <ulib/libevent/event.h>
#endif
struct timespec UEventTime::timeout;
long UEventTime::ms;
struct timeval UEventTime::timeout1;
struct timespec UEventTime::timeout2;
UEventTime::UEventTime(long sec, long usec) : UTimeVal(sec, usec)
UEventTime::UEventTime(long sec, long micro_sec) : UTimeVal(sec, micro_sec)
{
U_TRACE_REGISTER_OBJECT(0, UEventTime, "%ld,%ld", sec, usec)
U_TRACE_REGISTER_OBJECT(0, UEventTime, "%ld,%ld", sec, micro_sec)
reset();
setTolerance();
ctime.tv_sec =
ctime.tv_usec = 0L;
#ifdef USE_LIBEVENT
if (u_ev_base == 0) u_ev_base = (struct event_base*) U_SYSCALL_NO_PARAM(event_init);

View File

@ -22,11 +22,11 @@
# include <sys/event.h>
#endif
#ifdef HAVE_POLL_H
#ifndef HAVE_POLL_H
UEventTime* UNotifier::time_obj;
#else
# include <poll.h>
struct pollfd UNotifier::fds[1];
#else
UEventTime* UNotifier::time_obj;
#endif
#include <errno.h>
@ -728,37 +728,24 @@ int UNotifier::waitForEvent(int fd_max, fd_set* read_set, fd_set* write_set, UEv
#else
int result;
# ifdef HAVE_EPOLL_WAIT
int timeoutMS = (ptimeout ? ptimeout->getTimerVal() : -1);
result = U_SYSCALL(epoll_wait, "%d,%p,%u,%d", epollfd, events, max_connection, timeoutMS);
result = U_SYSCALL(epoll_wait, "%d,%p,%u,%d", epollfd, events, max_connection, UEventTime::getMilliSecond(ptimeout));
# elif defined(HAVE_KQUEUE)
struct timespec* timeout = (ptimeout ? ptimeout->getTimerValSpec() : 0);
result = U_SYSCALL(kevent, "%d,%p,%d,%p,%d,%p", kq, kqevents, nkqevents, kqrevents, max_connection, timeout);
result = U_SYSCALL(kevent, "%d,%p,%d,%p,%d,%p", kq, kqevents, nkqevents, kqrevents, max_connection, UEventTime::getTimeSpec(ptimeout));
nkqevents = 0;
# else
static struct timeval tmp;
struct timeval* ptmp;
// If both fields of the timeval structure are zero, then select() returns immediately.
// (This is useful for polling). If ptimeout is NULL (no timeout), select() can block indefinitely...
//
// On Linux, the function select modifies timeout to reflect the amount of time not slept; most other implementations do not do this.
// This causes problems both when Linux code which reads timeout is ported to other operating systems, and when code is ported to Linux
// that reuses a struct timeval for multiple selects in a loop without reinitializing it. Consider timeout to be undefined after select returns
# if defined(DEBUG) && !defined(_MSWINDOWS_)
if ( read_set) U_INTERNAL_DUMP(" read_set = %B", __FDS_BITS( read_set)[0])
if (write_set) U_INTERNAL_DUMP("write_set = %B", __FDS_BITS(write_set)[0])
# endif
if (ptimeout == 0) ptmp = 0;
else
{
// On Linux, the function select modifies timeout to reflect the amount of time not slept; most other implementations do not do this.
// This causes problems both when Linux code which reads timeout is ported to other operating systems, and when code is ported to Linux
// that reuses a struct timeval for multiple selects in a loop without reinitializing it. Consider timeout to be undefined after select returns
ptimeout->setTimerVal(ptmp = &tmp);
}
// If both fields of the timeval structure are zero, then select() returns immediately.
// (This is useful for polling). If ptmp is NULL (no timeout), select() can block indefinitely...
result = U_SYSCALL(select, "%d,%p,%p,%p,%p", fd_max, read_set, write_set, 0, ptmp);
result = U_SYSCALL(select, "%d,%p,%p,%p,%p", fd_max, read_set, write_set, 0, UEventTime::getTimeVal(ptimeout));
# if defined(DEBUG) && !defined(_MSWINDOWS_)
if ( read_set) U_INTERNAL_DUMP(" read_set = %B", __FDS_BITS( read_set)[0])
@ -793,9 +780,7 @@ loop:
ptimeout);
# elif defined(HAVE_KQUEUE)
loop:
struct timespec* timeout = (ptimeout ? ptimeout->getTimerValSpec() : 0);
nfd_ready = U_SYSCALL(kevent, "%d,%p,%d,%p,%d,%p", kq, kqevents, nkqevents, kqrevents, max_connection, timeout);
nfd_ready = U_SYSCALL(kevent, "%d,%p,%d,%p,%d,%p", kq, kqevents, nkqevents, kqrevents, max_connection, UEventTime::getTimeSpec(ptimeout));
# ifdef DEBUG
if (nfd_ready == -1 &&
errno == EINVAL)
@ -806,9 +791,7 @@ loop:
nkqevents = 0;
# else
loop:
int timeoutMS = (ptimeout ? ptimeout->getTimerVal() : -1);
nfd_ready = U_SYSCALL(epoll_wait, "%d,%p,%u,%d", epollfd, events, max_connection, timeoutMS);
nfd_ready = U_SYSCALL(epoll_wait, "%d,%p,%u,%d", epollfd, events, max_connection, UEventTime::getMilliSecond(ptimeout));
# endif
if (nfd_ready > 0)
@ -1045,11 +1028,11 @@ loop:
waitForEvent(ptimeout = UTimer::getTimeout());
if (nfd_ready == 0 &&
ptimeout)
ptimeout != 0)
{
U_INTERNAL_ASSERT_EQUALS(UTimer::first->alarm, ptimeout)
(void) UTimer::callHandlerTimeout();
UTimer::callHandlerTimeout();
goto loop;
}
@ -1322,7 +1305,7 @@ int UNotifier::waitForRead(int fd, int timeoutMS)
# endif
// If both fields of the timeval structure are zero, then select() returns immediately.
// (This is useful for polling). If ptmp is NULL (no timeout), select() can block indefinitely...
// (This is useful for polling). If ptime is NULL (no timeout), select() can block indefinitely...
UEventTime* ptime;
@ -1377,9 +1360,9 @@ int UNotifier::waitForWrite(int fd, int timeoutMS)
}
#else
# ifdef _MSWINDOWS_
# ifdef _MSWINDOWS_
if (is_pipe(fd) != INVALID_HANDLE_VALUE) U_RETURN(1);
# endif
# endif
// If both fields of the timeval structure are zero, then select() returns immediately.
// (This is useful for polling). If ptmp is NULL (no timeout), select() can block indefinitely...

View File

@ -41,7 +41,7 @@ void UTimer::init(Type _mode)
U_NO_EXPORT void UTimer::insertEntry()
{
U_TRACE_NO_PARAM(1, "UTimer::insertEntry()")
U_TRACE_NO_PARAM(0, "UTimer::insertEntry()")
U_CHECK_MEMORY
@ -70,7 +70,7 @@ U_NO_EXPORT void UTimer::insertEntry()
U_ASSERT(invariant())
}
bool UTimer::callHandlerTimeout()
void UTimer::callHandlerTimeout()
{
U_TRACE_NO_PARAM(0, "UTimer::callHandlerTimeout()")
@ -87,73 +87,83 @@ bool UTimer::callHandlerTimeout()
item->insertEntry();
U_RETURN(true);
item->alarm->setMilliSecond();
}
else
{
// put it on the free list
// put it on the free list
item->alarm = 0;
item->next = pool;
pool = item;
U_RETURN(false);
item->alarm = 0;
item->next = pool;
pool = item;
}
}
bool UTimer::run()
void UTimer::run()
{
U_TRACE_NO_PARAM(1, "UTimer::run()")
U_INTERNAL_ASSERT_POINTER(first)
(void) U_SYSCALL(gettimeofday, "%p,%p", u_now, 0);
U_INTERNAL_DUMP("u_now = { %ld %6ld }", u_now->tv_sec, u_now->tv_usec)
U_INTERNAL_DUMP("u_now = { %ld %6ld } first = %p", u_now->tv_sec, u_now->tv_usec, first)
UTimer* item = first;
bool bnosignal = (mode == NOSIGNAL), bexpired;
loop:
if ((mode == NOSIGNAL ? first->alarm->isOld()
: first->alarm->isExpired()))
{
if (callHandlerTimeout() ||
first)
{
goto loop;
}
#ifdef DEBUG
U_INTERNAL_DUMP("item = %p item->next = %p", item, item->next)
U_RETURN(false);
U_INTERNAL_ASSERT_POINTER(item)
if (item->next) U_INTERNAL_ASSERT(*item <= *(item->next))
#endif
bexpired = (bnosignal ? item->alarm->isExpired()
: item->alarm->isExpiredWithTolerance());
if (bexpired)
{
item = item->next;
callHandlerTimeout();
if (item) goto loop;
}
U_INTERNAL_DUMP("first = %p", first)
if (first) U_RETURN(true);
U_RETURN(false);
}
void UTimer::setTimer()
{
U_TRACE_NO_PARAM(1, "UTimer::setTimer()")
U_INTERNAL_ASSERT_POINTER(first)
U_INTERNAL_ASSERT_DIFFERS(mode, NOSIGNAL)
if (run())
{
U_INTERNAL_ASSERT_POINTER(first)
run();
first->alarm->setTimerVal(&UInterrupt::timerval.it_value);
}
else
if (first == 0)
{
U_INTERNAL_ASSERT_EQUALS(first, 0)
UInterrupt::timerval.it_value.tv_sec =
UInterrupt::timerval.it_value.tv_usec = 0L;
}
else
{
UEventTime* item = first->alarm;
// NB: can happen that setitimer() produce immediatly a signal because the interval is very short (< 10ms)...
UInterrupt::timerval.it_value.tv_sec = item->ctime.tv_sec + item->tv_sec - u_now->tv_sec;
UInterrupt::timerval.it_value.tv_usec = item->ctime.tv_usec + item->tv_usec - u_now->tv_usec;
UTimeVal::adjust(&(UInterrupt::timerval.it_value.tv_sec), &(UInterrupt::timerval.it_value.tv_usec));
}
// NB: it can happen that setitimer() produce immediatly a signal because the interval is very short (< 10ms)...
U_INTERNAL_DUMP("UInterrupt::timerval.it_value = { %ld %6ld }", UInterrupt::timerval.it_value.tv_sec, UInterrupt::timerval.it_value.tv_usec)
U_INTERNAL_ASSERT(UInterrupt::timerval.it_value.tv_sec >= 0 &&
UInterrupt::timerval.it_value.tv_usec >= 0)
(void) U_SYSCALL(setitimer, "%d,%p,%p", ITIMER_REAL, &UInterrupt::timerval, 0);
}
@ -161,7 +171,7 @@ void UTimer::insert(UEventTime* a)
{
U_TRACE(0, "UTimer::insert(%p,%b)", a)
// set an alarm to more than 2 month is very strange...
// set an alarm to more than 2 month is very suspect...
U_INTERNAL_ASSERT_MINOR(a->tv_sec, 60L * U_ONE_DAY_IN_SECOND) // 60 gg (2 month)
@ -210,14 +220,14 @@ void UTimer::erase(UEventTime* a)
void UTimer::clear()
{
U_TRACE_NO_PARAM(0, "UTimer::clear()")
U_TRACE_NO_PARAM(1, "UTimer::clear()")
U_INTERNAL_DUMP("mode = %d first = %p pool = %p", mode, first, pool)
if (mode != NOSIGNAL)
{
UInterrupt::timerval.it_value.tv_sec =
UInterrupt::timerval.it_value.tv_usec = 0;
UInterrupt::timerval.it_value.tv_usec = 0L;
(void) U_SYSCALL(setitimer, "%d,%p,%p", ITIMER_REAL, &UInterrupt::timerval, 0);
}
@ -252,7 +262,7 @@ bool UTimer::invariant()
{
for (UTimer* item = first; item->next; item = item->next)
{
U_INTERNAL_ASSERT(*item <= *(item->next))
if (item->next) U_INTERNAL_ASSERT(*item <= *(item->next))
}
}

View File

@ -45,7 +45,7 @@ HTTP/1.1 200 OK
Date: Thu, 03 Jul 2014 10:11:10 GMT
Server: ULib
Content-Length: 27
Content-Type: application/json; charset=UTF-8
Content-Type: application/json
{"message":"Hello, World!"}
```
@ -57,7 +57,7 @@ HTTP/1.1 200 OK
Date: Thu, 03 Jul 2014 10:14:51 GMT
Server: ULib
Content-Length: 31
Content-Type: application/json; charset=UTF-8
Content-Type: application/json
{"id":6227,"randomNumber":8489}
```
@ -69,7 +69,7 @@ HTTP/1.1 200 OK
Date: Thu, 03 Jul 2014 10:14:51 GMT
Server: ULib
Content-Length: 320
Content-Type: application/json; charset=UTF-8
Content-Type: application/json
[{"id":6851,"randomNumber":7598},{"id":3968,"randomNumber":7325},{"id":8159,"randomNumber":348},{"id":9560,"randomNumber":7333},{"id":9938,"randomNumber":9080},{"id":1598,"randomNumber":1623},{"id":3280,"randomNumber":8707},{"id":4521,"randomNumber":6063},{"id":8173,"randomNumber":3690},{"id":3648,"randomNumber":8803}]
```
@ -80,7 +80,7 @@ Content-Type: application/json; charset=UTF-8
HTTP/1.1 200 OK
Date: Thu, 03 Jul 2014 10:14:51 GMT
Server: ULib
Content-Type: text/html; charset=UTF-8
Content-Type: text/html
Content-Length: 1227
<!doctype html><html><head><title>Fortunes</title></head><body><table><tr><th>id</th><th>message</th></tr><tr><td>11</td><td>&lt;script&gt;alert(&quot;This should not be displayed in a browser alert box.&quot;);&lt;/script&gt;</td></tr><tr><td>4</td><td>A bad random number generator: 1, 1, 1, 1, 1, 4.33e+67, 1, 1, 1</td></tr><tr><td>5</td><td>A computer program does what you tell it to do, not what you want it to do.</td></tr><tr><td>2</td><td>A computer scientist is someone who fixes things that aren&apos;t broken.</td></tr><tr><td>8</td><td>A list is only as strong as its weakest link. — Donald Knuth</td></tr><tr><td>0</td><td>Additional fortune added at request time.</td></tr><tr><td>3</td><td>After enough decimal places, nobody gives a damn.</td></tr><tr><td>7</td><td>Any program that runs right is obsolete.</td></tr><tr><td>10</td><td>Computers make very fast, very accurate mistakes.</td></tr><tr><td>6</td><td>Emacs is a nice operating system, but I prefer UNIX. — Tom Christaensen</td></tr><tr><td>9</td><td>Feature: A bug with seniority.</td></tr><tr><td>1</td><td>fortune: No such file or directory</td></tr><tr><td>12</td><td>フレームワークのベンチマーク</td></tr></table></body></html>
@ -93,7 +93,7 @@ HTTP/1.1 200 OK
Date: Thu, 03 Jul 2014 10:14:51 GMT
Server: ULib
Content-Length: 319
Content-Type: application/json; charset=UTF-8
Content-Type: application/json
[{"id":7171,"randomNumber":351},{"id":6019,"randomNumber":9725},{"id":8118,"randomNumber":4023},{"id":7965,"randomNumber":1388},{"id":7797,"randomNumber":2249},{"id":112,"randomNumber":1108},{"id":6127,"randomNumber":4323},{"id":2597,"randomNumber":7509},{"id":2978,"randomNumber":7883},{"id":1111,"randomNumber":2228}]
```
@ -104,7 +104,7 @@ Content-Type: application/json; charset=UTF-8
HTTP/1.1 200 OK
Date: Thu, 03 Jul 2014 10:14:51 GMT
Server: ULib
Content-Type: text/plain; charset=UTF-8
Content-Type: text/plain
Content-Length: 13
Hello, World!

View File

@ -7,9 +7,10 @@
start_msg tsa_rpc
#UTRACE="0 50M 0"
#UTRACE_SIGNAL="0 10M -1"
#UOBJDUMP="0 1M 100"
#USIMERR="error.sim"
export UTRACE UOBJDUMP USIMERR
export UTRACE UOBJDUMP USIMERR UTRACE_SIGNAL
DOC_ROOT=TSA

View File

@ -10,7 +10,6 @@
#define TEST_CHANGE(b) {if(!TestChange(b))return 1;}
static bool status;
static volatile int n;
static int time_to_sleep = 5;
@ -83,7 +82,7 @@ public:
if (WaitNValue(2)) // wait for main thread
{
# ifdef DEBUG
status = UTrace::suspend();
UTrace::suspend();
# endif
while (true)
@ -261,7 +260,7 @@ int U_EXPORT main(int argc, char* argv[])
time_to_sleep = 5000;
#ifdef DEBUG
UTrace::resume(status);
UTrace::resume();
#endif
// Test child thread destroying before father