summaryrefslogtreecommitdiff
path: root/source/luametatex/source/luacore/luasocket/src/timeout.c
diff options
context:
space:
mode:
Diffstat (limited to 'source/luametatex/source/luacore/luasocket/src/timeout.c')
-rw-r--r--source/luametatex/source/luacore/luasocket/src/timeout.c226
1 files changed, 226 insertions, 0 deletions
diff --git a/source/luametatex/source/luacore/luasocket/src/timeout.c b/source/luametatex/source/luacore/luasocket/src/timeout.c
new file mode 100644
index 000000000..2bdc0698c
--- /dev/null
+++ b/source/luametatex/source/luacore/luasocket/src/timeout.c
@@ -0,0 +1,226 @@
+/*=========================================================================*\
+* Timeout management functions
+* LuaSocket toolkit
+\*=========================================================================*/
+#include "luasocket.h"
+
+#include "auxiliar.h"
+#include "timeout.h"
+
+#include <stdio.h>
+#include <limits.h>
+#include <float.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
+
+/*=========================================================================*\
+* Internal function prototypes
+\*=========================================================================*/
+static int timeout_lua_gettime(lua_State *L);
+static int timeout_lua_sleep(lua_State *L);
+
+static luaL_Reg 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) {
+ luaL_setfuncs(L, func, 0);
+ 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;
+}
+
+/*-------------------------------------------------------------------------*\
+* Gets timeout values for IO operations
+* Lua Output: block, total
+\*-------------------------------------------------------------------------*/
+int timeout_meth_gettimeout(lua_State *L, p_timeout tm) {
+ lua_pushnumber(L, tm->block);
+ lua_pushnumber(L, tm->total);
+ return 2;
+}
+
+/*=========================================================================*\
+* 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