@@ -892,6 +892,66 @@ l_sleep(lua_State *L) {
892892 return lua_yield (L , 0 );
893893}
894894
895+ static int
896+ l_spawn (lua_State * L ) {
897+ static constexpr int IDX_FUNC = 1 ;
898+
899+ // Prologue
900+ struct config_vm * vm = config_vm_from (L );
901+ struct wrap * wrap = config_vm_get_wrap (vm );
902+ if (!wrap ) {
903+ return luaL_error (L , STARTUP_ERRMSG ("sleep" ));
904+ }
905+
906+ if (lua_type (L , IDX_FUNC ) != LUA_TFUNCTION ) {
907+ return luaL_error (L , "expected a function, got '%s'" , luaL_typename (L , IDX_FUNC ));
908+ }
909+
910+ size_t argc = lua_gettop (L ) - IDX_FUNC ;
911+
912+ lua_State * coro = lua_newthread (vm -> L ); // stack: argc + 2
913+ config_vm_coro_add (coro , nullptr );
914+
915+ // The function and its arguments need to be moved to the coroutine's stack, but we need to keep
916+ // a reference to the newly created coroutine on the stack of the caller so that the coroutine
917+ // is not immediately garbage collected in the event of an error.
918+ lua_pop (L , 1 ); // stack: argc + 1
919+ lua_xmove (L , coro , argc + 1 ); // stack: 0 (coroutine: argc + 1)
920+ lua_pushthread (coro ); // stack: 0 (coroutine: argc + 2)
921+ lua_xmove (coro , L , 1 ); // stack: 1 (coroutine: argc + 1)
922+
923+ int ret = lua_resume (coro , argc );
924+
925+ switch (ret ) {
926+ case LUA_YIELD :
927+ // There needs to be a waker associated with the coroutine or else it will never be
928+ // resumed.
929+ if (config_vm_coro_get (coro )) {
930+ return 0 ;
931+ }
932+
933+ config_vm_coro_del (coro );
934+ return luaL_error (L , "invalid yield from coroutine" );
935+ case 0 :
936+ // The coroutine finished immediately without yielding, so it can be deleted from the
937+ // coroutine table.
938+ config_vm_coro_del (coro );
939+ break ;
940+ default :
941+ // An error occurred. The spawned coroutine is still on the stack of the coroutine which
942+ // called spawn so the error message will not get garbage collected.
943+
944+ config_vm_coro_del (coro );
945+ if (lua_type (coro , -1 ) == LUA_TSTRING ) {
946+ return luaL_error (L , lua_tostring (coro , -1 ));
947+ } else {
948+ return luaL_error (L , "unknown (%d): %s" , ret , lua_tostring (coro , -1 ));
949+ }
950+ }
951+
952+ return 0 ;
953+ }
954+
895955static int
896956l_state (lua_State * L ) {
897957 static constexpr int IDX_STATE = 1 ;
@@ -1215,6 +1275,7 @@ static const struct luaL_Reg lua_lib[] = {
12151275 {"log_error" , l_log_error },
12161276 {"register" , l_register },
12171277 {"setenv" , l_setenv },
1278+ {"spawn" , l_spawn },
12181279 {nullptr , nullptr },
12191280};
12201281
0 commit comments