lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


> -----Original Message-----
> From: lua-l-bounces@lists.lua.org [mailto:lua-l-bounces@lists.lua.org] On
> Behalf Of Moose
> Sent: dinsdag 1 april 2014 15:12
> To: Lua mailing list
> Subject: RE: C++ integration / DSEL alternative questions
> 
> Hello Thijs,
> 
> thanks for your response. Let me add some thoughts...
> 
> Am 01.04.2014 12:23 schrieb Thijs Schreijer:
> >> 4) In a real world use case my users have many scripts in my DSEL
> >> that
> >> get executed at a frequency of about 30 Hz or more. Would I create a
> >> Lua
> >> state and execute the chunk every time or can I re-use the state
> >> after
> >> instantiating it once and excecute many times?
> >
> > You might have to cleanup some stuff left behind in between calls,
> > probably using some sandboxing that can be discarded.
> >
> > Generally two approaches;
> > 1) use a single state. In this case you can use coroutines to create
> > different environments (cooperative multithreading)
> > 2) use multiple states. Using OS threads (preemptive multithreading)
> 
> I think I can rule out 2). The user scripts have to be executed
> sequentially in one thread. Unfortunately, the underlying functions,
> that they all end up calling at some point, are single threaded. As in
> "They all have to be executed from within one specific thread". I cannot
> influence them and have to live with that.
> 
> > 1: might require protection from a script locking/hanging the
> > environment too long to keep it fluent. Will only utilize a single CPU
> > core. Easier to share global state between the different scripts. In a
> > multithreaded application synchronization happens before entering the
> > Lua state.
> 
> So, to me (as a complete Lua newbie) that would mean...
> 
> I now do this, straight forward:
> 
> 	lua_State *L = luaL_newstate();
> 	luaL_openlibs(L);
> 	luaopen_MyCppWrapper(L);
> 
> 	if (luaL_dofile(L, "lunawrapper.lua")) {
> 		std::cerr << "Lua program returned an error: \n";
> 		std::cerr << lua_tostring(L, -1);
> 		std::cerr << std::endl;
> 		lua_close(L);
>                // fail
> 	}
> 
> 	lua_gc(L, LUA_GCCOLLECT, 0);  // collected garbage
> 	lua_close(L);
> 
> could you post some hints on how this would be modified to reflect your
> comment? When I would like to execute the file (or memory chunk, as it
> would be in real world) again and again, ideally keeping local
> variables?

I don't know C++, nor very well the parts of the Lua api for creating the coroutines. But maybe this can help;
If you only run the same routine over and over again, then a single state can be used as the environment. The state might be updated to reflect some security elements (eg. Remove file access and/or debug library). No need to create independent environments/threads in this case.
If you run multiple routines, each requiring their own separate environment then basically do the following steps (this is what I probably would do, but alternative approaches are plentiful);
 - setup an environment (remove insecure elements)
 - load code with this environment
 - create a thread (coroutine) to run the code
 - resume the thread for each invocation
It would require the code to be setup to be run as a coroutine (or your code to wrap any user code as a coroutine)
The above can be repeated for each piece of code that should run in its own environment, whilst still having only 1 Lua state.

Regarding protecting a script from hogging the system (eg. Code like 'while true do end') you can setup debughooks. There was a discussion on the list quite recent, so check the archives. For the general concepts have a look at corowatch [1] (pure Lua module). Note: the recent discussion was about forcefully yielding to create a scheduler, where corowatch just kills a coroutine, so different approaches.

Maybe others can add or improve upon this, as I'm not an expert on the api side of doing this.

Hth

Thijs

[1] https://github.com/Tieske/corowatch