0

A class t_analyser contains a function which performs some operations on a t_data object and outputs the results.

I would like to add to t_analyser a filter capability: a small and fast function

bool filter(const t_data & d) {...}

which allows to skip the analysis (and the output) if some conditions are met for that particular data. The filter should be setted up easily from the main, so I was thinking to store a shared function pointer in t_analyser and use a lambda to initialize it.

Is this a good approach? My concerns are related to the fact that many analysers can call the same filter function simultaneously in different threads, could this be a problem? Can I simply copy the pointer in the t_analyser's copy constructor? Any hint would be much appreciated.

DarioP
  • 5,377
  • 1
  • 33
  • 52
  • Your class contains a function that "performs some operations and outputs the results". Pass your lambda as an argument to this function, using a new parameter of the correct function pointer type. That way the function pointer is not shared between threads. – Kris Vandermotten Nov 19 '13 at 11:18
  • @KrisVandermotten I see the point, however that function is virtual and called many times in different places. Even taking huge efforts to modify the design, I would still need a place to store the filter functions. If this place is outside the `t_analyser` class, referencing would be hard, as filters can be different for different analyser objects. – DarioP Nov 19 '13 at 11:46
  • @DarioP, concerning the member function pointer, irrespective from which thread the member function pointer is used, it remains the same (or can if you've passed it by value to some holding class such as std::function). – Werner Erasmus Nov 19 '13 at 13:09
  • When used/called from various threads, it all depends on whether the code in the member function pointer modifies/reads shared data simultaneously. This would be the case if the same this pointer is used, in which case care must be taken when accessing (simultaneous read/writes or write/writes) its data members. – Werner Erasmus Nov 19 '13 at 13:12

3 Answers3

1

This could be a problem if your filter function had side effects. Its signature is simple and says that it just makes some decision reading data from t_data, so make sure that t_data is not modified in parallel thread and you'll be fine.

Andriy Tylychko
  • 15,967
  • 6
  • 64
  • 112
  • I think you are right. I was confused by the fact that two simultaneous calls to the function may influence each other, but this does not happen with normal functions and the same should be with pointers. – DarioP Nov 19 '13 at 12:42
0

Consider the following program:

#include <iostream>

struct X
{
    void foo1(){ std::cout << "foo1" << std::endl; }
    void foo2(){ std::cout << "foo2" << std::endl; }
};

typedef void (X::*MemberFunctionPointer)();

struct ByRef
{
    ByRef( MemberFunctionPointer& f )
      : f_( f )
    {
    }
    void operator()()
    {
      X x;
      (x.*f_)();
    }
    MemberFunctionPointer& f_;
};

struct ByValue
{
    ByValue( MemberFunctionPointer f )
      : f_( f )
    {
    }
    void operator()()
    {
      X x;
      (x.*f_)();
    }
    MemberFunctionPointer f_;
};

int main()
{
  MemberFunctionPointer p = &X::foo1;
  ByRef byRef( p );
  ByValue byValue( p );
  byRef();
  byValue();

  p = &X::foo2;
  byRef();
  byValue();
  return 0;
}

Output:

foo1
foo1
foo2
foo1
Press <RETURN> to close this window...

From this you will notice that in the one case the member function pointer is passed by value (and not shared), and in the other it is passed by reference (and shared). When using the syntax:

foo( void( X::*f)() )...

the pointer to member function is passed by value, and is copied (and cannot be modified) again.

Werner Erasmus
  • 3,988
  • 17
  • 31
0

You can declare the function pointer as static + thread specific:

static _declspec(thread) FUNC_TYPE filterFunc;

Each thread that modifies filterFunc works on a different copy of the pointer.

egur
  • 7,830
  • 2
  • 27
  • 47