[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: RE: C++ integration / DSEL alternative questions
- From: Thijs Schreijer <thijs@...>
- Date: Fri, 4 Apr 2014 14:08:26 +0000
> -----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