Search code examples
c++multithreadingmutexcondition-variable

Exceptions while using mutex and condition_variable


I'm writing a program to read data from .txt file and using it in output .txt file. I'm using two threads; The first thread is for reading the data from the .txt file, and the second one is for writing it in the output file. I'm a beginner in the programming with mutex and condition_variable and for somehow my program handles exceptions... The exception is

abort() has been called.

These are the two threads methods:

void MessagesSender::readsData()
{
    ifstream data;
    data.open("data.txt");
    string buffer;
    bool toEmpty = false;
    std::unique_lock<mutex> locker(mtx, std::defer_lock);
    if (data.is_open())
    {
        while (std::getline(data, buffer)) //reads line to the buffer.
        {
            locker.lock();
            this->messages.push(buffer); //push the message to the queue.
            locker.unlock();
            cond.notify_one();
        }
        data.close();
        toEmpty = true;
    }
    else
    {
        cout << "Error opening file... " << endl;
    }
    if (toEmpty) //empty the data file.
    {
        ofstream emptyFile; 
        emptyFile.open("data.txt", ofstream::out | ofstream::trunc);
        emptyFile.close();
    }
}

void MessagesSender::sendsData()
{
    ofstream output;
    output.open("output.txt");
    string tempString;
    string tempMessage;

    if (output.is_open())
    {
        std::unique_lock<mutex> locker(mtx, std::defer_lock);
        locker.lock();
        cond.wait(locker);
        while (!(this->messages.empty()))
        {
            tempMessage = this->messages.front();
            this->messages.pop();
            locker.unlock();
            for (std::vector<string>::iterator it = this->userNames.begin(); it != this->userNames.end(); ++it)
            {
                tempString = *it;
                tempString += ": ";
                tempString += tempMessage;
                tempString += "\n";
                output << tempString;
            }
        }
        output.close();
    }
    else
    {
        cout << "Error opening file... " << endl;
    }
}

Why is the program handling exception?


Solution

  • One possible error is that you are repeatedly unlocking the mutex in your while-loop, even though the mutex is not locked:

    if (output.is_open())
        {
            std::unique_lock<mutex> locker(mtx, std::defer_lock);
            locker.lock();
            cond.wait(locker);
            while (!(this->messages.empty()))
            {
                tempMessage = this->messages.front();
                this->messages.pop();
                // if multiple messages are in the queue, you unlock multiple times 
                // even though the mutex is not locked
                locker.unlock();   
                for (std::vector<string>::iterator it = this->userNames.begin(); it != this->userNames.end(); ++it)
                {
                    tempString = *it;
                    tempString += ": ";
                    tempString += tempMessage;
                    tempString += "\n";
                    output << tempString;
                }
            }
            output.close();
        }
    

    According to unique_lock::unlock this throws a std::system_error