226 lines
		
	
	
		
			7.0 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
		
		
			
		
	
	
			226 lines
		
	
	
		
			7.0 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| 
								 | 
							
								/*=========================================================================*\
							 | 
						||
| 
								 | 
							
								* Timeout management functions
							 | 
						||
| 
								 | 
							
								* LuaSocket toolkit
							 | 
						||
| 
								 | 
							
								\*=========================================================================*/
							 | 
						||
| 
								 | 
							
								#include <stdio.h>
							 | 
						||
| 
								 | 
							
								#include <limits.h>
							 | 
						||
| 
								 | 
							
								#include <float.h>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include "lua.h"
							 | 
						||
| 
								 | 
							
								#include "lauxlib.h"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include "auxiliar.h"
							 | 
						||
| 
								 | 
							
								#include "timeout.h"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifdef _WIN32
							 | 
						||
| 
								 | 
							
								#include <windows.h>
							 | 
						||
| 
								 | 
							
								#else
							 | 
						||
| 
								 | 
							
								#include <time.h>
							 | 
						||
| 
								 | 
							
								#include <sys/time.h>
							 | 
						||
| 
								 | 
							
								#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
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								namespace NS_SLUA {    
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*=========================================================================*\
							 | 
						||
| 
								 | 
							
								* Internal function prototypes
							 | 
						||
| 
								 | 
							
								\*=========================================================================*/
							 | 
						||
| 
								 | 
							
								static int timeout_lua_gettime(lua_State *L);
							 | 
						||
| 
								 | 
							
								static int timeout_lua_sleep(lua_State *L);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static luaL_Reg timeout_func[] = {
							 | 
						||
| 
								 | 
							
								    { "gettime", timeout_lua_gettime },
							 | 
						||
| 
								 | 
							
								    { "sleep", timeout_lua_sleep },
							 | 
						||
| 
								 | 
							
								    { NULL, NULL }
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*=========================================================================*\
							 | 
						||
| 
								 | 
							
								* Exported functions.
							 | 
						||
| 
								 | 
							
								\*=========================================================================*/
							 | 
						||
| 
								 | 
							
								/*-------------------------------------------------------------------------*\
							 | 
						||
| 
								 | 
							
								* Initialize structure
							 | 
						||
| 
								 | 
							
								\*-------------------------------------------------------------------------*/
							 | 
						||
| 
								 | 
							
								void timeout_init(p_timeout tm, double block, double total) {
							 | 
						||
| 
								 | 
							
								    tm->block = block;
							 | 
						||
| 
								 | 
							
								    tm->total = total;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*-------------------------------------------------------------------------*\
							 | 
						||
| 
								 | 
							
								* 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
							 | 
						||
| 
								 | 
							
								\*-------------------------------------------------------------------------*/
							 | 
						||
| 
								 | 
							
								double timeout_get(p_timeout tm) {
							 | 
						||
| 
								 | 
							
								    if (tm->block < 0.0 && tm->total < 0.0) {
							 | 
						||
| 
								 | 
							
								        return -1;
							 | 
						||
| 
								 | 
							
								    } else if (tm->block < 0.0) {
							 | 
						||
| 
								 | 
							
								        double t = tm->total - timeout_gettime() + tm->start;
							 | 
						||
| 
								 | 
							
								        return MAX(t, 0.0);
							 | 
						||
| 
								 | 
							
								    } else if (tm->total < 0.0) {
							 | 
						||
| 
								 | 
							
								        return tm->block;
							 | 
						||
| 
								 | 
							
								    } else {
							 | 
						||
| 
								 | 
							
								        double t = tm->total - timeout_gettime() + tm->start;
							 | 
						||
| 
								 | 
							
								        return MIN(tm->block, MAX(t, 0.0));
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*-------------------------------------------------------------------------*\
							 | 
						||
| 
								 | 
							
								* Returns time since start of operation
							 | 
						||
| 
								 | 
							
								* Input
							 | 
						||
| 
								 | 
							
								*   tm: timeout control structure
							 | 
						||
| 
								 | 
							
								* Returns
							 | 
						||
| 
								 | 
							
								*   start field of structure
							 | 
						||
| 
								 | 
							
								\*-------------------------------------------------------------------------*/
							 | 
						||
| 
								 | 
							
								double timeout_getstart(p_timeout tm) {
							 | 
						||
| 
								 | 
							
								    return tm->start;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*-------------------------------------------------------------------------*\
							 | 
						||
| 
								 | 
							
								* Determines how much time we have left for the next system call,
							 | 
						||
| 
								 | 
							
								* if the previous call was a failure
							 | 
						||
| 
								 | 
							
								* Input
							 | 
						||
| 
								 | 
							
								*   tm: timeout control structure
							 | 
						||
| 
								 | 
							
								* Returns
							 | 
						||
| 
								 | 
							
								*   the number of ms left or -1 if there is no time limit
							 | 
						||
| 
								 | 
							
								\*-------------------------------------------------------------------------*/
							 | 
						||
| 
								 | 
							
								double timeout_getretry(p_timeout tm) {
							 | 
						||
| 
								 | 
							
								    if (tm->block < 0.0 && tm->total < 0.0) {
							 | 
						||
| 
								 | 
							
								        return -1;
							 | 
						||
| 
								 | 
							
								    } else if (tm->block < 0.0) {
							 | 
						||
| 
								 | 
							
								        double t = tm->total - timeout_gettime() + tm->start;
							 | 
						||
| 
								 | 
							
								        return MAX(t, 0.0);
							 | 
						||
| 
								 | 
							
								    } else if (tm->total < 0.0) {
							 | 
						||
| 
								 | 
							
								        double t = tm->block - timeout_gettime() + tm->start;
							 | 
						||
| 
								 | 
							
								        return MAX(t, 0.0);
							 | 
						||
| 
								 | 
							
								    } else {
							 | 
						||
| 
								 | 
							
								        double t = tm->total - timeout_gettime() + tm->start;
							 | 
						||
| 
								 | 
							
								        return MIN(tm->block, MAX(t, 0.0));
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*-------------------------------------------------------------------------*\
							 | 
						||
| 
								 | 
							
								* Marks the operation start time in structure 
							 | 
						||
| 
								 | 
							
								* Input
							 | 
						||
| 
								 | 
							
								*   tm: timeout control structure
							 | 
						||
| 
								 | 
							
								\*-------------------------------------------------------------------------*/
							 | 
						||
| 
								 | 
							
								p_timeout timeout_markstart(p_timeout tm) {
							 | 
						||
| 
								 | 
							
								    tm->start = timeout_gettime();
							 | 
						||
| 
								 | 
							
								    return tm;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*-------------------------------------------------------------------------*\
							 | 
						||
| 
								 | 
							
								* Gets time in s, relative to January 1, 1970 (UTC) 
							 | 
						||
| 
								 | 
							
								* Returns
							 | 
						||
| 
								 | 
							
								*   time in s.
							 | 
						||
| 
								 | 
							
								\*-------------------------------------------------------------------------*/
							 | 
						||
| 
								 | 
							
								#ifdef _WIN32
							 | 
						||
| 
								 | 
							
								double timeout_gettime(void) {
							 | 
						||
| 
								 | 
							
								    FILETIME ft;
							 | 
						||
| 
								 | 
							
								    double t;
							 | 
						||
| 
								 | 
							
								    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);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								#else
							 | 
						||
| 
								 | 
							
								double timeout_gettime(void) {
							 | 
						||
| 
								 | 
							
								    struct timeval v;
							 | 
						||
| 
								 | 
							
								    gettimeofday(&v, (struct timezone *) NULL);
							 | 
						||
| 
								 | 
							
								    /* Unix Epoch time (time since January 1, 1970 (UTC)) */
							 | 
						||
| 
								 | 
							
								    return v.tv_sec + v.tv_usec/1.0e6;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*-------------------------------------------------------------------------*\
							 | 
						||
| 
								 | 
							
								* Initializes module
							 | 
						||
| 
								 | 
							
								\*-------------------------------------------------------------------------*/
							 | 
						||
| 
								 | 
							
								int timeout_open(lua_State *L) {
							 | 
						||
| 
								 | 
							
								#if LUA_VERSION_NUM > 501 && !defined(LUA_COMPAT_MODULE)
							 | 
						||
| 
								 | 
							
								    luaL_setfuncs(L, timeout_func, 0);
							 | 
						||
| 
								 | 
							
								#else
							 | 
						||
| 
								 | 
							
								    luaL_openlib(L, NULL, timeout_func, 0);
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								    return 0;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*-------------------------------------------------------------------------*\
							 | 
						||
| 
								 | 
							
								* 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)
							 | 
						||
| 
								 | 
							
								\*-------------------------------------------------------------------------*/
							 | 
						||
| 
								 | 
							
								int timeout_meth_settimeout(lua_State *L, p_timeout tm) {
							 | 
						||
| 
								 | 
							
								    double t = luaL_optnumber(L, 2, -1);
							 | 
						||
| 
								 | 
							
								    const char *mode = luaL_optstring(L, 3, "b");
							 | 
						||
| 
								 | 
							
								    switch (*mode) {
							 | 
						||
| 
								 | 
							
								        case 'b':
							 | 
						||
| 
								 | 
							
								            tm->block = t; 
							 | 
						||
| 
								 | 
							
								            break;
							 | 
						||
| 
								 | 
							
								        case 'r': case 't':
							 | 
						||
| 
								 | 
							
								            tm->total = t;
							 | 
						||
| 
								 | 
							
								            break;
							 | 
						||
| 
								 | 
							
								        default:
							 | 
						||
| 
								 | 
							
								            luaL_argcheck(L, 0, 3, "invalid timeout mode");
							 | 
						||
| 
								 | 
							
								            break;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    lua_pushnumber(L, 1);
							 | 
						||
| 
								 | 
							
								    return 1;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*=========================================================================*\
							 | 
						||
| 
								 | 
							
								* Test support functions
							 | 
						||
| 
								 | 
							
								\*=========================================================================*/
							 | 
						||
| 
								 | 
							
								/*-------------------------------------------------------------------------*\
							 | 
						||
| 
								 | 
							
								* Returns the time the system has been up, in secconds.
							 | 
						||
| 
								 | 
							
								\*-------------------------------------------------------------------------*/
							 | 
						||
| 
								 | 
							
								static int timeout_lua_gettime(lua_State *L)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    lua_pushnumber(L, timeout_gettime());
							 | 
						||
| 
								 | 
							
								    return 1;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*-------------------------------------------------------------------------*\
							 | 
						||
| 
								 | 
							
								* Sleep for n seconds.
							 | 
						||
| 
								 | 
							
								\*-------------------------------------------------------------------------*/
							 | 
						||
| 
								 | 
							
								#ifdef _WIN32
							 | 
						||
| 
								 | 
							
								int timeout_lua_sleep(lua_State *L)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    double n = luaL_checknumber(L, 1);
							 | 
						||
| 
								 | 
							
								    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;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								#else
							 | 
						||
| 
								 | 
							
								int timeout_lua_sleep(lua_State *L)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    double n = luaL_checknumber(L, 1);
							 | 
						||
| 
								 | 
							
								    struct timespec t, r;
							 | 
						||
| 
								 | 
							
								    if (n < 0.0) n = 0.0;
							 | 
						||
| 
								 | 
							
								    if (n > INT_MAX) n = INT_MAX;
							 | 
						||
| 
								 | 
							
								    t.tv_sec = (int) n;
							 | 
						||
| 
								 | 
							
								    n -= t.tv_sec;
							 | 
						||
| 
								 | 
							
								    t.tv_nsec = (int) (n * 1000000000);
							 | 
						||
| 
								 | 
							
								    if (t.tv_nsec >= 1000000000) t.tv_nsec = 999999999;
							 | 
						||
| 
								 | 
							
								    while (nanosleep(&t, &r) != 0) {
							 | 
						||
| 
								 | 
							
								        t.tv_sec = r.tv_sec;
							 | 
						||
| 
								 | 
							
								        t.tv_nsec = r.tv_nsec;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    return 0;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								} // end NS_SLUA
							 |