Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use a std::mutex in a class context

i'm having some trouble using a C++11 std::mutex

in my class I have a variable called semaphore of type std::mutex.

So I positioned my semaphore.lock() and semaphore.unlock() before and after my critical section

class Database {
public:
Database(string, string, string, string);
virtual ~Database();

struct sMyHome getMyHome(void);
struct sPhysical getPhysical(int);
struct sSystemInfo getSystemInfo(void);
void commitSystemInfo(struct sSystemInfo);
struct sTSensors getTSensors(int);
struct sWireless getWireless(int);
struct sWirelessConf getWirelessConf(int);
struct sWirelessStatus getWirelessStatus(int);

private:
void queryMyHome(void);
void queryPhysical(int);
void querySystemInfo(void);
void queryTSensors(int ID);
void queryWireless(int ID);
void queryWirelessConf(int ID);
void queryWirelessStatus(int ID);
string toString(int);

struct sMyHome MyHome;
struct sPhysical Physical[4];
struct sSystemInfo SystemInfo;
struct sTSensors TSensors[32];
struct sWireless Wireless[64];
struct sWirelessConf WirelessConf[64];
struct sWirelessStatus WirelessStatus[64];

MYSQL *connection;
mutex semaphore;
};

this is part of the main, where I retrieve the error:

 Database db = Database("192.168.1.10", "****", "******", "******");

but the cross-compiler says

../main.cpp:8:73: error: use of deleted function 'Database::Database(const Database&)'
  Database db = Database("192.168.1.10", "root", "raspberry", "DomoHome2");
                                                                     ^
In file included from ../main.cpp:2:0:
../Database.h:79:7: note: 'Database::Database(const Database&)' is implicitly deleted      because the default definition would be ill-formed:
 class Database {
   ^
../Database.h:79:7: error: use of deleted function 'std::mutex::mutex(const std::mutex&)'
 In file included from ../Database.h:12:0,
             from ../main.cpp:2:
/Volumes/rpi-crosscompiler-toolchain/arm-none-linux-gnueabi/arm-none-linux-gnueabi/include/c++/4.8.2/mutex:128:5: error: declared here
 mutex(const mutex&) = delete;
 ^
make: *** [main.o] Error 1

and this is my constructor:

Database::Database(string Address, string Username, string Password, string Database) {
// TODO Auto-generated constructor stub
connection = mysql_init(NULL);
mysql_real_connect(connection, Address.c_str(), Username.c_str(), Password.c_str(), Database.c_str(), 0, NULL, 0);
}
like image 397
Angelo Cassano Avatar asked Jun 17 '14 20:06

Angelo Cassano


People also ask

How do you use mutex in C++?

In C++, we create a mutex by constructing an instance of std::mutex, lock it with a call to the member function lock(), and unlock it with a call to the member function unlock().

How does STD mutex work?

The mutex class is a synchronization primitive that can be used to protect shared data from being simultaneously accessed by multiple threads. mutex offers exclusive, non-recursive ownership semantics: A calling thread owns a mutex from the time that it successfully calls either lock or try_lock until it calls unlock .

Can std :: mutex be copied?

Clearly the above is not possible as mutex object is not copyable.

Is std :: mutex fair?

On windows e.g. mutexes are mostly fair, but not always. Some implementations e.g. Thread Building Block provide special mutexes that are fair, but these are not based on the OSes native mutexes, and are usually implemented as spin-locks (which have their own caveats). Save this answer.


1 Answers

std::mutex is neither copyable nor movable. Including one in your class necessitates that your class becomes non-copyable (-movable) as well. If you want your class to be copyable or movable, you will have to tell the compiler how objects of your class are to be copied or moved by implementing copy/move construction/assignment yourself. For example:

class synchronized_int {
  mutable std::mutex mtx;
  int value;
public:
  synchronized_int(int v = 0) : value(v) {}

  // Move initialization
  synchronized_int(synchronized_int&& other) {
    std::lock_guard<std::mutex> lock(other.mtx);
    value = std::move(other.value);
    other.value = 0;
  }

  // Copy initialization
  synchronized_int(const synchronized_int& other) {
    std::lock_guard<std::mutex> lock(other.mtx);
    value = other.value;
  }

  // Move assignment
  synchronized_int& operator = (synchronized_int&& other) {
    std::lock(mtx, other.mtx);
    std::lock_guard<std::mutex> self_lock(mtx, std::adopt_lock);
    std::lock_guard<std::mutex> other_lock(other.mtx, std::adopt_lock);
    value = std::move(other.value);
    other.value = 0;
    return *this;
  }

  // Copy assignment
  synchronized_int& operator = (const synchronized_int& other) {
    std::lock(mtx, other.mtx);
    std::lock_guard<std::mutex> self_lock(mtx, std::adopt_lock);
    std::lock_guard<std::mutex> other_lock(other.mtx, std::adopt_lock);
    value = other.value;
    return *this;
  }
};
like image 125
Casey Avatar answered Sep 27 '22 20:09

Casey