@@ -26,22 +26,26 @@ namespace SeExpr2 {
2626class ExprNode ;
2727class ExprVarNode ;
2828class ExprFunc ;
29- class Expression ;
30- class Interpreter ;
3129
3230class VarBlockCreator ;
3331
3432// / A thread local evaluation context. Just allocate and fill in with data.
3533class VarBlock {
3634 private:
3735 // / Allocate an VarBlock
38- VarBlock (int size) : indirectIndex(0 ) { _dataPtrs. resize (size); }
36+ VarBlock (int size, bool makeThreadSafe ) : indirectIndex(0 ), threadSafe(makeThreadSafe), _dataPtrs(size) { }
3937
4038 public:
4139 friend class VarBlockCreator ;
4240
4341 // / Move semantics is the only allowed way to change the structure
44- VarBlock (VarBlock&& other) { _dataPtrs = std::move (other._dataPtrs ); }
42+ VarBlock (VarBlock&& other) {
43+ threadSafe = other.threadSafe ;
44+ d = std::move (other.d );
45+ s = std::move (other.s );
46+ _dataPtrs = std::move (other._dataPtrs );
47+ indirectIndex = other.indirectIndex ;
48+ }
4549
4650 ~VarBlock () {}
4751
@@ -57,11 +61,20 @@ class VarBlock {
5761 // i.e. _dataPtrs[someAttributeOffset][indirectIndex]
5862 int indirectIndex;
5963
64+ // / if true, interpreter's data will be copied to this instance before evaluation.
65+ bool threadSafe;
66+
67+ // / copy of Interpreter's double data
68+ std::vector<double > d;
69+
70+ // / copy of Interpreter's str data
71+ std::vector<char *> s;
72+
6073 // / Raw data of the data block pointer (used by compiler)
6174 char ** data () { return _dataPtrs.data (); }
6275
6376 private:
64- // / This stores double* or char** ptrs
77+ // / This stores double* or char** ptrs to variables
6578 std::vector<char *> _dataPtrs;
6679};
6780
@@ -97,7 +110,17 @@ class VarBlockCreator {
97110 }
98111
99112 // / Get an evaluation handle (one needed per thread)
100- VarBlock create () { return VarBlock (_nextOffset); }
113+ // / \param makeThreadSafe
114+ // / If true, right before evaluating the expression, all data used
115+ // / by the interpreter will be copied to the var block, to make the
116+ // / evaluation thread safe (assuming there's one var block instead
117+ // / per thread)
118+ // / If false or not specified, the old behavior occurs (var block
119+ // / will only hold variables sources and optionally output data,
120+ // / and the interpreter will work on its internal data)
121+ VarBlock create (bool makeThreadSafe = false ) {
122+ return VarBlock (_nextOffset, makeThreadSafe);
123+ }
101124
102125 // / Resolve the variable using anything in the data block (call from resolveVar in Expr subclass)
103126 ExprVarRef* resolveVar (const std::string& name) const {
0 commit comments