2002-07-03 21:06:54 +02:00
|
|
|
/*=========================================================================*\
|
|
|
|
* Timeout management functions
|
2003-06-26 20:47:49 +02:00
|
|
|
* LuaSocket toolkit
|
2003-03-28 22:08:50 +01:00
|
|
|
*
|
|
|
|
* RCS ID: $Id$
|
2002-07-03 21:06:54 +02:00
|
|
|
\*=========================================================================*/
|
2003-05-25 03:54:13 +02:00
|
|
|
#include <stdio.h>
|
|
|
|
|
2002-07-03 21:06:54 +02:00
|
|
|
#include <lua.h>
|
|
|
|
#include <lauxlib.h>
|
|
|
|
|
2003-05-25 03:54:13 +02:00
|
|
|
#include "luasocket.h"
|
2003-06-09 20:23:40 +02:00
|
|
|
#include "auxiliar.h"
|
|
|
|
#include "timeout.h"
|
2002-07-03 21:06:54 +02:00
|
|
|
|
2004-06-17 02:18:48 +02:00
|
|
|
#ifdef _WIN32
|
2002-07-03 21:06:54 +02:00
|
|
|
#include <windows.h>
|
|
|
|
#else
|
2004-01-17 01:17:46 +01:00
|
|
|
#include <time.h>
|
2003-11-27 01:30:54 +01:00
|
|
|
#include <sys/time.h>
|
2002-07-03 21:06:54 +02:00
|
|
|
#endif
|
|
|
|
|
2004-06-15 08:24:00 +02:00
|
|
|
/* 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 21:06:54 +02:00
|
|
|
/*=========================================================================*\
|
|
|
|
* Internal function prototypes
|
|
|
|
\*=========================================================================*/
|
2004-06-21 00:19:54 +02:00
|
|
|
static int tm_lua_gettime(lua_State *L);
|
2002-07-03 21:06:54 +02:00
|
|
|
static int tm_lua_sleep(lua_State *L);
|
|
|
|
|
2003-05-25 03:54:13 +02:00
|
|
|
static luaL_reg func[] = {
|
2004-06-21 00:19:54 +02:00
|
|
|
{ "gettime", tm_lua_gettime },
|
2003-05-25 03:54:13 +02:00
|
|
|
{ "sleep", tm_lua_sleep },
|
|
|
|
{ NULL, NULL }
|
|
|
|
};
|
|
|
|
|
2002-07-03 21:06:54 +02:00
|
|
|
/*=========================================================================*\
|
|
|
|
* Exported functions.
|
|
|
|
\*=========================================================================*/
|
|
|
|
/*-------------------------------------------------------------------------*\
|
2003-05-25 03:54:13 +02:00
|
|
|
* Initialize structure
|
2002-07-03 21:06:54 +02:00
|
|
|
\*-------------------------------------------------------------------------*/
|
2003-05-25 03:54:13 +02:00
|
|
|
void tm_init(p_tm tm, int block, int total)
|
2002-07-03 21:06:54 +02:00
|
|
|
{
|
2003-05-25 03:54:13 +02:00
|
|
|
tm->block = block;
|
|
|
|
tm->total = total;
|
2002-07-03 21:06:54 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*-------------------------------------------------------------------------*\
|
2003-11-27 01:30:54 +01:00
|
|
|
* Determines how much time we have left for the next system call,
|
|
|
|
* if the previous call was successful
|
|
|
|
* Input
|
|
|
|
* tm: timeout control structure
|
|
|
|
* Returns
|
|
|
|
* the number of ms left or -1 if there is no time limit
|
|
|
|
\*-------------------------------------------------------------------------*/
|
2004-01-18 01:04:20 +01:00
|
|
|
int tm_get(p_tm tm)
|
2003-11-27 01:30:54 +01:00
|
|
|
{
|
|
|
|
if (tm->block < 0 && tm->total < 0) {
|
|
|
|
return -1;
|
|
|
|
} else if (tm->block < 0) {
|
|
|
|
int t = tm->total - tm_gettime() + tm->start;
|
|
|
|
return MAX(t, 0);
|
|
|
|
} else if (tm->total < 0) {
|
|
|
|
return tm->block;
|
|
|
|
} else {
|
|
|
|
int t = tm->total - tm_gettime() + tm->start;
|
|
|
|
return MIN(tm->block, MAX(t, 0));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*-------------------------------------------------------------------------*\
|
|
|
|
* Returns time since start of operation
|
|
|
|
* Input
|
|
|
|
* tm: timeout control structure
|
|
|
|
* Returns
|
|
|
|
* start field of structure
|
2002-07-03 21:06:54 +02:00
|
|
|
\*-------------------------------------------------------------------------*/
|
2003-05-25 03:54:13 +02:00
|
|
|
int tm_getstart(p_tm tm)
|
2003-11-27 01:30:54 +01:00
|
|
|
{
|
|
|
|
return tm->start;
|
|
|
|
}
|
2002-07-03 21:06:54 +02:00
|
|
|
|
|
|
|
/*-------------------------------------------------------------------------*\
|
2003-11-27 01:30:54 +01:00
|
|
|
* Determines how much time we have left for the next system call,
|
|
|
|
* if the previous call was a failure
|
2002-07-03 21:06:54 +02:00
|
|
|
* Input
|
|
|
|
* tm: timeout control structure
|
|
|
|
* Returns
|
|
|
|
* the number of ms left or -1 if there is no time limit
|
|
|
|
\*-------------------------------------------------------------------------*/
|
2004-01-18 01:04:20 +01:00
|
|
|
int tm_getretry(p_tm tm)
|
2002-07-03 21:06:54 +02:00
|
|
|
{
|
2003-11-27 01:30:54 +01:00
|
|
|
if (tm->block < 0 && tm->total < 0) {
|
2002-07-03 21:06:54 +02:00
|
|
|
return -1;
|
2003-11-27 01:30:54 +01:00
|
|
|
} else if (tm->block < 0) {
|
|
|
|
int t = tm->total - tm_gettime() + tm->start;
|
|
|
|
return MAX(t, 0);
|
|
|
|
} else if (tm->total < 0) {
|
|
|
|
int t = tm->block - tm_gettime() + tm->start;
|
|
|
|
return MAX(t, 0);
|
|
|
|
} else {
|
|
|
|
int t = tm->total - tm_gettime() + tm->start;
|
|
|
|
return MIN(tm->block, MAX(t, 0));
|
|
|
|
}
|
2002-07-03 21:06:54 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*-------------------------------------------------------------------------*\
|
2003-05-25 03:54:13 +02:00
|
|
|
* Marks the operation start time in structure
|
2002-07-03 21:06:54 +02:00
|
|
|
* Input
|
|
|
|
* tm: timeout control structure
|
|
|
|
\*-------------------------------------------------------------------------*/
|
2004-01-21 19:40:52 +01:00
|
|
|
p_tm tm_markstart(p_tm tm)
|
2002-07-03 21:06:54 +02:00
|
|
|
{
|
2003-05-25 03:54:13 +02:00
|
|
|
tm->start = tm_gettime();
|
2004-01-21 19:40:52 +01:00
|
|
|
return tm;
|
2002-07-03 21:06:54 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*-------------------------------------------------------------------------*\
|
|
|
|
* Gets time in ms, relative to system startup.
|
|
|
|
* Returns
|
|
|
|
* time in ms.
|
|
|
|
\*-------------------------------------------------------------------------*/
|
2004-06-17 02:18:48 +02:00
|
|
|
#ifdef _WIN32
|
2002-07-03 21:06:54 +02:00
|
|
|
int tm_gettime(void)
|
|
|
|
{
|
|
|
|
return GetTickCount();
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
int tm_gettime(void)
|
|
|
|
{
|
2004-06-21 00:19:54 +02:00
|
|
|
struct timeval v;
|
2004-06-22 06:49:57 +02:00
|
|
|
gettimeofday(&v, (struct timezone *) NULL);
|
2004-06-21 00:19:54 +02:00
|
|
|
return v.tv_sec * 1000 + v.tv_usec/1000;
|
2002-07-03 21:06:54 +02:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/*-------------------------------------------------------------------------*\
|
|
|
|
* Initializes module
|
|
|
|
\*-------------------------------------------------------------------------*/
|
2004-02-04 15:29:11 +01:00
|
|
|
int tm_open(lua_State *L)
|
2002-07-03 21:06:54 +02:00
|
|
|
{
|
2004-06-04 17:15:45 +02:00
|
|
|
luaL_openlib(L, NULL, func, 0);
|
2004-02-04 15:29:11 +01:00
|
|
|
return 0;
|
2003-05-25 03:54:13 +02: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)
|
|
|
|
\*-------------------------------------------------------------------------*/
|
2003-08-16 02:06:04 +02:00
|
|
|
int tm_meth_settimeout(lua_State *L, p_tm tm)
|
2003-05-25 03:54:13 +02:00
|
|
|
{
|
|
|
|
int ms = lua_isnil(L, 2) ? -1 : (int) (luaL_checknumber(L, 2)*1000.0);
|
|
|
|
const char *mode = luaL_optstring(L, 3, "b");
|
|
|
|
switch (*mode) {
|
|
|
|
case 'b':
|
2003-11-27 01:30:54 +01:00
|
|
|
tm->block = ms;
|
2003-05-25 03:54:13 +02:00
|
|
|
break;
|
|
|
|
case 'r': case 't':
|
2003-11-27 01:30:54 +01:00
|
|
|
tm->total = ms;
|
2003-05-25 03:54:13 +02:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
luaL_argcheck(L, 0, 3, "invalid timeout mode");
|
|
|
|
break;
|
|
|
|
}
|
2004-03-22 08:45:07 +01:00
|
|
|
lua_pushnumber(L, 1);
|
|
|
|
return 1;
|
2002-07-03 21:06:54 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*=========================================================================*\
|
|
|
|
* Test support functions
|
|
|
|
\*=========================================================================*/
|
|
|
|
/*-------------------------------------------------------------------------*\
|
|
|
|
* Returns the time the system has been up, in secconds.
|
|
|
|
\*-------------------------------------------------------------------------*/
|
2004-06-21 00:19:54 +02:00
|
|
|
static int tm_lua_gettime(lua_State *L)
|
2002-07-03 21:06:54 +02:00
|
|
|
{
|
|
|
|
lua_pushnumber(L, tm_gettime()/1000.0);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*-------------------------------------------------------------------------*\
|
|
|
|
* Sleep for n seconds.
|
|
|
|
\*-------------------------------------------------------------------------*/
|
|
|
|
int tm_lua_sleep(lua_State *L)
|
|
|
|
{
|
2003-03-21 00:11:25 +01:00
|
|
|
double n = luaL_checknumber(L, 1);
|
2004-06-17 02:18:48 +02:00
|
|
|
#ifdef _WIN32
|
2004-06-21 00:19:54 +02:00
|
|
|
Sleep((int)(n*1000));
|
2002-07-03 21:06:54 +02:00
|
|
|
#else
|
2004-06-21 00:19:54 +02:00
|
|
|
struct timespec t, r;
|
|
|
|
t.tv_sec = (int) n;
|
|
|
|
n -= t.tv_sec;
|
|
|
|
t.tv_nsec = (int) (n * 1000000000) % 1000000000;
|
|
|
|
nanosleep(&t, &r);
|
2002-07-03 21:06:54 +02:00
|
|
|
#endif
|
|
|
|
return 0;
|
|
|
|
}
|