apply_pointwise must support functors with state
apply_pointwise
requires a functor type as a template argument. For example:
FieldT var1, var2, result;
//...
result <<= apply_pointwise<FunctorT>( var1, var2 );
However, if FunctorT
must have state, then we have a problem:
class FunctorT{
static const InterpT*& get_evaluator(){
static const InterpT* eval = NULL;
return eval;
}
public:
static void set_evaluator( const InterpT* eval ){
get_evaluator() = eval;
}
double operator()( const double x ) const{
return get_evaluator()->value(&x);
}
};
// ...
FunctorT::set_evaluator( &evaluator );
result <<= apply_pointwise<FunctorT>( var1, var2 );
Here, FunctorT
can only provide a static method (in this case set_evaluator
) because the FunctorT
object is instantiated within apply_pointwise
.
The problem arises when we have multiple apply_pointwise
assignments executed concurrently involving FunctorT
but requiring different state. In this case, we end up with race conditions and undefined behavior on the state within FunctorT
.
Here is a simple example that illustrates the essence of the problem:
#include <iostream>
class A{
int& get_val(){ static int val; return val; }
public:
void set_val( const int i ){ get_val()=i; }
void operator()(){
std::cout << get_val() << std::endl;
}
};
int main(){
A a1, a2;
a1.set_val( 1 );
a1(); // prints "1" as expected
a2.set_val( 2 );
a1(); // prints "2" - a2 wrecks the value in a1.
a2(); // prints "2" as expected
return 0;
}
@michaelb or @michaelbrown can you comment on how you think we should address this?