niklas
niklas

Reputation: 9

Mutex inside templated struct causes segmentation fault

For exchanging data between classes, I use a kind of "main-hub-class", from which each other class can access the data.
Now, to make this thread-safe I came up with a templated struct that holds a variable and a boost::shared_mutex for that variable:

class DataExchange {
    [...]
    template <typename T>
    struct ShareDataEntry {
            T value;
            boost::shared_mutex _mutex;
    };

    SharedDataEntry<int> ultraSonicValue;
    [...]
}

In the .cpp I am trying to use that like this:

void DataExchange::setUltrasSonicValue(int _value) {
    boost::unique_lock<boost::shared_mutex> lock ( ultraSonicValue._mutex ); // <-- this segfaults
        ultraSonicValue.value = _value;
    lock.unlock();
}

From gdb, I get the error

__GI____pthread_mutex_lock (mutex=0x58) at pthread_mutex_lock.c:66  
66       pthread_mutex_lock.c: No such file or directory

What am I doing wrong? My guess is that the mutex isn't initialized? But how (and where) would I do that?

EDIT

Updated code sample, now showing everything I use, also with a test for the problem I described:

DataExchange.hpp:

#pragma once

#include <boost/thread.hpp>

class DataExchange {
    private:
        DataExchange();
        DataExchange(DataExchange const&) {};
        DataExchange& operator=(DataExchangeconst&) { return *instance; };
        static DataExchange* instance;
        template <typename T>
        struct ShareDataEntry {
                T value;
                boost::shared_mutex _mutex;
        };

        // simple int with extra mutex
        int testIntOne;
        boost::shared_mutex testIntOne_M;

        // int in my struct
        SharedDataEntry<int> testIntTwo;

    public:
        static DataExchange* getInstance();
        ~DataExchange() { delete instance; };

        void setTestIntOne(int _tmp);
        int getTestIntOne();
        void setTestIntTwo(int _tmp);
        int getTestIntTwo();
}  

DataExchange.cpp:

#include "infrastructure/DataExchange.hpp"

DataExchange* DataExchange::instance = NULL;

DataExchange::DataExchange() {};

DataExchange* DataExchange::getInstance() {
    if (instance == NULL) instance = new DataExchange;
    return instance;
}

void DataExchange::setTestIntOne(int _tmp) {
    boost::unique_lock<boost::shared_mutex> lock ( testIntOne_M ); // this is now where the segfault occurs
        testIntOne = _tmp;
    lock.unlock();
}

int DataExchange::getTestIntOne() {
    boost::shared_lock<boost::shared_mutex> lock ( testIntOne_M );
    return testIntOne;
}

void DataExchange::setTestIntTwo(int _tmp) {
    boost::unique_lock<boost::shared_mutex> lock ( testIntTwo._mutex );
        testIntTwo.value = _tmp;
    lock.unlock();
}

int DataExchange::getTestIntTwo() {
    boost::shared_lock<boost::shared_mutex> lock ( testIntTwo._mutex );
    return testIntTwo.value;
}  

main.cpp:

#inlcude "infarstructure/DataExchange.hpp"

int main(int argc, char *argv[]) {
    DataExchange* dataExchange = DataExchange::getInstance();

    // this line segfaults already, altough I was pretty sure it worked before
    dataExchange->setTestIntOne(5);
    cout << dataExchange->getTestIntOne() << "\n";

    dataExchange->setTestIntTwo(-5);
    cout << dataExchange->getTestIntTwo() << "\n";

    return 0;
}  

Does it segfault because the mutex wasn't initialized? Also, I am very sure it worked earlier, at least the first way (without the struct).

Second Edit:
Alright, everything is working fine now. It was a stupid mistake on my part. Both approaches work flawlessly - as long as one initializes the DataExchange object.

Upvotes: 0

Views: 379

Answers (0)

Related Questions