wdas / SeExpr

SeExpr is an embeddable, arithmetic expression language that enables flexible artistic control and customization in creating computer graphics images. Example uses include procedural geometry synthesis, image synthesis, simulation control, crowd animation, and geometry deformation. https://wdas.github.io/SeExpr
https://www.disneyanimation.com/open-source/seexpr/
Other
405 stars 86 forks source link

Make Interpreter's evaluations thread safe #80

Closed ix-dcourtois closed 7 years ago

ix-dcourtois commented 7 years ago

Hi,

I've been playing with SeExpr in a multithreaded context, and I noticed that if you evaluate the same expression "v" in multiple threads, you get corrupted results, even if each thread is using a VarBlock instance.

The problem is that even though VarBlock holds input variables values and can hold the result of the evaluation, it doesn't hold the working data: Interpreter::d. This is where each op code writes its result. For instance, EvalVarBlockIndirect :

    double* destPointer = fp + destIndex;
    for (int i = 0; i < dim; i++) destPointer[i] = basePointer[i];

fp is a pointer to the Interpreter's d member. And this member is shared between all concurrent evalutions ...

Using the LLVM evaluator there is no problem, probably because the generated code works on the stack, and each evaluation creates its own stack.

Anyway, this pull request fixes the problem for the Interpreter by storing copies of the working data (namely the d and s members of Interpreter in the instance of VarBlock passed to the evaluation method.

If you have any question or remarks on the pull request, don't hesitate.