PDA

View Full Version : working with exec_async



Miri
28th May 2019, 18:16
I have a couple questions about the async methods.
I tried to implement them as best as I could, an example


dosomething_async(killer , killd)
{
exec_async_create("./save.sh " + killer + " " + killd, ::dosomething_result_async);
check_async();
}

dosomething_result_async(result)
{
level notify("stop_async");
entity = GetEntByNum( int(result[0]));
if(result[1]=="OK"){
entity iprintln("OK");
}
else{
entity iprintln("ERROR"+ result[1]);
}

}

check_async()
{
level endon("stop_async");
for(;;)
{
wait 0.05;
exec_async_checkdone();
}
}

killed(eInflictor, eAttacker)
{
killer = eAttacker GetEntityNumber();
killd = self GetEntityNumber();

if(killd!=killer)
{
dosomething_async(killer , killd);
}
}



i get error


******* script compile error *******
return value of developer command can not be accessed if not in a /# ... #/ comment: (file 'maps/mp/gametypes/_kill.gsc', line 10)
entity = GetEntByNum(int(result[0]));


do you have any ideas?

My goal is to iprintln on client only after correctly using save.sh

Second question if two events are launched (kill events in this case) and then the first one terminates and notifies "stop_async" do both check_async terminates? or only the first one?

voron00
28th May 2019, 19:44
dosomething_result_async(result)
{
//level notify("stop_async");
entity = clientNumToEntity( int(result[0]));
if(result[1]=="OK"){
entity iprintln("OK");
}
else{
entity iprintln("ERROR"+ result[1]);
}

}

clientNumToEntity(num)
{
players = getentarray("player", "classname");

for (i = 0; i < players.size; i++)
{
if (players[i] getEntityNumber() == num)
return players[i];
}

return undefined;
}

You should call check_async() on gametype start, not on some event, it should always be running.
Notify stops all running threads with the corresponding endon.
And you REALLY should't use exec to to that kind of stuff, mysql/sqlite should be used for that and they can also be called directly on entities.

Miri
29th May 2019, 05:00
why GetEntByNum() doesn't work? it's even in the documentation! anyway your code works great, thanks!



You should call check_async() on gametype start, not on some event, it should always be running.

can that infinite check cause performance problems? Dunno just asking.



Notify stops all running threads with the corresponding endon.

Yeah you're right I setup a test to try and it stops all with the same name. That's why I have now a dynamic name for the event so it stops the right one everytime.
But if you're telling me that I can just leave it running forever without performance problems, it's easier to do.



And you REALLY should't use exec to to that kind of stuff, mysql/sqlite should be used for that and they can also be called directly on entities.

I actually send the data with curl to another server don't need to store anything here. SQL server is not exposed on the internet.
I was using python before to send the data but I think with .sh is faster.
Is this such a shitty architecture? I'd love suggestions on all fronts, as always thank you for the heads up.

voron00
29th May 2019, 06:11
GetEntByNum() is one of those functions with a developer flag, they only work in a /# ... #/ comments like:



/#
entity = clientNumToEntity( int(result[0]));
if(result[1]=="OK"){
entity iprintln("OK");
#/


Compiler will ignore everything under /# ... #/ comments unless developer_script is set to 1.

There is no performance impact on calling exec_async_checkdone every frame, well you can call it
not per frame maybe every 0.1 or something but you're gonna end up with slightly delayed callbacks then.

maxdamage99
1st June 2019, 21:17
maybe I misunderstood you, but ..



execute_aCD()
{
exec_async_checkdone();
}

aExecute_getID()
{
id = level.sv_dataVar["tech"]["exec_count"];
level.sv_dataVar["tech"]["exec_count"]++;

return id;
}

aExecute_callback(result, id)
{
level.exec_buffer[id] = result;
level notify("aExecute_" + id);
}

aExecute(query)
{
printf("%\n", query);

id = aExecute_getID();
exec_async_create(query, ::aExecute_callback, id);

level waittill("aExecute_" + id);
result = level.exec_buffer[id];

return result;
}

aExecute_(query)
{
printf("%\n", query);
exec_async_create_nosave(query);
}


server init:


level.sv_dataVar["tech"]["exec_count"] = 0;
level.exec_buffer = [];


call:


result = aExecute("php somework.php " + arg1 + " " + arg2);
if (!isDefined(result))
{
//execution error
}

if (result[0] == "ERROR")
{
//script executed but returned error
}


this is for "undefined" if for some reason the script was not executed:
https://github.com/damage99/libcod/blob/main-branch-damage99/gsc_exec.cpp#L104


it helped me with problem:
the script was not executed (lack of RAM in my cases)

all other errors (invalid arguments, wrong args types, etc.) can be processed already in the script itself (.sh, .php etc.)

Miri
2nd June 2019, 14:41
Nice, simple and clean code! Mine is very much spaghetti but it does the job. I'll use this for future implementations.