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 // Design by contract - if (expr == false) then stop
#ifdef DEBUG #ifdef DEBUG
# define U_ASSERT(expr) { int _status_ = UTrace::suspend(); U_INTERNAL_ASSERT(expr); UTrace::resume(_status_); } # define U_ASSERT(expr) { UTrace::suspend(); U_INTERNAL_ASSERT(expr); UTrace::resume(); }
# define U_ASSERT_MINOR(a,b) { int _status_ = UTrace::suspend(); U_INTERNAL_ASSERT_MINOR(a,b); UTrace::resume(_status_); } # define U_ASSERT_MINOR(a,b) { UTrace::suspend(); U_INTERNAL_ASSERT_MINOR(a,b); UTrace::resume(); }
# define U_ASSERT_MAJOR(a,b) { int _status_ = UTrace::suspend(); U_INTERNAL_ASSERT_MAJOR(a,b); UTrace::resume(_status_); } # define U_ASSERT_MAJOR(a,b) { UTrace::suspend(); U_INTERNAL_ASSERT_MAJOR(a,b); UTrace::resume(); }
# define U_ASSERT_EQUALS(a,b) { int _status_ = UTrace::suspend(); U_INTERNAL_ASSERT_EQUALS(a,b); UTrace::resume(_status_); } # define U_ASSERT_EQUALS(a,b) { UTrace::suspend(); U_INTERNAL_ASSERT_EQUALS(a,b); UTrace::resume(); }
# define U_ASSERT_DIFFERS(a,b) { int _status_ = UTrace::suspend(); U_INTERNAL_ASSERT_DIFFERS(a,b); UTrace::resume(_status_); } # define U_ASSERT_DIFFERS(a,b) { UTrace::suspend(); U_INTERNAL_ASSERT_DIFFERS(a,b); UTrace::resume(); }
# define U_ASSERT_POINTER(ptr) { int _status_ = UTrace::suspend(); U_INTERNAL_ASSERT_POINTER(ptr); UTrace::resume(_status_); } # define U_ASSERT_POINTER(ptr) { UTrace::suspend(); U_INTERNAL_ASSERT_POINTER(ptr); UTrace::resume(); }
# define U_ASSERT_RANGE(a,x,b) { int _status_ = UTrace::suspend(); U_INTERNAL_ASSERT_RANGE(a,x,b); UTrace::resume(_status_); } # 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_MSG(expr,info) { UTrace::suspend(); U_INTERNAL_ASSERT_MSG(expr,info); UTrace::resume(); }
# 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_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) { int _status_ = UTrace::suspend(); U_INTERNAL_ASSERT_MAJOR_MSG(a,b,info); UTrace::resume(_status_); } # 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) { int _status_ = UTrace::suspend(); U_INTERNAL_ASSERT_EQUALS_MSG(a,b,info); UTrace::resume(_status_); } # 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) { int _status_ = UTrace::suspend(); U_INTERNAL_ASSERT_DIFFERS_MSG(a,b,info); UTrace::resume(_status_); } # 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) { int _status_ = UTrace::suspend(); U_INTERNAL_ASSERT_POINTER_MSG(ptr,info); UTrace::resume(_status_); } # 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) { int _status_ = UTrace::suspend(); U_INTERNAL_ASSERT_RANGE_MSG(a,x,b,info); UTrace::resume(_status_); } # 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) #elif defined(U_TEST)
# define U_ASSERT(expr) U_INTERNAL_ASSERT(expr) # define U_ASSERT(expr) U_INTERNAL_ASSERT(expr)
# define U_ASSERT_MINOR(a,b) U_INTERNAL_ASSERT_MINOR(a,b) # define U_ASSERT_MINOR(a,b) U_INTERNAL_ASSERT_MINOR(a,b)
@ -86,20 +86,20 @@
// NB: U_DUMP, U_SYSCALL() and U_RETURN() depend on presence of U_TRACE() // 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_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_DUMP(args...) { if (utr.active[0]) { UTrace::suspend(); u_trace_dump(args); UTrace::resume(); } }
# define U_SYSCALL(name,format,args...) (utr.trace_syscall("::"#name"(" format ")" , ##args), \
utr.trace_sysreturn_type(::name(args)))
# define U_SYSCALL_NO_PARAM(name) (utr.trace_syscall("::"#name"()",0), \ # define U_SYSCALL_NO_PARAM(name) (utr.trace_syscall("::"#name"()",0), \
utr.trace_sysreturn_type(::name())) 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); \ # define U_SYSCALL_VOID_NO_PARAM(name) { utr.trace_syscall("::"#name"()",0); \
name(); utr.trace_sysreturn(false,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(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));} # define U_RETURN_STRING(str) {U_INTERNAL_ASSERT((str).invariant()); return (utr.trace_return("%V",(str).rep),(str));}
# define U_RETURN_OBJECT(obj) return (utr.trace_return("%O",U_OBJECT_TO_TRACE((obj))),(obj)) # define U_RETURN_OBJECT(obj) return (utr.trace_return("%O",U_OBJECT_TO_TRACE((obj))),(obj))

View File

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

View File

@ -16,6 +16,8 @@
#include <ulib/timeval.h> #include <ulib/timeval.h>
class UTimer;
class UNotifier;
#ifdef USE_LIBEVENT #ifdef USE_LIBEVENT
template <class T> class UTimerEv; template <class T> class UTimerEv;
#endif #endif
@ -25,48 +27,24 @@ public:
struct timeval ctime; struct timeval ctime;
void reset() { ctime.tv_sec = ctime.tv_usec = 0L; } UEventTime(long sec = 0L, long micro_sec = 1L);
UEventTime(long sec = 0L, long usec = 1L);
virtual ~UEventTime(); virtual ~UEventTime();
bool operator<(const UEventTime& t) const __pure; bool operator<(const UEventTime& t) const __pure;
// SERVICES // SERVICES
void setTime(long timeoutMS) bool isExpired() const __pure
{ {
U_TRACE(0, "UEventTime::setTime(%ld)", timeoutMS) U_TRACE_NO_PARAM(0, "UEventTime::isExpired()")
setCurrentTime();
UTimeVal::setMilliSecond(timeoutMS);
}
void setCurrentTime()
{
U_TRACE_NO_PARAM(1, "UEventTime::setCurrentTime()")
U_CHECK_MEMORY U_CHECK_MEMORY
(void) U_SYSCALL(gettimeofday, "%p,%p", &ctime, 0); long diff1 = ctime.tv_sec + tv_sec - u_now->tv_sec,
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,
diff2 = ctime.tv_usec + tv_usec - u_now->tv_usec; 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 || if ( diff1 < 0 ||
(diff1 == 0 && (diff1 == 0 &&
@ -75,71 +53,31 @@ public:
U_RETURN(true); U_RETURN(true);
} }
long diff = (diff1 * 1000L) + ms = (diff1 * 1000L) +
(diff2 / 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); U_RETURN(false);
} }
bool isOld() const __pure { return isExpired(0); } bool isExpiredWithTolerance() const __pure
bool isExpired() const __pure { return isExpired(UTimeVal::getTolerance()); }
void setTimerVal(struct timeval* it_value)
{ {
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; if (ms > tolerance) U_RETURN(false);
it_value->tv_usec = ctime.tv_usec + tv_usec - u_now->tv_usec;
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)
} }
long getTimerVal() U_RETURN(true);
{
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() time_t expire() const { return (ctime.tv_sec + tv_sec); }
{
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);
}
// ------------------------------------------- // -------------------------------------------
// method VIRTUAL to define // method VIRTUAL to define
@ -163,14 +101,157 @@ public:
# endif # endif
#endif #endif
private: protected:
static struct timespec timeout; 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 #ifdef U_COMPILER_DELETE_MEMBERS
UEventTime& operator=(const UEventTime&) = delete; UEventTime& operator=(const UEventTime&) = delete;
#else #else
UEventTime& operator=(const UEventTime&) { return *this; } UEventTime& operator=(const UEventTime&) { return *this; }
#endif #endif
friend class UTimer;
friend class UNotifier;
}; };
#endif #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) U_INTERNAL_TRACE("U_OBJECT_TO_TRACE(%p)", &object)
#ifdef DEBUG #ifdef DEBUG
bool status = UTrace::suspend(); UTrace::suspend();
#endif #endif
char* str = UObject2String<T>(object); 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); str = strndup(str, UObjectIO::buffer_output_len);
#ifdef DEBUG #ifdef DEBUG
UTrace::resume(status); UTrace::resume();
#endif #endif
return str; return str;

View File

@ -85,7 +85,7 @@ public:
// run the list of timers. Your main program needs to call this every so often, or as indicated by getTimeout() // 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 void setTimer();
static UEventTime* getTimeout() // returns a timeout indicating how long until the next timer triggers static UEventTime* getTimeout() // returns a timeout indicating how long until the next timer triggers
@ -93,7 +93,7 @@ public:
U_TRACE_NO_PARAM(0, "UTimer::getTimeout()") U_TRACE_NO_PARAM(0, "UTimer::getTimeout()")
if ( first && if ( first &&
run()) (run(), first))
{ {
U_RETURN_POINTER(first->alarm, UEventTime); U_RETURN_POINTER(first->alarm, UEventTime);
} }
@ -145,7 +145,7 @@ protected:
static UTimer* pool; // free list static UTimer* pool; // free list
static UTimer* first; // active list static UTimer* first; // active list
static bool callHandlerTimeout(); static void callHandlerTimeout();
#ifdef DEBUG #ifdef DEBUG
static bool invariant(); static bool invariant();

View File

@ -149,15 +149,6 @@ public:
void setSecond(long sec) { tv_sec = sec; } void setSecond(long sec) { tv_sec = sec; }
void setMicroSecond(long micro_sec) { tv_usec = micro_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 long getSecond() const
{ {
U_TRACE_NO_PARAM(0, "UTimeVal::getSecond()") U_TRACE_NO_PARAM(0, "UTimeVal::getSecond()")
@ -181,15 +172,6 @@ public:
U_RETURN(ms); U_RETURN(ms);
} }
long getTolerance() const
{
U_TRACE_NO_PARAM(0, "UTimeVal::getTolerance()")
long ms = getMilliSecond() / 128;
U_RETURN(ms);
}
double getMicroSecond() const double getMicroSecond() const
{ {
U_TRACE_NO_PARAM(0, "UTimeVal::getMicroSecond()") U_TRACE_NO_PARAM(0, "UTimeVal::getMicroSecond()")
@ -199,6 +181,18 @@ public:
U_RETURN(micro_sec); 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 // OPERATOR
int operator !() const { return isZero(); } int operator !() const { return isZero(); }

View File

@ -23,7 +23,8 @@
#include <errno.h> #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) U_NO_EXPORT void UTrace::set(int level)
{ {

View File

@ -17,13 +17,18 @@
# include <ulib/libevent/event.h> # include <ulib/libevent/event.h>
#endif #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 #ifdef USE_LIBEVENT
if (u_ev_base == 0) u_ev_base = (struct event_base*) U_SYSCALL_NO_PARAM(event_init); 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> # include <sys/event.h>
#endif #endif
#ifdef HAVE_POLL_H #ifndef HAVE_POLL_H
UEventTime* UNotifier::time_obj;
#else
# include <poll.h> # include <poll.h>
struct pollfd UNotifier::fds[1]; struct pollfd UNotifier::fds[1];
#else
UEventTime* UNotifier::time_obj;
#endif #endif
#include <errno.h> #include <errno.h>
@ -728,37 +728,24 @@ int UNotifier::waitForEvent(int fd_max, fd_set* read_set, fd_set* write_set, UEv
#else #else
int result; int result;
# ifdef HAVE_EPOLL_WAIT # ifdef HAVE_EPOLL_WAIT
int timeoutMS = (ptimeout ? ptimeout->getTimerVal() : -1); result = U_SYSCALL(epoll_wait, "%d,%p,%u,%d", epollfd, events, max_connection, UEventTime::getMilliSecond(ptimeout));
result = U_SYSCALL(epoll_wait, "%d,%p,%u,%d", epollfd, events, max_connection, timeoutMS);
# elif defined(HAVE_KQUEUE) # 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, UEventTime::getTimeSpec(ptimeout));
result = U_SYSCALL(kevent, "%d,%p,%d,%p,%d,%p", kq, kqevents, nkqevents, kqrevents, max_connection, timeout);
nkqevents = 0; nkqevents = 0;
# else # else
static struct timeval tmp; // If both fields of the timeval structure are zero, then select() returns immediately.
struct timeval* ptmp; // (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 defined(DEBUG) && !defined(_MSWINDOWS_)
if ( read_set) U_INTERNAL_DUMP(" read_set = %B", __FDS_BITS( read_set)[0]) 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]) if (write_set) U_INTERNAL_DUMP("write_set = %B", __FDS_BITS(write_set)[0])
# endif # endif
if (ptimeout == 0) ptmp = 0; result = U_SYSCALL(select, "%d,%p,%p,%p,%p", fd_max, read_set, write_set, 0, UEventTime::getTimeVal(ptimeout));
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);
# if defined(DEBUG) && !defined(_MSWINDOWS_) # if defined(DEBUG) && !defined(_MSWINDOWS_)
if ( read_set) U_INTERNAL_DUMP(" read_set = %B", __FDS_BITS( read_set)[0]) if ( read_set) U_INTERNAL_DUMP(" read_set = %B", __FDS_BITS( read_set)[0])
@ -793,9 +780,7 @@ loop:
ptimeout); ptimeout);
# elif defined(HAVE_KQUEUE) # elif defined(HAVE_KQUEUE)
loop: 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, UEventTime::getTimeSpec(ptimeout));
nfd_ready = U_SYSCALL(kevent, "%d,%p,%d,%p,%d,%p", kq, kqevents, nkqevents, kqrevents, max_connection, timeout);
# ifdef DEBUG # ifdef DEBUG
if (nfd_ready == -1 && if (nfd_ready == -1 &&
errno == EINVAL) errno == EINVAL)
@ -806,9 +791,7 @@ loop:
nkqevents = 0; nkqevents = 0;
# else # else
loop: loop:
int timeoutMS = (ptimeout ? ptimeout->getTimerVal() : -1); nfd_ready = U_SYSCALL(epoll_wait, "%d,%p,%u,%d", epollfd, events, max_connection, UEventTime::getMilliSecond(ptimeout));
nfd_ready = U_SYSCALL(epoll_wait, "%d,%p,%u,%d", epollfd, events, max_connection, timeoutMS);
# endif # endif
if (nfd_ready > 0) if (nfd_ready > 0)
@ -1045,11 +1028,11 @@ loop:
waitForEvent(ptimeout = UTimer::getTimeout()); waitForEvent(ptimeout = UTimer::getTimeout());
if (nfd_ready == 0 && if (nfd_ready == 0 &&
ptimeout) ptimeout != 0)
{ {
U_INTERNAL_ASSERT_EQUALS(UTimer::first->alarm, ptimeout) U_INTERNAL_ASSERT_EQUALS(UTimer::first->alarm, ptimeout)
(void) UTimer::callHandlerTimeout(); UTimer::callHandlerTimeout();
goto loop; goto loop;
} }
@ -1322,7 +1305,7 @@ int UNotifier::waitForRead(int fd, int timeoutMS)
# endif # endif
// If both fields of the timeval structure are zero, then select() returns immediately. // 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; UEventTime* ptime;

View File

@ -41,7 +41,7 @@ void UTimer::init(Type _mode)
U_NO_EXPORT void UTimer::insertEntry() U_NO_EXPORT void UTimer::insertEntry()
{ {
U_TRACE_NO_PARAM(1, "UTimer::insertEntry()") U_TRACE_NO_PARAM(0, "UTimer::insertEntry()")
U_CHECK_MEMORY U_CHECK_MEMORY
@ -70,7 +70,7 @@ U_NO_EXPORT void UTimer::insertEntry()
U_ASSERT(invariant()) U_ASSERT(invariant())
} }
bool UTimer::callHandlerTimeout() void UTimer::callHandlerTimeout()
{ {
U_TRACE_NO_PARAM(0, "UTimer::callHandlerTimeout()") U_TRACE_NO_PARAM(0, "UTimer::callHandlerTimeout()")
@ -87,73 +87,83 @@ bool UTimer::callHandlerTimeout()
item->insertEntry(); 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->alarm = 0;
item->next = pool; item->next = pool;
pool = item; pool = item;
}
U_RETURN(false);
} }
bool UTimer::run() void UTimer::run()
{ {
U_TRACE_NO_PARAM(1, "UTimer::run()") U_TRACE_NO_PARAM(1, "UTimer::run()")
U_INTERNAL_ASSERT_POINTER(first)
(void) U_SYSCALL(gettimeofday, "%p,%p", u_now, 0); (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: loop:
if ((mode == NOSIGNAL ? first->alarm->isOld() #ifdef DEBUG
: first->alarm->isExpired())) U_INTERNAL_DUMP("item = %p item->next = %p", item, item->next)
{
if (callHandlerTimeout() ||
first)
{
goto loop;
}
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) U_INTERNAL_DUMP("first = %p", first)
if (first) U_RETURN(true);
U_RETURN(false);
} }
void UTimer::setTimer() void UTimer::setTimer()
{ {
U_TRACE_NO_PARAM(1, "UTimer::setTimer()") U_TRACE_NO_PARAM(1, "UTimer::setTimer()")
U_INTERNAL_ASSERT_POINTER(first)
U_INTERNAL_ASSERT_DIFFERS(mode, NOSIGNAL) U_INTERNAL_ASSERT_DIFFERS(mode, NOSIGNAL)
if (run()) run();
{
U_INTERNAL_ASSERT_POINTER(first)
first->alarm->setTimerVal(&UInterrupt::timerval.it_value); if (first == 0)
}
else
{ {
U_INTERNAL_ASSERT_EQUALS(first, 0)
UInterrupt::timerval.it_value.tv_sec = UInterrupt::timerval.it_value.tv_sec =
UInterrupt::timerval.it_value.tv_usec = 0L; 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_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); (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) 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) 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() 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) U_INTERNAL_DUMP("mode = %d first = %p pool = %p", mode, first, pool)
if (mode != NOSIGNAL) if (mode != NOSIGNAL)
{ {
UInterrupt::timerval.it_value.tv_sec = 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); (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) 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 Date: Thu, 03 Jul 2014 10:11:10 GMT
Server: ULib Server: ULib
Content-Length: 27 Content-Length: 27
Content-Type: application/json; charset=UTF-8 Content-Type: application/json
{"message":"Hello, World!"} {"message":"Hello, World!"}
``` ```
@ -57,7 +57,7 @@ HTTP/1.1 200 OK
Date: Thu, 03 Jul 2014 10:14:51 GMT Date: Thu, 03 Jul 2014 10:14:51 GMT
Server: ULib Server: ULib
Content-Length: 31 Content-Length: 31
Content-Type: application/json; charset=UTF-8 Content-Type: application/json
{"id":6227,"randomNumber":8489} {"id":6227,"randomNumber":8489}
``` ```
@ -69,7 +69,7 @@ HTTP/1.1 200 OK
Date: Thu, 03 Jul 2014 10:14:51 GMT Date: Thu, 03 Jul 2014 10:14:51 GMT
Server: ULib Server: ULib
Content-Length: 320 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}] [{"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 HTTP/1.1 200 OK
Date: Thu, 03 Jul 2014 10:14:51 GMT Date: Thu, 03 Jul 2014 10:14:51 GMT
Server: ULib Server: ULib
Content-Type: text/html; charset=UTF-8 Content-Type: text/html
Content-Length: 1227 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> <!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 Date: Thu, 03 Jul 2014 10:14:51 GMT
Server: ULib Server: ULib
Content-Length: 319 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}] [{"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 HTTP/1.1 200 OK
Date: Thu, 03 Jul 2014 10:14:51 GMT Date: Thu, 03 Jul 2014 10:14:51 GMT
Server: ULib Server: ULib
Content-Type: text/plain; charset=UTF-8 Content-Type: text/plain
Content-Length: 13 Content-Length: 13
Hello, World! Hello, World!

View File

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

View File

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