I'm trying to use a mutex to prevent multiple threads from reading variables at the same time.
My code generates multiple "Carriers" objects all having the same "SMSDetector" and the code crashes (segmentation fault) when trying to evaluate some Dolfin functions (yes I use Fenics libraries for some FEM calculations); so I'm trying to lock the mutex before evaluation and unlock afterwards.
My problem now is that I need copy/move constructors for Carrier class to be mov/copi-able but I don't seem to get them right. Without the mutex I get: Carrier.cpp:203:42: error: ‘Carrier& operator=(const Carrier&)’ must be a nonstatic member function Carrier& operator = (const Carrier& other)
and with the mutex I get: Carrier.cpp:200:49: error: no matching function for call to ‘std::lock_guard<std::mutex>::lock_guard(const std::mutex&)’
std::lock_guard<std::mutex> lock(other.safeRead);
I'm trying to write the whole program in c++11 standard, so if anyone has a c++11 solution would be really appreciated.
Here is the conflicting code:
std::valarray<double> Carrier::simulate_drift(double dt, double max_time, double x_init, double y_init )
{
_x[0] = x_init;
_x[1] = y_init;
// get number of steps from time
int max_steps = (int) std::floor(max_time / dt);
std::valarray<double> i_n(max_steps); // valarray to save intensity
runge_kutta4<std::array< double,2>> stepper;
// wrapper for the arrays using dolphin array class
Array<double> wrap_x(2, _x.data());
Array<double> wrap_e_field(2, _e_field.data());
Array<double> wrap_w_field(2, _w_field.data());
double t=0.0; // Start at time = 0
for ( int i = 0 ; i < max_steps; i++)
{
if (t < _gen_time) // If CC not yet generated
{
i_n[i] = 0;
}
else if (_detector->is_out(_x)) // If CC outside detector
{
i_n[i] = 0;
break; // Finish (CC gone out)
}
else
{
safeRead.lock();
_detector->get_d_f_grad()->eval(wrap_e_field, wrap_x);
_detector->get_w_f_grad()->eval(wrap_w_field, wrap_x);
safeRead.unlock();
_e_field_mod = sqrt(_e_field[0]*_e_field[0] + _e_field[1]*_e_field[1]);
i_n[i] = _q *_sign* _mu.obtain_mobility(_e_field_mod) * (_e_field[0]*_w_field[0] + _e_field[1]*_w_field[1]);
stepper.do_step(_drift, _x, t, dt);
// Trapping effects due to radiation-induced defects (traps) implemented in CarrierColleciton.cpp
}
t+=dt;
}
return i_n;
}
/*
* Copy initialization
*/
Carrier::Carrier(const Carrier& other)
{
_carrier_type = other._carrier_type;
_q = other._q;
_gen_time = other._gen_time;
_x = other._x;
_e_field = other._e_field;
_w_field = other._w_field;
_e_field_mod = other._e_field_mod;
_sign = other._sign;
_detector = other._detector;
_myTemp = other._myTemp;
_drift = other._drift;
_mu = other._mu;
_trapping_time = other._trapping_time;
std::lock_guard<std::mutex> lock(other.safeRead);
}
/*
* Copy assignment
*/
Carrier& operator = (const Carrier& other)
{
// std::lock(safeRead, other.safeRead;
// std::lock_guard<std::mutex> self_lock(safeRead, std::adopt_lock;
// std::lock_guard<std::mutex> other_lock(other.safeRead, std::adopt_lock;
std::lock_guard<std::mutex> self_lock(safeRead, std::adopt_lock);
std::lock_guard<std::mutex> other_lock(other.safeRead, std::adopt_lock);
_carrier_type = other._carrier_type;
_q = other._q;
_gen_time = other._gen_time;
_x = other._x;
_e_field = other._e_field;
_w_field = other._w_field;
_e_field_mod = other._e_field_mod;
_sign = other._sign;
_detector = other._detector;
_myTemp = other._myTemp;
_drift = other._drift;
_trapping_time = other._trapping_time;
return *this;
}
/*
* Move initialization
*/
Carrier::Carrier(Carrier&& other)
{
_carrier_type = std::move(other._carrier_type);
_q = std::move(other._q);
_gen_time = std::move(other._gen_time);
_x = std::move(other._x);
_e_field = std::move(other._e_field);
_w_field = std::move(other._w_field);
_e_field_mod = std::move(other._e_field_mod);
_sign = std::move(other._sign);
_detector = std::move(other._detector);
_myTemp = std::move(other._myTemp);
_drift = std::move(other._drift);
_mu = std::move(other._mu);
_trapping_time = std::move(other._trapping_time);
std::lock_guard<std::mutex> lock(other.safeRead);
}
/*
* Move assignment
*/
Carrier& operator = ( Carrier&& other)
{
std::lock(safeRead, other.safeRead);
std::lock_guard<std::mutex> self_lock(safeRead, std::adopt_lock);
std::lock_guard<std::mutex> other_lock(other.safeRead, std::adopt_lock);
_carrier_type = std::move(other._carrier_type);
other._carrier_type = NULL;
_q = std::move(other._q);
other._q = 0;
_gen_time = std::move(other._gen_time);
other._gen_time = 0;
_x = std::move(other._x);
other._x = {0,0};
_e_field = std::move(other._e_field);
other._e_field = {0,0};
_w_field = std::move(other._w_field);
other._w_field = {0,0};
_e_field_mod = std::move(other._e_field_mod);
other._e_field_mod = 0;
_sign = std::move(other._sign);
other._sign = 0;
_detector = std::move(other._detector);
other._detector = NULL;
_myTemp = std::move(other._myTemp);
other._myTemp = 0;
_drift = std::move(other._drift);
_mu = std::move(other._mu);
_trapping_time = std::move(other._trapping_time);
other._trapping_time = 1e300;
return *this;
}
I would upload more of the code if helpful but I feel this is enough.
Thanks in advance for the help
EDIT: Class declaration (full header file):
#ifndef CARRIER_H
#define CARRIER_H
#include <valarray>
#include <mutex>
#include <CarrierTransport.h>
#include <SMSDetector.h>
#ifndef Q_MOC_RUN // See: https://bugreports.qt-project.org/browse/QTBUG-22829
#include <boost/numeric/odeint/stepper/runge_kutta4.hpp>
#endif
using namespace boost::numeric::odeint;
class Carrier
{
private:
char _carrier_type;
double _q; // charge
double _gen_time; // instant of generation of the carrier
std::array< double,2> _x; // carrier position array
std::array< double,2> _e_field; // electric field at the carrier position
std::array< double,2> _w_field; // weighting field at the carrier positions
double _e_field_mod;
int _sign; // sign to describe if carrier moves in e field direction or opposite
// std::mutex safeRead;
SMSDetector * _detector;
double _myTemp; // Temperature of the detector
DriftTransport _drift;
JacoboniMobility _mu;
double _trapping_time;
public:
Carrier( char carrier_type, double q, double x_init, double y_init, SMSDetector * detector, double gen_time);
Carrier(Carrier&& other); // Move declaration
Carrier& operator = (Carrier&& other); // Move assignment
Carrier(const Carrier& other); // Copy declaration
Carrier& operator = (const Carrier& other); // Copy Assignment
~Carrier();
char get_carrier_type();
std::array< double,2> get_x();
double get_q();
std::valarray<double> simulate_drift( double dt, double max_time);
std::valarray<double> simulate_drift(double dt, double max_time, double x_init, double y_init );
};
#endif // CARRIER_H