162 |
163 |
163 // return true if yielded, false if done |
164 // return true if yielded, false if done |
164 return (thread->L != NULL); |
165 return (thread->L != NULL); |
165 } |
166 } |
166 |
167 |
167 void lua_thread_resume_state (lua_State *L) |
168 int lua_thread_yield_state (lua_State *L) |
|
169 { |
|
170 return lua_yield(L, 0); |
|
171 } |
|
172 |
|
173 static int _lua_thread_resume_state (lua_State *L) |
168 { |
174 { |
169 struct lua_thread *thread; |
175 struct lua_thread *thread; |
170 error_t err; |
176 error_t err; |
171 int ret; |
177 int ret; |
172 |
178 |
|
179 // pop irrelevant context arg |
|
180 lua_pop(L, 1); |
|
181 |
173 // lookup the thread's context |
182 // lookup the thread's context |
174 lua_pushthread(L); |
183 lua_pushthread(L); |
175 lua_gettable(L, LUA_REGISTRYINDEX); |
184 lua_gettable(L, LUA_REGISTRYINDEX); |
|
185 |
|
186 // not registered? |
|
187 if (lua_isnil(L, -1)) |
|
188 return luaL_error(L, "not a registered lua_thread state"); |
|
189 |
|
190 else if (lua_isboolean(L, -1) && !lua_toboolean(L, -1)) |
|
191 return luaL_error(L, "lua_thread was aborted"); |
176 |
192 |
177 // get it as a pointer |
193 // get it as a pointer |
178 if ((thread = lua_touserdata(L, -1)) == NULL) |
194 if ((thread = lua_touserdata(L, -1)) == NULL) |
179 luaL_error(L, "lua_thread_resume_state: lua_touserdata"); |
195 return luaL_error(L, "lua_touserdata"); |
|
196 else |
|
197 lua_pop(L, 1); |
180 |
198 |
181 // handle the resume |
199 // handle the resume |
182 if ((ret = lua_thread_resume(L, thread, &err)) < 0) |
200 if ((ret = lua_thread_resume(L, thread, &err)) < 0) |
183 // notify user |
201 // notify user |
184 return lua_thread_done(thread->L, thread, &err); |
202 lua_thread_done(thread->L, thread, &err); |
185 |
203 |
186 // finished? |
204 // finished? |
187 if (ret == 0) |
205 else if (ret == 0) |
188 return lua_thread_done(thread->L, thread, NULL); |
206 lua_thread_done(thread->L, thread, NULL); |
189 } |
207 |
190 |
208 // ok |
|
209 return 0; |
|
210 } |
|
211 |
|
212 void lua_thread_resume_state (lua_State *L) |
|
213 { |
|
214 error_t err; |
|
215 |
|
216 // execute in protected mode |
|
217 if (nexus_lua_error(L, lua_cpcall(L, _lua_thread_resume_state, NULL), &err)) |
|
218 log_warn_error(&err, "%p", L); |
|
219 } |
|
220 |
|
221 static int _lua_thread_abort (lua_State *L) |
|
222 { |
|
223 struct lua_thread *thread; |
|
224 |
|
225 // get context arg |
|
226 if ((thread = lua_touserdata(L, -1)) == NULL) |
|
227 luaL_error(L, "lua_thread_resume_state: lua_touserdata"); |
|
228 else |
|
229 lua_pop(L, 1); |
|
230 |
|
231 // no mechanism to actually abort the underlying wait yet |
|
232 (void) thread; |
|
233 |
|
234 // invalidate in registry for later lua_thread_resume_state |
|
235 lua_pushthread(L); |
|
236 lua_pushboolean(L, false); |
|
237 lua_settable(L, LUA_REGISTRYINDEX); |
|
238 |
|
239 // not much else we can do |
|
240 return 0; |
|
241 } |
|
242 |
|
243 void lua_thread_abort (struct lua_thread *thread) |
|
244 { |
|
245 error_t err; |
|
246 |
|
247 if (!thread->L) |
|
248 // no thread executing |
|
249 return; |
|
250 |
|
251 // use protected mode |
|
252 if (nexus_lua_error(thread->L, lua_cpcall(thread->L, _lua_thread_abort, thread), &err)) |
|
253 log_warn_error(&err, "_lua_thread_abort"); |
|
254 |
|
255 // unset |
|
256 thread->L = NULL; |
|
257 } |
|
258 |