source: trunk/src/lua/lcorolib.c @ 2542

Last change on this file since 2542 was 2542, checked in by sam, 10 years ago

lua: compilation fixes for non-quite-POSIX platforms.

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