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