Hello! I have started using AS and it's been a blast. The best scripting language I have used hands down.
But now I have hit a hurdle. I'm making a block based system - you take many blocks and link them all together. Every block is programmed in AS and threaded. Now the question is which parts I can thread? The doc's says the engine is totally thread safe if I only use one. Couldn't see anything specific about contexts or modules. Recent commits seems to have put locks on modules though (haven't tested the WIP version), which seems to me that it wasn't thread safe. I have tried this:
//This is done once
asPrepareMultithread();
asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
//Then in each thread:
asIScriptContext *ctx = engine->CreateContext();
string code;
as::LoadScriptFile(script, code);
asAcquireExclusiveLock();
asIScriptModule *mod = engine->GetModule("my_module", asGM_ALWAYS_CREATE);
asReleaseExclusiveLock();
mod->AddScriptSection("my_module", code.c_str());
// Build the module
int r = mod->Build();
if( r < 0 )
{
printf("Please correct the errors in the script and try again.\n");
return;
}
asIScriptFunction *func = mod->GetFunctionByDecl("void main()");
if( func == 0 )
{
printf("The script must have the function %s. Please add it and try again.\n", function.c_str());
return -1;
}
while (true){ //This executes the function in the thread until it breaks
ctx->Prepare(func);
int r = ctx->Execute();
if (thread_break == true) break;
}
ctx->Release();
asThreadCleanup();
//Here threads end
The problem here is that it sometimes crashes. When I put asAcquireExclusiveLock(); around every as call then it doesn't, but then it impacts the framerate as it stalls for large amount of time. So what else needs to be locked specify? I could experiment and find out, but I would like to know what is recommend. Like if GetModule are not thread safe, then is GetFunctionByDecl neither? What is thread specific? Like can I call a function from the same context in two threads the same time (if they don't have any shared or global variables)? Do I need to Release "function" pointers just like I need to release contexts and engines?
And I seem to have problems with "Script section empty" error. I have tried several methods on loading files and I don't know why, but it sometimes fails. I tried the ScriptBuilder, as well as code from "Compiling scripts" section of the docs. When I have this error, I have to modify and save the file again for it to load. I do autoload files though based on their modify date, which could be the issue (I load it before it has finished writing on the disk??). I will add a delay and see if that helps. I do see that in threads formatInt() and other string functions crashes. Not sure if I'm at fault.
Another question is about variable sharing.
I need to have several blocks, like "BlockA" and "BlockB". I need have several instances of the same block, like "BlockA1" and "BlockA2". Then I need to execute the blocks in parallel without them interfering with one another. In AS terms each of my unique blocks (A and B) would be separate modules - "ModuleA" and "ModuleB". Then separate instances of blocks would be different contexts "ContextA1" and "ContextA2" right? So if contexts are different, then they won't interfere with one another? Like I need them to have global variables (declared outside any function, so it holds the state if you will), because each block is made out of several functions. Like this:
int s = 0; //State that doesn't change between function calls
void funcInit(){ //This is called from C++
s = 5;
}
void funcUpdate(){
s = s + 1; //This changes the state and is called from C++
}
I guess this is how something like that would work?