Lua yield allows waiting for threads in Lua?
#1
Just posting this here for future reference, I want to test some things with this.

http://stackoverflow.com/questions/72064...o-routines

As it is right now a web plugin (or any other plugins) can deadlock the server because they receive callbacks from multiple threads. When receiving a callback from one thread Lua has access to all MCServer's functions, but some code areas may be locked by another thread which is currently waiting for the Lua state to unlock.

I want to create a multi-threaded test case that uses lua_newthread, yielding and returning.

lua_newthread creates a "Lua thread" that shares global plugin data but has its own call stack. This still does not allow multiple threads to run a plugin at once, because of the shared global data. However it does allow a plugin to yield and stop execution in one thread while another thread can call whatever callback they want. When the callback is done executing (or any other requirements are met) the old thread can kick back in and resume execution where it left off.

An example of how I see this working:

function BlockChangedCallback()
	--blabla do something heavy that takes a long time making sure stuff is blocking and possibly deadlocking
end

function WebCallback()
	local BlockID = GetBlockIDYield(x, y, z)
end

List< Messages > m_MessageList; // In the case of Lua this should probably be a single message instead of a list, or at least linked with the Lua thread it belongs to

int LUA_GetBlockIDYield(int x, int y, int z)
{
	m_MessageList.push_back( new Runnable()
	{
		void Run()
		{
			cWorld::GetBlockID(x, y, z);
		}
	} );
    return lua_yield(L,0); // I _think_ this immediately returns LUA_YIELD in main()
}


int main() {
	lua_register(L, "GetBlockIDYield", LUA_GetBlockIDYield);

    lua_State* luaThread = lua_newthread(luaState);
    
	lua_getglobal(luaThread, "WebCallback");
	lua_resume(luaThread, 0); // Should execute WebCallback??

    while (running) {
        int status;
        status = lua_resume(cL,0);
        if (status == LUA_YIELD) {
			// Lua has returned, we should unlock the CriticalSection so other threads can run BlockChangedCallback()
			// Handle all messages here??
			foreach( message in m_MessageList )
			{
				message->Run();
			}
			// Somehow fill some variables in the Lua script with results from the messages
			// I think it should be possible to push some objects on the stack before calling lua_resume which results in returning the results directly into Lua
        } else {
            running=false; // It did not yield which means execution was completed (error or not is not relevant)
        }
    }
    return 0;
}

I haven't really thought this out, and the example is horribly incomplete and wrong.. but I'm tired I'll look at it later again.

Maybe you guys can look at this with a fresh non-fried brain and let me know whether this sounds reasonable.
Reply
Thanks given by:


Messages In This Thread
Lua yield allows waiting for threads in Lua? - by FakeTruth - 02-01-2013, 08:39 AM



Users browsing this thread: 4 Guest(s)