Based on the comments I think I've come up with an answer. I used @Sam Varshavchik's suggestion and I define the thread function as:
void write_image_thread(std::valarray<T> &data, Archon::Information &info, FITS_file<T> *obj) {
const std::lock_guard<std::mutex> lock(obj->fits_mutex); // access private members!
obj->writing_file = true; // access private members!
try {
obj->pFits->pHDU().addKey("EXPOSURE", fpixel,"Total Exposure Time");
// and more stuff...
}
catch (CCfits::FitsError& error){
// handle faults
}
// all done
obj->writing_file = false;
}
then call it with:
std::thread([&](){this->write_image_thread(std::ref(array), std::ref(info), this);}).detach();
and this seems to work! So I think this is the answer (I'm going to try to exercise it a bit more before tagging this as answered, to be safe).
Not sure if it's good practice to ask addition questions but they're related...
1) are the std::ref() functions really necessary? I added them to be explicit but it seems to work without them.
2) I have to admit I don't REALLY understand the lambda expression I'm using; I found that on another Stack Overflow question (C++ 11 Thread initialization with member functions compiling error -- in a comment on the original question). I've tried various ways to make it work without the lambda but can't get it to compile otherwise.
In other words, this:
std::thread(&FITS_file<T>::write_image_thread, std::ref(array), std::ref(info), this).detach();
does not work; it gives the following error:
In file included from /usr/include/c++/4.8.2/mutex:42:0,
from /home/user/archon-interface/include/common.h:13,
from /home/user/archon-interface/src/archon.cpp:9:
/usr/include/c++/4.8.2/functional: In instantiation of ‘struct std::_Bind_simple<std::_Mem_fn<void (FITS_file<float>::*)(std::valarray<float>&, Archon::Information&, FITS_file<float>*)>(std::reference_wrapper<std::valarray<float> >, std::reference_wrapper<Archon::Information>, FITS_file<float>*)>’:
/usr/include/c++/4.8.2/thread:137:47: required from ‘std::thread::thread(_Callable&&, _Args&& ...) [with _Callable = void (FITS_file<float>::*)(std::valarray<float>&, Archon::Information&, FITS_file<float>*); _Args = {std::reference_wrapper<std::valarray<float> >, std::reference_wrapper<Archon::Information>, FITS_file<float>* const}]’
/home/user/archon-interface/include/fits.h:137:94: required from ‘long int FITS_file<T>::write_image(T*, Archon::Information&) [with T = float]’
/home/user/archon-interface/src/archon.cpp:1697:52: required from here
/usr/include/c++/4.8.2/functional:1697:61: error: no type named ‘type’ in ‘class std::result_of<std::_Mem_fn<void (FITS_file<float>::*)(std::valarray<float>&, Archon::Information&, FITS_file<float>*)>(std::reference_wrapper<std::valarray<float> >, std::reference_wrapper<Archon::Information>, FITS_file<float>*)>’
typedef typename result_of<_Callable(_Args...)>::type result_type;
^
/usr/include/c++/4.8.2/functional:1727:9: error: no type named ‘type’ in ‘class std::result_of<std::_Mem_fn<void (FITS_file<float>::*)(std::valarray<float>&, Archon::Information&, FITS_file<float>*)>(std::reference_wrapper<std::valarray<float> >, std::reference_wrapper<Archon::Information>, FITS_file<float>*)>’
_M_invoke(_Index_tuple<_Indices...>)
^
make[2]: *** [CMakeFiles/archonserver.dir/src/archon.cpp.o] Error 1
make[1]: *** [CMakeFiles/archonserver.dir/all] Error 2
make: *** [all] Error 2
But as I said, if I use the lambda then it works! So maybe I should just be happy with that.