Mercurial > luasocket
comparison src/timeout.c @ 0:4b915342e2a8
LuaSocket 2.0.2 + CMake build description.
author | Eric Wing <ewing . public |-at-| gmail . com> |
---|---|
date | Tue, 26 Aug 2008 18:40:01 -0700 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:4b915342e2a8 |
---|---|
1 /*=========================================================================*\ | |
2 * Timeout management functions | |
3 * LuaSocket toolkit | |
4 * | |
5 * RCS ID: $Id: timeout.c,v 1.30 2005/10/07 04:40:59 diego Exp $ | |
6 \*=========================================================================*/ | |
7 #include <stdio.h> | |
8 | |
9 #include "lua.h" | |
10 #include "lauxlib.h" | |
11 | |
12 #include "auxiliar.h" | |
13 #include "timeout.h" | |
14 | |
15 #ifdef _WIN32 | |
16 #include <windows.h> | |
17 #else | |
18 #include <time.h> | |
19 #include <sys/time.h> | |
20 #endif | |
21 | |
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 | |
29 | |
30 /*=========================================================================*\ | |
31 * Internal function prototypes | |
32 \*=========================================================================*/ | |
33 static int timeout_lua_gettime(lua_State *L); | |
34 static int timeout_lua_sleep(lua_State *L); | |
35 | |
36 static luaL_reg func[] = { | |
37 { "gettime", timeout_lua_gettime }, | |
38 { "sleep", timeout_lua_sleep }, | |
39 { NULL, NULL } | |
40 }; | |
41 | |
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; | |
51 } | |
52 | |
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)); | |
72 } | |
73 } | |
74 | |
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; | |
84 } | |
85 | |
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)); | |
106 } | |
107 } | |
108 | |
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; | |
117 } | |
118 | |
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); | |
133 } | |
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; | |
140 } | |
141 #endif | |
142 | |
143 /*-------------------------------------------------------------------------*\ | |
144 * Initializes module | |
145 \*-------------------------------------------------------------------------*/ | |
146 int timeout_open(lua_State *L) { | |
147 luaL_openlib(L, NULL, func, 0); | |
148 return 0; | |
149 } | |
150 | |
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; | |
170 } | |
171 lua_pushnumber(L, 1); | |
172 return 1; | |
173 } | |
174 | |
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) | |
182 { | |
183 lua_pushnumber(L, timeout_gettime()); | |
184 return 1; | |
185 } | |
186 | |
187 /*-------------------------------------------------------------------------*\ | |
188 * Sleep for n seconds. | |
189 \*-------------------------------------------------------------------------*/ | |
190 int timeout_lua_sleep(lua_State *L) | |
191 { | |
192 double n = luaL_checknumber(L, 1); | |
193 #ifdef _WIN32 | |
194 Sleep((int)(n*1000)); | |
195 #else | |
196 struct timespec t, r; | |
197 t.tv_sec = (int) n; | |
198 n -= t.tv_sec; | |
199 t.tv_nsec = (int) (n * 1000000000); | |
200 if (t.tv_nsec >= 1000000000) t.tv_nsec = 999999999; | |
201 while (nanosleep(&t, &r) != 0) { | |
202 t.tv_sec = r.tv_sec; | |
203 t.tv_nsec = r.tv_nsec; | |
204 } | |
205 #endif | |
206 return 0; | |
207 } |