Jump to content
Sign in to follow this  
sandbird

Function that returns after it was spawn called.

Recommended Posts

This i gonna sound weird....but i was wondering if its even possible to do this...i've been trying...believe me.

I'll simplify my code, cause its huge...but basically the algorithm is like this:

my fetchFnc.sqf has (gets included) :

fetch_data = {
 _name= _this select 0; 
 _fncName= _this select 1; 
        .....blah blah blah based on _name, and then....
        _number= 10;
 [_name, _number] spawn _fncName; 
};

I got this in my init.sqf:

#include "fetchFnc.sqf";

private ["_name","_number"];

my_function = { 
_name= _this select 0; 
_number= _this select 1; 
};
0 = [
      "George", 
my_function
     ] spawn fetch_data;

[b]diag_log format [ "After calculations: %1 has %2", _name, _number];[/b]

How can i update on my main init.sqf the values for _name and _number to be show in the diag_log ?

Cause right now as you can guess it doesnt get the values. I need to get the values outside of the function...I tried making them global variables....still no luck.

ps: Cant do "call fetch_data" cause inside there are waituntil functions. I dont mind the script to fail...for example something went wrong and there is no data for _name George...so i send out an error. I can handle that after in my main code. So if _name == "error" then do.....

-Thanks

Edited by Sandbird

Share this post


Link to post
Share on other sites

Either you wait until the spawned code has been executed or you define a callback to be called after.

// the waiting example
myFunction = {
_semaphore 		= _this select 0;  // a regular string for naming the semaphore
_otherparams 	= _this select 1;
// ....

// do something here

// release the semaphore
call compile format ["%1 = true;", _semaphore];
};

sem_mySem = false;
["sem_mySem", "param1", "param2"] spawn myFunction;
waitUntil {sem_mySem};

// the callback example
myFunction = {
_callback 		= _this select 0;
_otherparams 	= _this select 1;
// ....

// do something here

// release the semaphore
["your", "desired", "parameters"] spawn _callback;
};
_yourCallback = {
_your 		= _this select 0;
_desired	= _this select 1;
_paramseters= _this select 2;

// do something here
};

[_yourCallback, "param1", "param2"] spawn myFunction;

Imho I'd take the callback one, I like that method a lot because you can define a common interface for the callback and stuff like that, which works better programatically.

Share this post


Link to post
Share on other sites

I am sorry if this is a noob question...but how is that returning values to me ?

I cant call it....wish i could but i cant cause it has waituntils inside...

In a nutshell (i wish) i could do it like this:

_key = format["%1:",_myValueHere];
_primary = _key call fetch_data;
........
_medical = _primary select 1;
_stats =    _primary select 2;
_state =    _primary select 3;

this is taken from my server.pbo...just trying to make it easy to understand.

Right now i have:

0 = [
      "George", 
my_function
     ] spawn fetch_data;

meaning i cant have this result (whatever it may be) returned in a value, that then i can do _primary select 1;_primary select 2; etc

I cant say

_key = [
      "George", 
my_function
     ] spawn fetch_data;

I need to continue coding from where i was before the spawn fetch_data...by doing this:

_yourCallback = {
   _your         = _this select 0;
   _desired    = _this select 1;
   _paramseters= _this select 2;

   // do something here
};

isnt it still 'blocking' _your _desired _parameters to come out of the function so i can use them further down ?

(Again, sorry if this is a noob question...I am good with PHP, arma language is such a pain....

Share this post


Link to post
Share on other sites

Haha okay knowing PHP won't get you anywhere in ArmaScript ^^

The thing is - whener you spawn a function, you won't get a return value. Ever!

Or let me rephrase that: You'll get a return value, like any other function does, but because your code after the spawn is being executed at the "same" time, you can't assign the return value to a (any) variable.

If you even use one spawn in your code, you have to be clear on the consequences: if you want a return value from a spawned function, you have to wait after the spawn or put the code after the spawn into another function and call it in your spawned function.

So you have to either forcibly wait until the spawned code has been executed and save the desired return values into a global variable so you can access them outta your function, or call another function after you're done.

Because you didn't get my examples, I'll post some more detailed ones :)

// Waiting for the spawned code

fetch_data = {
   _key = _this;

   // do something here

   // put the results into the global array
   primary_data = [1, 2, 3, 4];
};

primary_data = [];

_key = format["%1:",_myValueHere];
_fetch_data_handler = _key spawn fetch_data;
waitUntil {scriptDone _fetch_data_handler};

_medical = primary_data select 1;
_stats =    primary_data select 2;
_state =    primary_data select 3; 

// using a callback

fetch_data = {
   _callback = _this select 1;
   _key       = _this select 0;

   // do something here
   _primary_data = [1, 2, 3, 4];

   // at the end, spawn the callback
   _primary_data spawn _callback;    
};

yourOtherCode = {
   _primary_data = _this;

   _medical = _primary_data select 1;
   _stats =    _primary_data select 2;
   _state =    _primary_data select 3; 
};

_key = format["%1:",_myValueHere];
_fetch_data_handler = [_key, yourOtherCode] spawn fetch_data;

I hope this explains it more to you. The callback-method looks rather discomfortable at the first sight, but when did right, it is more flexible.

But if you don't want to change much in your code, you should opt for the waitUntil-method.

However, if you're code to process the return-value of fetch_data is being called rather than spawned or execVM'ed, you can't use the waitUntil-method due to the same regulations about synchronous functions.

Edited by XxAnimusxX

Share this post


Link to post
Share on other sites

Oh snap, yeah i didnt think of that, the code is called...i have to go with the callback function then.

I really appreciate you taking the time to write this. Its like watch the movie Pi...lol my brain just hurt a bit.

But i'll digest it slowly :)

One last question before i start experimenting..so i am sure of the results.

In case it does take its time to return results...and since i will include ALL this inside a while function that sleeps for 5 sec at the end of it...will the _fetch_data_handler show the data eventually or not ?

To be specific, this code will go to a custom debug monitor. Besides the data that its gonna be shown there, at the bottom i want to bring some specific information about the player.

The rest of the debug values will always show, since their code is pretty basic and easy to do...At the bottom of this, i'll 'try' and show the results from _fetch_data_handler.

If they are delayed a bit (like 1/3 of a second) will they eventually popup or it will skip them all together since 'their time has passed'. They should show right ? since the whole thing is spawning the code.

Share this post


Link to post
Share on other sites

Well that depends solely on your implementation :D

Let us assume that fetch_data does nothing "heavy" and has no delays like sleeps in it, then spawning fetch_data will almost instantaneously spawn "yourOtherCode", so you won't have any major delays between that.

But if you have a loop which shows constant informations with a fixed delay between every iteration, you're gonna be at a loss because "yourOtherCode" will be executed in the "same" time like your loop, so using the callback-method you have to think about other ways of synchronization (which is kind of difficult without mutexes/semaphores) because while you continue to execute the code in your loop, which finally shows something on the screen, "yourOtherCode" is executed without any means to control what is shown due to your loop.

The usual approach is to define a global variable and use that in the output (concatenating), while feeding the global variable in your fetch_data-function. But this approach calls for pretty minor delays between each iteration because the spawned code eventually will take some milliseconds longer than the execution of the loop, so it's thinkable that your "special" output will lag behind for several milliseconds. So using a delay of five seconds between each loop iteration would cause some weird problems.

But to sum this up: Are you really calling the code which has the loop in it? Isn't it eventually executed via execVM?

Because if you call a script/function and have a loop in it, that loop will only last for a max. of 10000 iterations and skip the loop afterwards.

Please be advised that you can't show the informations you want to output for a long time if that's the case.

Imho you should execVM the script which holds the loop and use the waitUntil-method which is clearly more easy to implement and understand AND has the benefit that you don't have to synchronize anything :)

Share this post


Link to post
Share on other sites

I have to further test this during the weekend :)

Thanks Animus!

Edited by Sandbird

Share this post


Link to post
Share on other sites

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
Sign in to follow this  

×