beta-0.89.2
[luatex.git] / source / texk / web2c / luatexdir / luasocket / src / timeout.c
blobc7354b52f3867255d8df6920d55300b3aa7e70f3
1 /*=========================================================================*\
2 * Timeout management functions
3 * LuaSocket toolkit
4 \*=========================================================================*/
5 #include <stdio.h>
6 #include <limits.h>
7 #include <float.h>
9 #include "lua.h"
10 #include "lauxlib.h"
12 #include "auxiliar.h"
13 #include "timeout.h"
15 #ifdef _WIN32
16 #include <windows.h>
17 #else
18 #include <time.h>
19 #include <sys/time.h>
20 #endif
22 /* min and max macros */
23 #ifndef MIN
24 #define MIN(x, y) ((x) < (y) ? x : y)
25 #endif
26 #ifndef MAX
27 #define MAX(x, y) ((x) > (y) ? x : y)
28 #endif
30 /*=========================================================================*\
31 * Internal function prototypes
32 \*=========================================================================*/
33 static int timeout_lua_gettime(lua_State *L);
34 static int timeout_lua_sleep(lua_State *L);
36 static luaL_Reg func[] = {
37 { "gettime", timeout_lua_gettime },
38 { "sleep", timeout_lua_sleep },
39 { NULL, NULL }
42 /*=========================================================================*\
43 * Exported functions.
44 \*=========================================================================*/
45 /*-------------------------------------------------------------------------*\
46 * Initialize structure
47 \*-------------------------------------------------------------------------*/
48 void timeout_init(p_timeout tm, double block, double total) {
49 tm->block = block;
50 tm->total = total;
53 /*-------------------------------------------------------------------------*\
54 * Determines how much time we have left for the next system call,
55 * if the previous call was successful
56 * Input
57 * tm: timeout control structure
58 * Returns
59 * the number of ms left or -1 if there is no time limit
60 \*-------------------------------------------------------------------------*/
61 double timeout_get(p_timeout tm) {
62 if (tm->block < 0.0 && tm->total < 0.0) {
63 return -1;
64 } else if (tm->block < 0.0) {
65 double t = tm->total - timeout_gettime() + tm->start;
66 return MAX(t, 0.0);
67 } else if (tm->total < 0.0) {
68 return tm->block;
69 } else {
70 double t = tm->total - timeout_gettime() + tm->start;
71 return MIN(tm->block, MAX(t, 0.0));
75 /*-------------------------------------------------------------------------*\
76 * Returns time since start of operation
77 * Input
78 * tm: timeout control structure
79 * Returns
80 * start field of structure
81 \*-------------------------------------------------------------------------*/
82 double timeout_getstart(p_timeout tm) {
83 return tm->start;
86 /*-------------------------------------------------------------------------*\
87 * Determines how much time we have left for the next system call,
88 * if the previous call was a failure
89 * Input
90 * tm: timeout control structure
91 * Returns
92 * the number of ms left or -1 if there is no time limit
93 \*-------------------------------------------------------------------------*/
94 double timeout_getretry(p_timeout tm) {
95 if (tm->block < 0.0 && tm->total < 0.0) {
96 return -1;
97 } else if (tm->block < 0.0) {
98 double t = tm->total - timeout_gettime() + tm->start;
99 return MAX(t, 0.0);
100 } else if (tm->total < 0.0) {
101 double t = tm->block - timeout_gettime() + tm->start;
102 return MAX(t, 0.0);
103 } else {
104 double t = tm->total - timeout_gettime() + tm->start;
105 return MIN(tm->block, MAX(t, 0.0));
109 /*-------------------------------------------------------------------------*\
110 * Marks the operation start time in structure
111 * Input
112 * tm: timeout control structure
113 \*-------------------------------------------------------------------------*/
114 p_timeout timeout_markstart(p_timeout tm) {
115 tm->start = timeout_gettime();
116 return tm;
119 /*-------------------------------------------------------------------------*\
120 * Gets time in s, relative to January 1, 1970 (UTC)
121 * Returns
122 * time in s.
123 \*-------------------------------------------------------------------------*/
124 #ifdef _WIN32
125 double timeout_gettime(void) {
126 FILETIME ft;
127 double t;
128 GetSystemTimeAsFileTime(&ft);
129 /* Windows file time (time since January 1, 1601 (UTC)) */
130 t = ft.dwLowDateTime/1.0e7 + ft.dwHighDateTime*(4294967296.0/1.0e7);
131 /* convert to Unix Epoch time (time since January 1, 1970 (UTC)) */
132 return (t - 11644473600.0);
134 #else
135 double timeout_gettime(void) {
136 struct timeval v;
137 gettimeofday(&v, (struct timezone *) NULL);
138 /* Unix Epoch time (time since January 1, 1970 (UTC)) */
139 return v.tv_sec + v.tv_usec/1.0e6;
141 #endif
143 /*-------------------------------------------------------------------------*\
144 * Initializes module
145 \*-------------------------------------------------------------------------*/
146 int timeout_open(lua_State *L) {
147 luaL_openlib(L, NULL, func, 0);
148 return 0;
151 /*-------------------------------------------------------------------------*\
152 * Sets timeout values for IO operations
153 * Lua Input: base, time [, mode]
154 * time: time out value in seconds
155 * mode: "b" for block timeout, "t" for total timeout. (default: b)
156 \*-------------------------------------------------------------------------*/
157 int timeout_meth_settimeout(lua_State *L, p_timeout tm) {
158 double t = luaL_optnumber(L, 2, -1);
159 const char *mode = luaL_optstring(L, 3, "b");
160 switch (*mode) {
161 case 'b':
162 tm->block = t;
163 break;
164 case 'r': case 't':
165 tm->total = t;
166 break;
167 default:
168 luaL_argcheck(L, 0, 3, "invalid timeout mode");
169 break;
171 lua_pushnumber(L, 1);
172 return 1;
175 /*=========================================================================*\
176 * Test support functions
177 \*=========================================================================*/
178 /*-------------------------------------------------------------------------*\
179 * Returns the time the system has been up, in secconds.
180 \*-------------------------------------------------------------------------*/
181 static int timeout_lua_gettime(lua_State *L)
183 lua_pushnumber(L, timeout_gettime());
184 return 1;
187 /*-------------------------------------------------------------------------*\
188 * Sleep for n seconds.
189 \*-------------------------------------------------------------------------*/
190 #ifdef _WIN32
191 int timeout_lua_sleep(lua_State *L)
193 double n = luaL_checknumber(L, 1);
194 if (n < 0.0) n = 0.0;
195 if (n < DBL_MAX/1000.0) n *= 1000.0;
196 if (n > INT_MAX) n = INT_MAX;
197 Sleep((int)n);
198 return 0;
200 #else
201 int timeout_lua_sleep(lua_State *L)
203 double n = luaL_checknumber(L, 1);
204 struct timespec t, r;
205 if (n < 0.0) n = 0.0;
206 if (n > INT_MAX) n = INT_MAX;
207 t.tv_sec = (int) n;
208 n -= t.tv_sec;
209 t.tv_nsec = (int) (n * 1000000000);
210 if (t.tv_nsec >= 1000000000) t.tv_nsec = 999999999;
211 while (nanosleep(&t, &r) != 0) {
212 t.tv_sec = r.tv_sec;
213 t.tv_nsec = r.tv_nsec;
215 return 0;
217 #endif