diff options
Diffstat (limited to 'vendor/luasocket/src/timeout.c')
-rw-r--r-- | vendor/luasocket/src/timeout.c | 226 |
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 | \*=========================================================================*/ | ||
32 | static int timeout_lua_gettime(lua_State *L); | ||
33 | static int timeout_lua_sleep(lua_State *L); | ||
34 | |||
35 | static 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 | \*-------------------------------------------------------------------------*/ | ||
47 | void 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 | \*-------------------------------------------------------------------------*/ | ||
60 | double 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 | \*-------------------------------------------------------------------------*/ | ||
81 | double 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 | \*-------------------------------------------------------------------------*/ | ||
93 | double 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 | \*-------------------------------------------------------------------------*/ | ||
113 | p_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 | ||
124 | double 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 | ||
134 | double 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 | \*-------------------------------------------------------------------------*/ | ||
145 | int 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 | \*-------------------------------------------------------------------------*/ | ||
156 | int 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 | \*-------------------------------------------------------------------------*/ | ||
178 | int 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 | \*-------------------------------------------------------------------------*/ | ||
190 | static 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 | ||
200 | int 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 | ||
210 | int 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 | ||