11
11
#include < functional>
12
12
#include < iterator>
13
13
14
+
14
15
// taken from extern/luau/VM/lcorolib.cpp
15
16
static const char * const statnames[] = {" running" , " suspended" , " normal" , " dead" , " dead" };
16
17
@@ -23,10 +24,10 @@ struct WaitData
23
24
uint64_t startedAtMs;
24
25
25
26
bool putDeltaTimeOnStack;
27
+ int nargs;
26
28
};
27
29
28
-
29
- static void yieldLuaStateFor (lua_State* L, uint64_t milliseconds, bool putDeltaTimeOnStack)
30
+ static void yieldLuaStateFor (lua_State* L, uint64_t milliseconds, bool putDeltaTimeOnStack, int nargs)
30
31
{
31
32
WaitData* yield = new WaitData ();
32
33
uv_timer_init (uv_default_loop (), &yield->uvTimer );
@@ -35,6 +36,7 @@ static void yieldLuaStateFor(lua_State* L, uint64_t milliseconds, bool putDeltaT
35
36
yield->startedAtMs = uv_now (uv_default_loop ());
36
37
yield->uvTimer .data = yield;
37
38
yield->putDeltaTimeOnStack = putDeltaTimeOnStack;
39
+ yield->nargs = nargs;
38
40
39
41
uv_timer_start (
40
42
&yield->uvTimer ,
@@ -45,8 +47,9 @@ static void yieldLuaStateFor(lua_State* L, uint64_t milliseconds, bool putDeltaT
45
47
yield->resumptionToken ->complete (
46
48
[yield](lua_State* L)
47
49
{
48
- int stackReturnAmount = yield->putDeltaTimeOnStack ? 1 : 0 ;
49
- if (stackReturnAmount)
50
+ int stackReturnAmount = yield->putDeltaTimeOnStack ? yield->nargs + 1 : yield->nargs ;
51
+
52
+ if (yield->putDeltaTimeOnStack )
50
53
lua_pushnumber (L, static_cast <double >(uv_now (uv_default_loop ()) - yield->startedAtMs ) / 1000.0 );
51
54
52
55
delete yield;
@@ -71,16 +74,80 @@ int lua_defer(lua_State* L)
71
74
return lua_yield (L, 0 );
72
75
};
73
76
77
+
78
+ int lua_delay (lua_State* L)
79
+ {
80
+ int type = lua_type (L, 1 );
81
+ uint64_t milliseconds = 0 ;
82
+
83
+ // Handle overloads
84
+ switch (type)
85
+ {
86
+ case LUA_TNUMBER:
87
+ milliseconds = static_cast <uint64_t >(lua_tonumber (L, 1 ) * 1000 );
88
+ break ;
89
+
90
+ case LUA_TUSERDATA:
91
+ {
92
+ double seconds = getSecondsFromTimespec (getTimespecFromDuration (L, 1 ));
93
+ milliseconds = static_cast <uint64_t >(seconds * 1000 );
94
+ break ;
95
+ }
96
+
97
+ default :
98
+ luaL_errorL (L, " invalid type %s passed into task.delay" , lua_typename (L, lua_type (L, 1 )));
99
+ break ;
100
+ };
101
+
102
+ // remove the wait time
103
+ lua_remove (L, 1 );
104
+
105
+ lua_State* passedLuaState;
106
+
107
+ if (lua_isfunction (L, 1 ))
108
+ {
109
+ lua_State* NL = lua_newthread (L);
110
+ lua_pop (L, 1 );
111
+
112
+ passedLuaState = NL;
113
+
114
+ // get the function
115
+ lua_xpush (L, NL, 1 );
116
+
117
+ // remove the function
118
+ lua_remove (L, 1 );
119
+ }
120
+ else if (lua_isthread (L, 1 ))
121
+ {
122
+ passedLuaState = lua_tothread (L, 1 );
123
+ lua_remove (L, 1 );
124
+ }
125
+ else
126
+ {
127
+ luaL_error (L, " can only pass threads or functions to task.spawn" );
128
+ };
129
+
130
+ int nargs = lua_gettop (L);
131
+ lua_xmove (L, passedLuaState, nargs);
132
+
133
+ yieldLuaStateFor (passedLuaState, milliseconds, false , nargs);
134
+
135
+ return 1 ;
136
+ }
137
+
74
138
int lua_spawn (lua_State* L)
75
139
{
76
140
if (lua_isfunction (L, 1 ))
77
141
{
78
142
lua_State* NL = lua_newthread (L);
79
143
144
+ // transfer arguments from other lua_State to the called lua_State
80
145
lua_xpush (L, NL, 1 );
81
146
147
+ // remove the function arg
82
148
lua_remove (L, 1 );
83
149
150
+ // insert the thread
84
151
lua_insert (L, 1 );
85
152
}
86
153
else if (!lua_isthread (L, 1 ))
@@ -89,6 +156,8 @@ int lua_spawn(lua_State* L)
89
156
}
90
157
91
158
lute_resume (L);
159
+
160
+ // return the thread
92
161
return 1 ;
93
162
}
94
163
@@ -116,7 +185,7 @@ int lua_wait(lua_State* L)
116
185
break ;
117
186
};
118
187
119
- yieldLuaStateFor (L, milliseconds, true );
188
+ yieldLuaStateFor (L, milliseconds, true , 0 );
120
189
121
190
return lua_yield (L, 0 );
122
191
}
0 commit comments