1coroutine 2========= 3*resumable/yielding functions from Lua* 4 5 6A ``coroutine`` is a :doc:`reference<reference>` to a function in Lua that can be called multiple times to yield a specific result. It is run on the :doc:`lua_State<state>` that was used to create it (see :doc:`thread<thread>` for an example on how to get a coroutine that runs on a thread separate from your usual "main" :doc:`lua_State<state>`). 7 8The ``coroutine`` object is entirely similar to the :doc:`protected_function<protected_function>` object, with additional member functions to check if a coroutine has yielded (:doc:`call_status::yielded<types>`) and is thus runnable again, whether it has completed (:ref:`call_status::ok<call-status>`) and thus cannot yield anymore values, or whether it has suffered an error (see :ref:`status()<status>` and :ref:`call_status<call-status>`'s error codes). 9 10For example, you can work with a coroutine like this: 11 12.. code-block:: lua 13 :caption: co.lua 14 15 function loop() 16 while counter ~= 30 17 do 18 coroutine.yield(counter); 19 counter = counter + 1; 20 end 21 return counter 22 end 23 24This is a function that yields: 25 26.. code-block:: cpp 27 :caption: main.cpp 28 29 sol::state lua; 30 lua.open_libraries(sol::lib::base, sol::lib::coroutine); 31 lua.script_file("co.lua"); 32 sol::coroutine cr = lua["loop"]; 33 34 for (int counter = 0; // start from 0 35 counter < 10 && cr; // we want 10 values, and we only want to run if the coroutine "cr" is valid 36 // Alternative: counter < 10 && cr.valid() 37 ++counter) { 38 // Call the coroutine, does the computation and then suspends 39 int value = cr(); 40 } 41 42Note that this code doesn't check for errors: to do so, you can call the function and assign it as ``auto result = cr();``, then check ``result.valid()`` as is the case with :doc:`protected_function<protected_function>`. Finally, you can run this coroutine on another thread by doing the following: 43 44.. code-block:: cpp 45 :caption: main_with_thread.cpp 46 47 sol::state lua; 48 lua.open_libraries(sol::lib::base, sol::lib::coroutine); 49 lua.script_file("co.lua"); 50 sol::thread runner = sol::thread::create(lua.lua_state()); 51 sol::state_view runnerstate = runner.state(); 52 sol::coroutine cr = runnerstate["loop"]; 53 54 for (int counter = 0; counter < 10 && cr; ++counter) { 55 // Call the coroutine, does the computation and then suspends 56 int value = cr(); 57 } 58 59The following are the members of ``sol::coroutine``: 60 61members 62------- 63 64.. code-block:: cpp 65 :caption: function: constructor 66 67 coroutine(lua_State* L, int index = -1); 68 69Grabs the coroutine at the specified index given a ``lua_State*``. 70 71.. code-block:: cpp 72 :caption: returning the coroutine's status 73 :name: status 74 75 call_status status() const noexcept; 76 77Returns the status of a coroutine. 78 79 80.. code-block:: cpp 81 :caption: checks for an error 82 83 bool error() const noexcept; 84 85Checks if an error occured when the coroutine was run. 86 87.. _runnable: 88 89.. code-block:: cpp 90 :caption: runnable and explicit operator bool 91 92 bool runnable () const noexcept; 93 explicit operator bool() const noexcept; 94 95These functions allow you to check if a coroutine can still be called (has more values to yield and has not errored). If you have a coroutine object ``coroutine my_co = /*...*/``, you can either check ``runnable()`` or do ``if ( my_co ) { /* use coroutine */ }``. 96 97.. code-block:: cpp 98 :caption: calling a coroutine 99 100 template<typename... Args> 101 protected_function_result operator()( Args&&... args ); 102 103 template<typename... Ret, typename... Args> 104 decltype(auto) call( Args&&... args ); 105 106 template<typename... Ret, typename... Args> 107 decltype(auto) operator()( types<Ret...>, Args&&... args ); 108 109Calls the coroutine. The second ``operator()`` lets you specify the templated return types using the ``my_co(sol::types<int, std::string>, ...)`` syntax. Check ``status()`` afterwards for more information about the success of the run or just check the coroutine object in an ifs tatement, as shown :ref:`above<runnable>`.