You need to make sure that the function runs identically everytime it is called.
This generally means that you need to protect any data that is accessed/written in the function.
For stand-alone free functions that generally means removing static elements from function.
If you are referring to a member function of some class, then you need to be more careful - because the class will generally store data independantely of the member function which may change between calls to that member. You will generally do this with a mutex.
For example:
//Threadsafe because the function do not change each time it is called
double add_one(double d)
{
return d+1;
}
struct A
{
double m_data;
//Not thread safe because if function called simultaneously then m_data could change more than once before it is returned
double
run(double d)
{
m_data += d;
return m_data/2.0;
}
}
This can be fixed by adding a mutex that demands that two threads cannot run the run member simultaneously. See Boost.Thread for a good mutex example.
struct A
{
double m_data;
mutex m_mutex;
//Thread safe because mutex protects m_data from being written by multiple threads at once
double
run(double d)
{
lock(m_mutex); //lock the function, unlock on destruction.
m_data += d;
return m_data/2.0;
}
}