# sol2 3.5.0 documentation

## threading

### Search the Documentation

# threading

Lua has no thread safety. sol does not force thread safety bottlenecks anywhere. Treat access and object handling like you were dealing with a raw `int` reference (`int&`) (no safety or order guarantees whatsoever).

Assume any access or any call on Lua affects the whole `sol::state`/`lua_State*` (because it does, in a fair bit of cases). Therefore, every call to a state should be blocked off in C++ with some kind of access control (when you’re working with multiple C++ threads). When you start hitting the same state from multiple threads, race conditions (data or instruction) can happen.

To handle multithreaded environments, it is encouraged to either spawn a Lua state (`sol::state`) for each thread you are working with and keep inter-state communication to synchronized serialization points. This means that 3 C++ threads should have 3 Lua states, and access between them should be controlled using some kind of synchronized C++ mechanism (actual transfer between states must be done by serializing the value into C++ and then re-pushing it into the other state).

Here is an example of a processor that explicitly serializes Lua returns into C++ values, and Lua functions into state-transferrable byte code to do work.

Using coroutines and Lua’s threads might also buy you some concurrency and parallelism (unconfirmed and likely untrue, do not gamble on this), but remember that Lua’s ‘threading’ technique is ultimately cooperative and requires explicit yielding and resuming (simplified as function calls for sol::coroutine).

## getting the main thread

Lua 5.1 does not keep a reference to the main thread, therefore the user has to store it themselves. If you create a `sol::state` or follow the steps for opening up compatibility and default handlers here, you can work with `sol::main_thread` to retrieve you the main thread, given a `lua_State*` that is either a full state or a thread: `lua_state* Lmain = sol::main_thread( Lcoroutine )`; This function will always work in Lua 5.2 and above: in Lua 5.1, if you do not follow the `sol::state` instructions and do not pass a fallback `lua_State*` to the function, this function may not work properly and return `nullptr`.

## working with multiple Lua threads

You can mitigate some of the pressure of using coroutines and threading by using the `lua_xmove` constructors that sol implements. Simply keep a reference to your `sol::state_view` or `sol::state` or the target `lua_State*` pointer, and pass it into the constructor along with the object you want to copy. Note that there is also some implicit `lua_xmove` checks that are done for copy and move assignment operators as well, as noted at the reference constructor explanations.

Note

Advanced: For every single `sol::reference` derived type, there exists a version prefixed with the word `main_`, such as `sol::main_table`, `sol::main_function`, `sol::main_object` and similar. These classes, on construction, assignment and other operations, forcibly obtain the `lua_State*` associated with the main thread, if possible. Using these classes will allow your code to be immune when a wrapped coroutine or a lua thread is set to `nil` and then garbage-collected.

Note

This does not provide immunity from typical multithreading issues in C++, such as synchronized access and the like. Lua’s coroutines are cooperative in nature and concurrent execution with things like `std::thread` and similar still need to follow good C++ practices for multi threading.

Here’s an example of explicit state transferring below:

     1#define SOL_ALL_SAFETIES_ON 1
     2
     3#include <sol/sol.hpp>
     4
     5#include <iostream>
     6
     7int main(int, char*[]) {
     8
     9	sol::state lua;
    10	lua.open_libraries();
    11	sol::function transferred_into;
    12	lua["f"] = [&lua, &transferred_into](
    13	                sol::object t, sol::this_state this_L) {
    14		std::cout << "state of main     : "
    15		          << (void*)lua.lua_state() << std::endl;
    16		std::cout << "state of function : "
    17		          << (void*)this_L.lua_state() << std::endl;
    18		// pass original lua_State* (or
    19		// sol::state/sol::state_view) transfers ownership from
    20		// the state of "t", to the "lua" sol::state
    21		transferred_into = sol::function(lua, t);
    22	};
    23
    24	lua.script(R"(
    25	i = 0
    26	function test()
    27	co = coroutine.create(
    28		function()
    29			local g = function() i = i + 1 end
    30			f(g)
    31			g = nil
    32			collectgarbage()
    33		end
    34	)
    35	coroutine.resume(co)
    36	co = nil
    37	collectgarbage()
    38	end
    39	)");
    40
    41	// give it a try
    42	lua.safe_script("test()");
    43	// should call 'g' from main thread, increment i by 1
    44	transferred_into();
    45	// check
    46	int i = lua["i"];
    47	SOL_ASSERT(i == 1);
    48
    49	return 0;
    50}