如何复制/移动包含互斥体的类

Al *_*epé 6 c++ multithreading mutex c++11

我正在尝试使用互斥锁来防止多个线程同时读取变量。

\n\n

我的代码生成多个“Carriers”对象,所有对象都具有相同的“SMSDetector”,并且在尝试评估某些 Dolfin 函数时代码崩溃(分段错误)(是的,我使用 Fenics 库进行一些 FEM 计算);所以我试图在评估之前锁定互斥体并在评估之后解锁。

\n\n

我现在的问题是,我需要复制/移动构造函数以使 Carrier 类能够 mov/copi,但我似乎没有正确理解它们。没有互斥体我得到:Carrier.cpp:203:42: error: \xe2\x80\x98Carrier& operator=(const Carrier&)\xe2\x80\x99 must be a nonstatic member function Carrier& operator = (const Carrier& other)

\n\n

通过互斥体我得到:Carrier.cpp:200:49: error: no matching function for call to \xe2\x80\x98std::lock_guard<std::mutex>::lock_guard(const std::mutex&)\xe2\x80\x99\n std::lock_guard<std::mutex> lock(other.safeRead);

\n\n

我正在尝试用 c++11 标准编写整个程序,因此如果有人有 c++11 解决方案,我将非常感激。

\n\n

这是冲突的代码:\n

\n\n
std::valarray<double> Carrier::simulate_drift(double dt, double max_time, double x_init, double y_init )\n\n{\n      _x[0] = x_init;\n      _x[1] = y_init;\n\n      // get number of steps from time\n  int max_steps = (int) std::floor(max_time / dt);\n\n  std::valarray<double>  i_n(max_steps); // valarray to save intensity\n\n  runge_kutta4<std::array< double,2>> stepper;\n\n  // wrapper for the arrays using dolphin array class\n  Array<double> wrap_x(2, _x.data());\n  Array<double> wrap_e_field(2, _e_field.data());\n  Array<double> wrap_w_field(2, _w_field.data());\n\n  double t=0.0; // Start at time = 0\n\n  for ( int i = 0 ; i < max_steps; i++)\n  {\n\n    if (t < _gen_time) // If CC not yet generated\n    {   \n      i_n[i] = 0;\n    }   \n    else if (_detector->is_out(_x)) // If CC outside detector\n    {   \n      i_n[i] = 0;\n      break; // Finish (CC gone out)\n    }   \n    else\n    {   \n      safeRead.lock();\n      _detector->get_d_f_grad()->eval(wrap_e_field, wrap_x);\n      _detector->get_w_f_grad()->eval(wrap_w_field, wrap_x);\n      safeRead.unlock();\n      _e_field_mod = sqrt(_e_field[0]*_e_field[0] + _e_field[1]*_e_field[1]);\n      i_n[i] = _q *_sign* _mu.obtain_mobility(_e_field_mod) * (_e_field[0]*_w_field[0] + _e_field[1]*_w_field[1]);\n      stepper.do_step(_drift, _x, t, dt);\n      // Trapping effects due to radiation-induced defects (traps) implemented in CarrierColleciton.cpp\n    }   \n    t+=dt;\n  }\n    return i_n;\n}\n/*\n * Copy initialization\n */\nCarrier::Carrier(const Carrier& other)\n{\n  _carrier_type = other._carrier_type;\n    _q = other._q;\n    _gen_time = other._gen_time;\n    _x = other._x; \n    _e_field = other._e_field; \n    _w_field = other._w_field;\n    _e_field_mod = other._e_field_mod;\n    _sign = other._sign; \n    _detector = other._detector;\n    _myTemp = other._myTemp;\n    _drift = other._drift;\n    _mu = other._mu;\n    _trapping_time = other._trapping_time;\n    std::lock_guard<std::mutex> lock(other.safeRead);\n}\n\n/*\n * Copy assignment\n */\nCarrier& operator = (const Carrier& other) \n{\n//  std::lock(safeRead, other.safeRead;\n//  std::lock_guard<std::mutex> self_lock(safeRead, std::adopt_lock;\n//  std::lock_guard<std::mutex> other_lock(other.safeRead, std::adopt_lock;\n    std::lock_guard<std::mutex> self_lock(safeRead, std::adopt_lock);\n    std::lock_guard<std::mutex> other_lock(other.safeRead, std::adopt_lock);\n  _carrier_type = other._carrier_type;\n    _q = other._q;\n    _gen_time = other._gen_time;\n    _x = other._x; \n    _e_field = other._e_field; \n    _w_field = other._w_field;\n    _e_field_mod = other._e_field_mod;\n    _sign = other._sign; \n    _detector = other._detector;\n    _myTemp = other._myTemp;\n    _drift = other._drift;\n    _trapping_time = other._trapping_time;\n    return *this;\n}\n\n\n/*\n * Move initialization\n */\nCarrier::Carrier(Carrier&& other)\n{\n  _carrier_type = std::move(other._carrier_type);\n    _q = std::move(other._q);\n    _gen_time = std::move(other._gen_time);\n    _x = std::move(other._x); \n    _e_field = std::move(other._e_field); \n    _w_field = std::move(other._w_field);\n    _e_field_mod = std::move(other._e_field_mod);\n    _sign = std::move(other._sign); \n    _detector = std::move(other._detector);\n    _myTemp = std::move(other._myTemp);\n    _drift = std::move(other._drift);\n    _mu = std::move(other._mu);\n    _trapping_time = std::move(other._trapping_time);\n    std::lock_guard<std::mutex> lock(other.safeRead);\n}\n\n/*\n * Move assignment\n */\nCarrier& operator = ( Carrier&& other) \n{\n    std::lock(safeRead, other.safeRead);\n    std::lock_guard<std::mutex> self_lock(safeRead, std::adopt_lock);\n    std::lock_guard<std::mutex> other_lock(other.safeRead, std::adopt_lock);\n  _carrier_type = std::move(other._carrier_type);\n    other._carrier_type = NULL;\n    _q = std::move(other._q);\n    other._q = 0;\n    _gen_time = std::move(other._gen_time);\n    other._gen_time = 0;\n    _x = std::move(other._x); \n    other._x = {0,0};\n    _e_field = std::move(other._e_field); \n    other._e_field = {0,0};\n    _w_field = std::move(other._w_field);\n    other._w_field = {0,0};\n    _e_field_mod = std::move(other._e_field_mod);\n    other._e_field_mod = 0;\n    _sign = std::move(other._sign); \n    other._sign = 0;\n    _detector = std::move(other._detector);\n    other._detector = NULL;\n    _myTemp = std::move(other._myTemp);\n    other._myTemp = 0;\n    _drift = std::move(other._drift);\n    _mu = std::move(other._mu);\n    _trapping_time = std::move(other._trapping_time);\n    other._trapping_time = 1e300;\n    return *this;\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

如果有帮助,我会上传更多代码,但我觉得这已经足够了。

\n\n

先谢谢您的帮助

\n\n

编辑:类声明(完整头文件):

\n\n
#ifndef CARRIER_H\n#define CARRIER_H\n\n#include  <valarray>\n#include  <mutex>\n\n#include <CarrierTransport.h>\n#include <SMSDetector.h>\n\n#ifndef Q_MOC_RUN  // See: https://bugreports.qt-project.org/browse/QTBUG-22829\n#include <boost/numeric/odeint/stepper/runge_kutta4.hpp>\n#endif\n\nusing namespace boost::numeric::odeint;\n\nclass Carrier\n{\n  private:\n    char _carrier_type;\n    double _q; // charge\n    double _gen_time; // instant of generation of the carrier\n    std::array< double,2> _x; // carrier position array\n    std::array< double,2> _e_field; // electric field at the carrier position\n    std::array< double,2> _w_field; // weighting field at the carrier positions\n    double _e_field_mod;\n    int _sign; // sign to describe if carrier moves in e field direction or opposite\n//      std::mutex safeRead;\n\n    SMSDetector * _detector;\n    double _myTemp; // Temperature of the detector\n    DriftTransport _drift;\n    JacoboniMobility _mu;\n    double _trapping_time;\n\n  public:\n    Carrier( char carrier_type, double q, double x_init, double y_init, SMSDetector * detector, double gen_time);\n        Carrier(Carrier&& other); // Move declaration\n        Carrier& operator = (Carrier&& other); // Move assignment\n        Carrier(const Carrier& other); // Copy declaration\n        Carrier& operator = (const Carrier& other); // Copy Assignment\n        ~Carrier();\n\n    char get_carrier_type();\n\n    std::array< double,2> get_x();\n    double get_q();\n\n    std::valarray<double> simulate_drift( double dt, double max_time);\n    std::valarray<double> simulate_drift(double dt, double max_time, double x_init, double y_init );\n};\n\n#endif // CARRIER_H\n
Run Code Online (Sandbox Code Playgroud)\n

Jas*_*n R 1

在您的实现中operator=,您需要指定类名:

Carrier& Carrier::operator = (const Carrier& other)

锁定互斥体时,您会收到您所描述的编译错误,因为std::mutex::lock()它不是一种const方法。在赋值运算符中,您应该other按引用获取参数。const因此,它试图constconst对象上调用非函数,从而导致编译错误。

mutable解决方法是按照类声明中的方式声明成员Carrier

mutable std::mutex safeRead;

这允许您解决编译错误。