jeudi 25 janvier 2018

Confusion about thread-safety

I am new to the world of concurrency but from what I have read I understand the program below to be undefined in its execution. If I understand correctly this is not threadsafe as I am concurrently reading/writing both the shared_ptr and the counter variable in non-atomic ways.

#include <string>
#include <memory>
#include <thread>
#include <chrono>
#include <iostream>


struct Inner {
    Inner() {
        t_ = std::thread([this]() {
            counter_ = 0;
            running_ = true;
            while (running_) {
                counter_++;
                std::this_thread::sleep_for(std::chrono::milliseconds(10));
            }
        });
    }

    ~Inner() {
        running_ = false;
        if (t_.joinable()) {
            t_.join();
        }
    }


    std::uint64_t counter_;
    std::thread t_;
    bool running_;
};


struct Middle {

    Middle() {
        data_.reset(new Inner);
        t_ = std::thread([this]() {
            running_ = true;
            while (running_) {
                data_.reset(new Inner());
                std::this_thread::sleep_for(std::chrono::milliseconds(1000));
            }
        });
    }

    ~Middle() {
        running_ = false;
        if (t_.joinable()) {
            t_.join();
        }
    }

    std::uint64_t inner_data() {
        return data_->counter_;
    }

    std::shared_ptr<Inner> data_;
    std::thread t_;
    bool running_;
};

struct Outer {

    std::uint64_t data() {
        return middle_.inner_data();
    }

    Middle middle_;
};




int main() {

    Outer o;
    while (true) {
        std::cout << "Data: " << o.data() << std::endl;
    }

    return 0;
}

My confusion comes from this:

  1. Is the access to data_->counter safe in Middle::inner_data?
  2. If thread A has a member shared_ptr<T> sp and decides to update it while thread B does shared_ptr<T> sp = A::sp will the copy and destruction be threadsafe? Or do I risk the copy failing because the object is in the process of being destroyed.

Under what circumstances (can I check this with some tool?) is undefined likely to mean std::terminate? I suspect something like the above happens in some of my production code but I cannot be certain as I am confused about 1 and 2 but this small program has been running for days since I wrote it and nothing happens.

Code can be checked here at https://godbolt.org/g/saHz94

Aucun commentaire:

Enregistrer un commentaire