luasocket/src/timeout.c

227 lines
7.1 KiB
C
Raw Permalink Normal View History

2002-07-03 12:06:54 -07:00
/*=========================================================================*\
* Timeout management functions
* LuaSocket toolkit
2002-07-03 12:06:54 -07:00
\*=========================================================================*/
2019-02-25 15:01:04 -08:00
#include "luasocket.h"
2003-05-24 18:54:13 -07:00
#include "auxiliar.h"
#include "timeout.h"
2002-07-03 12:06:54 -07:00
2019-02-25 15:01:04 -08:00
#include <stdio.h>
#include <limits.h>
#include <float.h>
2004-06-16 17:18:48 -07:00
#ifdef _WIN32
2002-07-03 12:06:54 -07:00
#include <windows.h>
#else
#include <time.h>
2003-11-26 16:30:54 -08:00
#include <sys/time.h>
2002-07-03 12:06:54 -07:00
#endif
/* min and max macros */
#ifndef MIN
#define MIN(x, y) ((x) < (y) ? x : y)
#endif
#ifndef MAX
#define MAX(x, y) ((x) > (y) ? x : y)
#endif
2002-07-03 12:06:54 -07:00
/*=========================================================================*\
* Internal function prototypes
\*=========================================================================*/
2005-10-06 21:40:59 -07:00
static int timeout_lua_gettime(lua_State *L);
static int timeout_lua_sleep(lua_State *L);
2002-07-03 12:06:54 -07:00
static luaL_Reg func[] = {
2005-10-06 21:40:59 -07:00
{ "gettime", timeout_lua_gettime },
{ "sleep", timeout_lua_sleep },
2003-05-24 18:54:13 -07:00
{ NULL, NULL }
};
2002-07-03 12:06:54 -07:00
/*=========================================================================*\
* Exported functions.
\*=========================================================================*/
/*-------------------------------------------------------------------------*\
2003-05-24 18:54:13 -07:00
* Initialize structure
2002-07-03 12:06:54 -07:00
\*-------------------------------------------------------------------------*/
2019-02-27 20:01:16 -08:00
void timeout_init(p_timeout tm, double block, double total) {
2003-05-24 18:54:13 -07:00
tm->block = block;
tm->total = total;
2002-07-03 12:06:54 -07:00
}
/*-------------------------------------------------------------------------*\
2003-11-26 16:30:54 -08:00
* Determines how much time we have left for the next system call,
* if the previous call was successful
2003-11-26 16:30:54 -08:00
* Input
* tm: timeout control structure
* Returns
* the number of ms left or -1 if there is no time limit
\*-------------------------------------------------------------------------*/
2019-02-27 20:01:16 -08:00
double timeout_get(p_timeout tm) {
2004-06-30 20:32:09 -07:00
if (tm->block < 0.0 && tm->total < 0.0) {
2003-11-26 16:30:54 -08:00
return -1;
2004-06-30 20:32:09 -07:00
} else if (tm->block < 0.0) {
2005-10-06 21:40:59 -07:00
double t = tm->total - timeout_gettime() + tm->start;
2004-06-30 20:32:09 -07:00
return MAX(t, 0.0);
} else if (tm->total < 0.0) {
2003-11-26 16:30:54 -08:00
return tm->block;
} else {
2005-10-06 21:40:59 -07:00
double t = tm->total - timeout_gettime() + tm->start;
2004-06-30 20:32:09 -07:00
return MIN(tm->block, MAX(t, 0.0));
2003-11-26 16:30:54 -08:00
}
}
/*-------------------------------------------------------------------------*\
* Returns time since start of operation
* Input
* tm: timeout control structure
* Returns
* start field of structure
2002-07-03 12:06:54 -07:00
\*-------------------------------------------------------------------------*/
2019-02-27 20:01:16 -08:00
double timeout_getstart(p_timeout tm) {
2003-11-26 16:30:54 -08:00
return tm->start;
}
2002-07-03 12:06:54 -07:00
/*-------------------------------------------------------------------------*\
2003-11-26 16:30:54 -08:00
* Determines how much time we have left for the next system call,
* if the previous call was a failure
2002-07-03 12:06:54 -07:00
* Input
* tm: timeout control structure
* Returns
* the number of ms left or -1 if there is no time limit
\*-------------------------------------------------------------------------*/
2019-02-27 20:01:16 -08:00
double timeout_getretry(p_timeout tm) {
2004-06-30 20:32:09 -07:00
if (tm->block < 0.0 && tm->total < 0.0) {
2002-07-03 12:06:54 -07:00
return -1;
2004-06-30 20:32:09 -07:00
} else if (tm->block < 0.0) {
2005-10-06 21:40:59 -07:00
double t = tm->total - timeout_gettime() + tm->start;
2004-06-30 20:32:09 -07:00
return MAX(t, 0.0);
} else if (tm->total < 0.0) {
2005-10-06 21:40:59 -07:00
double t = tm->block - timeout_gettime() + tm->start;
2004-06-30 20:32:09 -07:00
return MAX(t, 0.0);
2003-11-26 16:30:54 -08:00
} else {
2005-10-06 21:40:59 -07:00
double t = tm->total - timeout_gettime() + tm->start;
2004-06-30 20:32:09 -07:00
return MIN(tm->block, MAX(t, 0.0));
2003-11-26 16:30:54 -08:00
}
2002-07-03 12:06:54 -07:00
}
/*-------------------------------------------------------------------------*\
* Marks the operation start time in structure
2002-07-03 12:06:54 -07:00
* Input
* tm: timeout control structure
\*-------------------------------------------------------------------------*/
2019-02-27 20:01:16 -08:00
p_timeout timeout_markstart(p_timeout tm) {
2005-10-06 21:40:59 -07:00
tm->start = timeout_gettime();
return tm;
2002-07-03 12:06:54 -07:00
}
/*-------------------------------------------------------------------------*\
* Gets time in s, relative to January 1, 1970 (UTC)
2002-07-03 12:06:54 -07:00
* Returns
* time in s.
2002-07-03 12:06:54 -07:00
\*-------------------------------------------------------------------------*/
2004-06-16 17:18:48 -07:00
#ifdef _WIN32
2019-02-27 20:01:16 -08:00
double timeout_gettime(void) {
2004-06-30 20:32:09 -07:00
FILETIME ft;
double t;
2004-06-30 20:32:09 -07:00
GetSystemTimeAsFileTime(&ft);
/* Windows file time (time since January 1, 1601 (UTC)) */
t = ft.dwLowDateTime/1.0e7 + ft.dwHighDateTime*(4294967296.0/1.0e7);
/* convert to Unix Epoch time (time since January 1, 1970 (UTC)) */
return (t - 11644473600.0);
2002-07-03 12:06:54 -07:00
}
#else
2019-02-27 20:01:16 -08:00
double timeout_gettime(void) {
2004-06-20 15:19:54 -07:00
struct timeval v;
2004-06-21 21:49:57 -07:00
gettimeofday(&v, (struct timezone *) NULL);
/* Unix Epoch time (time since January 1, 1970 (UTC)) */
2004-06-30 20:32:09 -07:00
return v.tv_sec + v.tv_usec/1.0e6;
2002-07-03 12:06:54 -07:00
}
#endif
/*-------------------------------------------------------------------------*\
* Initializes module
\*-------------------------------------------------------------------------*/
2019-02-27 20:01:16 -08:00
int timeout_open(lua_State *L) {
luaL_setfuncs(L, func, 0);
return 0;
2003-05-24 18:54:13 -07:00
}
/*-------------------------------------------------------------------------*\
* Sets timeout values for IO operations
* Lua Input: base, time [, mode]
* time: time out value in seconds
* mode: "b" for block timeout, "t" for total timeout. (default: b)
\*-------------------------------------------------------------------------*/
2019-02-27 20:01:16 -08:00
int timeout_meth_settimeout(lua_State *L, p_timeout tm) {
2004-06-30 20:32:09 -07:00
double t = luaL_optnumber(L, 2, -1);
2003-05-24 18:54:13 -07:00
const char *mode = luaL_optstring(L, 3, "b");
switch (*mode) {
case 'b':
tm->block = t;
2003-05-24 18:54:13 -07:00
break;
case 'r': case 't':
2004-06-30 20:32:09 -07:00
tm->total = t;
2003-05-24 18:54:13 -07:00
break;
default:
luaL_argcheck(L, 0, 3, "invalid timeout mode");
break;
}
lua_pushnumber(L, 1);
return 1;
2002-07-03 12:06:54 -07:00
}
/*-------------------------------------------------------------------------*\
* Gets timeout values for IO operations
* Lua Output: block, total
\*-------------------------------------------------------------------------*/
2019-02-27 20:01:16 -08:00
int timeout_meth_gettimeout(lua_State *L, p_timeout tm) {
lua_pushnumber(L, tm->block);
lua_pushnumber(L, tm->total);
return 2;
}
2002-07-03 12:06:54 -07:00
/*=========================================================================*\
* Test support functions
\*=========================================================================*/
/*-------------------------------------------------------------------------*\
* Returns the time the system has been up, in secconds.
\*-------------------------------------------------------------------------*/
2005-10-06 21:40:59 -07:00
static int timeout_lua_gettime(lua_State *L)
2002-07-03 12:06:54 -07:00
{
2005-10-06 21:40:59 -07:00
lua_pushnumber(L, timeout_gettime());
2002-07-03 12:06:54 -07:00
return 1;
}
/*-------------------------------------------------------------------------*\
* Sleep for n seconds.
\*-------------------------------------------------------------------------*/
2009-05-27 02:31:38 -07:00
#ifdef _WIN32
2019-02-27 20:01:16 -08:00
int timeout_lua_sleep(lua_State *L)
2002-07-03 12:06:54 -07:00
{
2003-03-20 15:11:25 -08:00
double n = luaL_checknumber(L, 1);
2009-05-27 02:31:38 -07:00
if (n < 0.0) n = 0.0;
if (n < DBL_MAX/1000.0) n *= 1000.0;
if (n > INT_MAX) n = INT_MAX;
Sleep((int)n);
return 0;
}
2002-07-03 12:06:54 -07:00
#else
2019-02-27 20:01:16 -08:00
int timeout_lua_sleep(lua_State *L)
2009-05-27 02:31:38 -07:00
{
double n = luaL_checknumber(L, 1);
2004-06-20 15:19:54 -07:00
struct timespec t, r;
2009-05-27 02:31:38 -07:00
if (n < 0.0) n = 0.0;
if (n > INT_MAX) n = INT_MAX;
2004-06-20 15:19:54 -07:00
t.tv_sec = (int) n;
n -= t.tv_sec;
t.tv_nsec = (int) (n * 1000000000);
if (t.tv_nsec >= 1000000000) t.tv_nsec = 999999999;
2004-08-04 13:51:57 -07:00
while (nanosleep(&t, &r) != 0) {
t.tv_sec = r.tv_sec;
t.tv_nsec = r.tv_nsec;
}
2002-07-03 12:06:54 -07:00
return 0;
}
2009-05-27 02:31:38 -07:00
#endif