I was wondering whether the following setup would work for a small game:
Lets assume I have the following functions registered to Lua like so:
lua_register(L, "createTimer", createTimer);
lua_register(L, "getCondition", getCondition);
lua_register(L, "setAction", setAction);
Where: (leaving the type checking behind)
int createTimer(lua_State* L){
string condition = lua_tostring(L, 1);
string action = lua_tostring(L, 2);
double timer = lua_tonumber(L, 3);
double expiration = lua_tonumber(L, 4);
addTimer(condition, action, timer, expiration); // adds the "timer" to a vector or something
return 1;
}
Calling this function in lua by:
createTimer("getCondition=<5", "setAction(7,4,6)", 5, 20);
Can I then do the following(?):
// this function is called in the game-loop to loop through all timers in the vector
void checkTimers(){
for(std::vector<T>::iterator it = v.begin(); it != v.end(); ++it) {
if(luaL_doString(L, *it->condition)){
luaL_doString(L, *it->action)
}
}
}
Would this work? Would luaL_doString pass "getCondition=<5" to the lua state engine, where it will call the c++ function getCondition(), then see if it is =<5 and return true or false? And would the same go for luaL_doString(L, "setAction(7, 4, 6)"); ?
Moreover, would this be a suitable way to create timers by only accessing lua once (to create them) and let c++ handle the rest, only calling the c++ functions through lua and letting lua deal with logic only?
Thanks in advance.
You may want to change the condition string to "return getCondition()<=5" otherwise the string chunk will not compile or run. Then check the boolean return value on the stack when the luaL_doString() returns successfully. Something like this:
// this function is called in the game-loop to loop through all timers in the vector
void checkTimers(){
for(std::vector<T>::iterator it = v.begin(); it != v.end(); ++it) {
lua_settop(L, 0);
if(luaL_doString(L, *it->condition) == 0 && lua_toboolean(1)){
luaL_doString(L, *it->action);
}
}
}
You cannot interrupt Lua while it is running. The best you can do is to set a flag and then handle the interruption at a safe time. The standalone interpreter uses this technique to handle user interrupts (control-C). This technique is also used in my lalarm library, which can be used to implement timer callbacks, though not at the high level you want.
Related
I'm trying to add the LUA API to my C++ program, and I'm attempting to allow the script to draw to my GUI. So far, I have this for my lambda function:
auto addToDrawList = [](lua_State* L) -> int
{
int DrawType = (int)lua_tonumber(L, -2);
std::string Label = (std::string)lua_tostring(L, -1);
bool found = false;
for (int i = 0; i <= DrawList.size(); i++)
{
if (DrawList[i].Active == false && !found)
{
switch (DrawType)
{
case(0):
break;
case(1):
DrawList[i].Active = true;
DrawList[i].DrawType = Type::TextBox;
DrawList[i].Label = Label;
break;
}
found = true;
}
}
return 0;
};
This as my LUA script being run:
const char* LUA_FILE = R"(
addToDrawList(1, "Test")
)";
This is how I'm pushing my function to the LUA stack:
lua_State* L = luaL_newstate();
lua_newtable(L);
int uiTableInd = lua_gettop(L);
lua_pushvalue(L, uiTableInd);
lua_setglobal(L, "Ui");
lua_pushcfunction(L, addToDrawList);
lua_setfield(L, -2, "addToDrawList");
The problem is within my first script, as it can't get to the 'DrawList' array as its inside of this.
So, to resolve it, I tried to add this to the lambda's capture list by doing this:
auto addToDrawList = [this](lua_State* L) -> int
Which appeared to work and resolve the error, but then I had an issue with the last script:
lua_pushcfunction(L, addToDrawList);
I've been searching the Internet for a fix, but I can't find any.
lua_pushcfunction() takes a C-style function pointer. A capture-less lambda can be converted to such a function pointer, but a capturing lambda cannot.
Use lua_pushcclosure()1 instead. It will allow you to associate user-defined values (known as upvalues) with the C function, such as your this pointer, or just a pointer to DrawList, etc.
When a C function is created, it is possible to associate some values with it, thus creating a C closure (see ยง3.4); these values are then accessible to the function whenever it is called. To associate values with a C function, first these values should be pushed onto the stack (when there are multiple values, the first value is pushed first). Then lua_pushcclosure is called to create and push the C function onto the stack, with the argument n telling how many values should be associated with the function. lua_pushcclosure also pops these values from the stack.
1: lua_pushcfunction() is just a wrapper for lua_pushcclosure() with 0 upvalues defined.
For example:
auto addToDrawList = [](lua_State* L) -> int
{
const MyClassType *pThis = (const MyClassType*) lua_topointer(L, lua_upvalueindex(1));
// use pThis->DrawList as needed...
return 0;
};
...
lua_State* L = luaL_newstate();
...
//lua_pushcfunction(L, addToDrawList);
lua_pushlightuserdata(L, this);
lua_pushcclosure(L, addToDrawList, 1);
...
I can't find a grpc example showing how to use the ClientAsyncReaderWriter (is there one?). I tried something on my own, but am having trouble with the reference counts. My question comes from tracing through the code.
struct grpc_call has a member of type gpr_refcount called ext_ref. The ClientContext C++ object wraps the grpc_call, and holds onto it in a member grpc_call *call_;. Only when ext_ref is 0, can this grpc_call pointer be deleted.
When I use grpc synchronously with ClientReader:
In its implementation it uses CreateCall() and PerformOps() to add to ext_ref (ext_ref == 2).
Then I use Pluck() which subtracts from ext_ref so that (ext_ref == 1).
The last use ~ClientContext() subtracts from ext_ref, so that ext_ref == 0 and deletes the call
But when I use grpc asynchronously with ClientAsyncReaderWriter:
First use asyncXXX(), this API use CreateCall() and register Write() (ext_ref == 2).
Then it uses AsyncNext() to get tag...which must use a write or read operator.
So ext_ref > 1 forever, unless got_event you don't handle.
I'm calling it like this:
struct Notice
{
std::unique_ptr<
grpc::ClientAsyncReaderWriter<ObserveNoticRequest, EventNotice>
> _rw;
ClientContext _context;
EventNotice _rsp;
}
Register Thread
CompletionQueue *cq = new CompletionQueue;
Notice *notice = new Notice;
notice->rw = stub->AsyncobserverNotice(&context, cq, notice);
// here context.call_.ext_ref is 2
Get CompletionQueue Event Thread
void *tag = NULL;
bool ok = false;
CompletionQueue::NextStatus got = CompletionQueue::NextStatus::TIMEOUT;
gpr_timespec deadline;
deadline.clock_type = GPR_TIMESPAN;
deadline.tv_sec = 0;
deadline.tv_nsec = 10000000;
got = cq->AsyncNext<gpr_timespec>(&tag, &ok, deadline);
if (GOT_EVENT == got) {
if (tag != NULL) {
Notice *notice = (Notice *)tag;
notice->_rw->Read(&_rsp, notice);
// here context.call_.ext_ref is 2.
// now I want to stop this CompletionQueue.
delete notice;
// use ~ClientContext(), ext_ref change to 1
// but only ext_ref == 0, call_ be deleted
}
}
Take a look at this file, client_async.cc, for good use of the ClientAsyncReaderWriter. If you still have confusion, please create a very clean reproduction of the issue, and we will look into it further.
I've stumbled into something very peculiar - I'm writing an LLVM module Pass. I iterate over all functions of the module and then all loops of every non-declaration function and I store pointers to loops in a std::vector. Here's the source:
virtual bool runOnModule(Module& Mod){
std::vector<Loop*> loops;
// first gather all loop info
for(Module::iterator f = Mod.begin(), fend = Mod.end(); f != fend; ++f){
if (!(*f).isDeclaration()){
LoopInfo& LI = getAnalysis<LoopInfo>(*f);
for(LoopInfo::iterator l = LI.begin(), lend = LI.end(); l != lend; ++l){
loops.push_back(*l);
}
}
}
for (auto& l: loops) errs () << *l << " ";
}
Now if I run this I get a runtime error - it can't print the loops, somehow I'm doing a null pointer dereference or sth. Any ideas?
You have to make sure that the LoopInfo pass actually runs before your pass. Here is a complete example - stanalone from opt:
class AnalyzeLoops : public FunctionPass {
public:
AnalyzeLoops()
: FunctionPass(ID) {}
void getAnalysisUsage(AnalysisUsage &AU) const {
AU.addRequired<LoopInfo>();
}
virtual bool runOnFunction(Function &F) {
LoopInfo &LI = getAnalysis<LoopInfo>();
for (LoopInfo::iterator L = LI.begin(), LE = LI.end(); L != LE; ++L) {
(*L)->dump();
}
return false;
}
static char ID;
};
In addition, when creating the passes, do:
PassManager PM;
PM.add(new LoopInfo());
PM.add(new AnalyzeLoops());
PM.run(*Mod);
I suspect that to make opt actually run LoopInfo before your pass, you should pass -loops too.
Also, note that I define getAnalysisUsage - this will make LLVM complain if LoopInfo didn't run before this pass, making the problem more obvious.
Note that LoopInfo is specifically a FunctionPass, and as an analysis it has to be used from another FunctionPass. The LoopInfo data structure doesn't really survive between different functions, and since it owns its data (those Loop* objects) they will be destroyed as well.
One thing you could do if you really need a ModulePass is just invoke LoopInfo manually and not as an analysis. When you iterate the functions in the module, for each function create a new LoopInfo object and use its runOnFunction method. Though even in this case, you have to make sure the LoopInfo that owns a given Loop* survives if you want to use the latter.
First of all LoopInfo should run just once before the for loop.
Secondly LoopInfo::iterator just includes top level loops of the Function. in order to visit all loops you also need to iterate over subloops of every loop. it can be implemented either as recursive function or by WorkList, like this`
virtual bool runOnFunction(Function &F) {
LoopInfo *loopinfo;
loopinfo = &getAnalysis<LoopInfo>();
std::vector<Loop*> allLoops;
for (LoopInfo::iterator Li = loopinfo->begin(), Le = loopinfo->end();
Li != Le; Li++) {
Loop *L = *Li;
allLoops.push_back(L);
dfsOnLoops(L, loopinfo, allLoops);
}
}
void dfsOnLoops(Loop *L, LoopInfo *loopinfo, std::vector<Loop*> LoopS) {
std::vector<Loop *> subloops = L->getSubLoops();
if (subloops.size()) {
// recursive on subloops
for (std::vector<Loop *>::iterator Li = subloops.begin();Li != subloops.end(); Li++){
LoopS.push_back(*Li);
dfsOnLoops(*Li, loopinfo, LoopS);
}
}
}
`
None of the answers really helped but I managed to solve the problem myself. Basically, each llvm pass can define a releaseMemory() method, read more here. The LoopInfo class had that method implemented and thus the analysis information would be lost every time we get out of scope from the call to getAnalysis. I simply removed the releaseMemory() method in Loopinfo.h and the memory was no longer released. Note that this triggered a big change in the codebase and even opt had to be rebuilt so doing this in general is probably a bad idea and this would definitely not be easily accepted as a change to llvm (I speculate, not sure).
I think the best way to solve this is to explicitly create LoopInfo objects and save them. Here is the Code for LLVM 3.5
using LoopInfoType=llvm::LoopInfoBase<llvm::BasicBlock, llvm::Loop>;
std::vector<llvm::Loop*> loopVec;
std::vector<LoopInfoType*> loopInfoVec;
for(llvm::Module::iterator F = M.begin(); F!= M.end(); F++){
//skip declrations
if(F->isDeclaration()){
continue;
}
//TODO that scope problem
llvm::DominatorTree DT = llvm::DominatorTree();
DT.recalculate(*F);
LoopInfoType *loopInfo = new LoopInfoType();
loopInfo->releaseMemory();
loopInfo->Analyze(DT);
loopInfoVec.push_back(loopInfo);
for(llvm::LoopInfo::iterator lit = loopInfo->begin(); lit != loopInfo->end(); lit++){
Loop * L = * lit;
loopVec.push_back(L);
//L->dump();
}
}//for all functions
cin.get();
for(auto loop : loopVec){
std::cout << "loop\n";
loop->dump();
for(llvm::Loop::block_iterator bit = loop->block_begin(); bit != loop->block_end(); bit++){
llvm::BasicBlock * B = * bit;
B->dump();
std::cout << "\n\n";
}
}
In Lua I have a function called utils.debug() and what I would like to do is use it in my Lua code as follows:
function Foo:doSomething
if (/* something */) then
print("Success!")
else
utils.debug()
end
end
function Foo:doSomethingElse
if (/* something else */) then
print("Awesome!")
else
utils.debug()
end
end
I would like to use it throughout my Lua code to help me debug. As a result, I would like my C++ code to know where in the Lua code the utils.debug() was called from. I looked into lua_Debug and lua_getinfo and they seem pretty close to what I want, but I'm missing a piece:
int MyLua::debug(lua_State* L)
{
lua_Debug ar;
lua_getstack(L, 1, &ar);
lua_getinfo(L, ??????, &ar);
// print out relevant info from 'ar'
// such as in what function it was called, line number, etc
}
Is this what the lua_Debug struct is for or is there another facility or method I should use to do this?
This is what I use to produce a Lua stack trace:
lua_Debug info;
int level = 0;
while (lua_getstack(l, level, &info)) {
lua_getinfo(l, "nSl", &info);
fprintf(stderr, " [%d] %s:%d -- %s [%s]\n",
level, info.short_src, info.currentline,
(info.name ? info.name : "<unknown>"), info.what);
++level;
}
See the documentation for lua_getinfo for more info.
I am trying to call the "Run" function in a new thread. Right now, I have this code using openMP that doesn't actually run "Run" in a new thread. NOTE: I am not asking for help using OpenMP. This code was just a quick fix. I would prefer a CreateThread() method of going about this.
vector<ICommand*>* commands;
string strInput;
// For each command...
for(vector<ICommand*>::iterator i = commands->begin(); i != commands->end(); ++i)
{
// ...if the current command we're examining is valid...
if((*i)->ContainsCommand(strInput))
{
// ...run it in a new thread and don't let ZChatInput handle it normally...
#pragma omp sections nowait
{
#pragma omp section
(*i)->Run(strInput);
#pragma omp section
bRet = false;
}
// ...and don't check any more commands.
break;
}
}
So how would this be done using just standard and STL? Of course, I'm looking for a way that works :)
How about using Boost.Thread?
if((*i)->ContainsCommand(strInput))
{
boost::thread t( boost::bind( &ICommand::Run, *i ) );
}
This will run "Run" in a detached thread.
(Note, I did not test this.)
like this? http://msdn.microsoft.com/en-us/library/kdzttdcb(VS.80).aspx
You can try something like this:
vector<ICommand*>* commands;
string strInput;
void CommandOnThread(void* command)
{
(ICommand*)command->Run();
}
// For each command...
for(vector<ICommand*>::iterator i = commands->begin(); i != commands->end(); ++i)
{
// ...if the current command we're examining is valid...
if((*i)->ContainsCommand(strInput))
{
//Attach the input to the command
(*i)->AttachInput(strInput);
_beginthread(CommandOnThread, 0, *i);
break;
}
}
For this you have to change the command interface a little for passing the command input in two steps: first store the input in the command object and then call Run() without arguments. You can replace _beginthread with CreateThread if you like they are quite similar.
Just to clarify: You can't use an instance method as the function parameter for _beginthread (or CreateThread). The solution above is to pass the object (command) to the function and then call its instance method (Run). However in that case you can't pass extra arguments to the thread function, and therefore can't pass arguments to the instance method. The easiest solution for this is to somehow attach the argument to the instance before passing it to the thread function.
I hope this helps. Of course this solution is not possible if you can't change the interface and implementation of the Command class.
Do you really want to create a thread for each command? Thread creation is expensive.
If you absolutely need this part to be asynchronous - create a synchronized queue, pre-spawn number of threads (that's your scalability here,) have them block on the queue, then put a message (pointer?) onto the queue in your loop.
Answering your comment:
// setup
sync_queue wq; // that would be protected by mutex and a conditional var or two
for ( i = 0; i < parallel_factor; ++i ) start_thread( th_func, wq );
...
// your loop body :
...
if ( valid_input ) q.put( item );
...
// thread function
void th_func( sync_queue& q )
{
work_item* pwi;
while (( pwi = q.get())) do_it( pwi );
}
Makes sense?
So I figured it out after double-checking the MSDN documentation. Here's how I did it, in case any of you are interested:
static vector<ICommand*>* commands;
// This is what we pass to CommandOnThread.
struct CommandParameter
{
string strInput;
ICommand* command;
};
int CommandOnThread(CommandParameter* cp)
{
cp->command->Run(cp->strInput);
delete cp;
return 0;
}
void foo()
{
string strInput;
...
// For each command...
for(vector<ICommand*>::iterator i = commands->begin(); i != commands->end(); ++i)
{
// ...if the current command we're examining is valid...
if((*i)->ContainsCommand(strInput))
{
// Put the CP on the stack.
CommandParameter* temp = new CommandParameter;
if(temp == NULL)
{
Print("Out of memory!");
bRet = false;
break;
}
// ...set up the parameters to createthread...
temp->strInput = strInput;
temp->command = *i;
// ...run it in a new thread...
CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)CommandOnThread, temp, NULL, NULL);
// ...and don't check any more commands.
bRet = false;
break;
}
}
}