Mercurial > mm7
comparison lib/lua/lua-5.2.2/lcorolib.c @ 1866:41cc4dd3c122
Lua 5.2.2 added.
author | Nomad |
---|---|
date | Wed, 16 Oct 2013 13:34:26 +0200 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
1848:3b39b70e8e93 | 1866:41cc4dd3c122 |
---|---|
1 /* | |
2 ** $Id: lcorolib.c,v 1.5 2013/02/21 13:44:53 roberto Exp $ | |
3 ** Coroutine Library | |
4 ** See Copyright Notice in lua.h | |
5 */ | |
6 | |
7 | |
8 #include <stdlib.h> | |
9 | |
10 | |
11 #define lcorolib_c | |
12 #define LUA_LIB | |
13 | |
14 #include "lua.h" | |
15 | |
16 #include "lauxlib.h" | |
17 #include "lualib.h" | |
18 | |
19 | |
20 static int auxresume (lua_State *L, lua_State *co, int narg) { | |
21 int status; | |
22 if (!lua_checkstack(co, narg)) { | |
23 lua_pushliteral(L, "too many arguments to resume"); | |
24 return -1; /* error flag */ | |
25 } | |
26 if (lua_status(co) == LUA_OK && lua_gettop(co) == 0) { | |
27 lua_pushliteral(L, "cannot resume dead coroutine"); | |
28 return -1; /* error flag */ | |
29 } | |
30 lua_xmove(L, co, narg); | |
31 status = lua_resume(co, L, narg); | |
32 if (status == LUA_OK || status == LUA_YIELD) { | |
33 int nres = lua_gettop(co); | |
34 if (!lua_checkstack(L, nres + 1)) { | |
35 lua_pop(co, nres); /* remove results anyway */ | |
36 lua_pushliteral(L, "too many results to resume"); | |
37 return -1; /* error flag */ | |
38 } | |
39 lua_xmove(co, L, nres); /* move yielded values */ | |
40 return nres; | |
41 } | |
42 else { | |
43 lua_xmove(co, L, 1); /* move error message */ | |
44 return -1; /* error flag */ | |
45 } | |
46 } | |
47 | |
48 | |
49 static int luaB_coresume (lua_State *L) { | |
50 lua_State *co = lua_tothread(L, 1); | |
51 int r; | |
52 luaL_argcheck(L, co, 1, "coroutine expected"); | |
53 r = auxresume(L, co, lua_gettop(L) - 1); | |
54 if (r < 0) { | |
55 lua_pushboolean(L, 0); | |
56 lua_insert(L, -2); | |
57 return 2; /* return false + error message */ | |
58 } | |
59 else { | |
60 lua_pushboolean(L, 1); | |
61 lua_insert(L, -(r + 1)); | |
62 return r + 1; /* return true + `resume' returns */ | |
63 } | |
64 } | |
65 | |
66 | |
67 static int luaB_auxwrap (lua_State *L) { | |
68 lua_State *co = lua_tothread(L, lua_upvalueindex(1)); | |
69 int r = auxresume(L, co, lua_gettop(L)); | |
70 if (r < 0) { | |
71 if (lua_isstring(L, -1)) { /* error object is a string? */ | |
72 luaL_where(L, 1); /* add extra info */ | |
73 lua_insert(L, -2); | |
74 lua_concat(L, 2); | |
75 } | |
76 return lua_error(L); /* propagate error */ | |
77 } | |
78 return r; | |
79 } | |
80 | |
81 | |
82 static int luaB_cocreate (lua_State *L) { | |
83 lua_State *NL; | |
84 luaL_checktype(L, 1, LUA_TFUNCTION); | |
85 NL = lua_newthread(L); | |
86 lua_pushvalue(L, 1); /* move function to top */ | |
87 lua_xmove(L, NL, 1); /* move function from L to NL */ | |
88 return 1; | |
89 } | |
90 | |
91 | |
92 static int luaB_cowrap (lua_State *L) { | |
93 luaB_cocreate(L); | |
94 lua_pushcclosure(L, luaB_auxwrap, 1); | |
95 return 1; | |
96 } | |
97 | |
98 | |
99 static int luaB_yield (lua_State *L) { | |
100 return lua_yield(L, lua_gettop(L)); | |
101 } | |
102 | |
103 | |
104 static int luaB_costatus (lua_State *L) { | |
105 lua_State *co = lua_tothread(L, 1); | |
106 luaL_argcheck(L, co, 1, "coroutine expected"); | |
107 if (L == co) lua_pushliteral(L, "running"); | |
108 else { | |
109 switch (lua_status(co)) { | |
110 case LUA_YIELD: | |
111 lua_pushliteral(L, "suspended"); | |
112 break; | |
113 case LUA_OK: { | |
114 lua_Debug ar; | |
115 if (lua_getstack(co, 0, &ar) > 0) /* does it have frames? */ | |
116 lua_pushliteral(L, "normal"); /* it is running */ | |
117 else if (lua_gettop(co) == 0) | |
118 lua_pushliteral(L, "dead"); | |
119 else | |
120 lua_pushliteral(L, "suspended"); /* initial state */ | |
121 break; | |
122 } | |
123 default: /* some error occurred */ | |
124 lua_pushliteral(L, "dead"); | |
125 break; | |
126 } | |
127 } | |
128 return 1; | |
129 } | |
130 | |
131 | |
132 static int luaB_corunning (lua_State *L) { | |
133 int ismain = lua_pushthread(L); | |
134 lua_pushboolean(L, ismain); | |
135 return 2; | |
136 } | |
137 | |
138 | |
139 static const luaL_Reg co_funcs[] = { | |
140 {"create", luaB_cocreate}, | |
141 {"resume", luaB_coresume}, | |
142 {"running", luaB_corunning}, | |
143 {"status", luaB_costatus}, | |
144 {"wrap", luaB_cowrap}, | |
145 {"yield", luaB_yield}, | |
146 {NULL, NULL} | |
147 }; | |
148 | |
149 | |
150 | |
151 LUAMOD_API int luaopen_coroutine (lua_State *L) { | |
152 luaL_newlib(L, co_funcs); | |
153 return 1; | |
154 } | |
155 |