0

If I reference an object in the secondary thread B* b and one data members of this object is modying through the principal thread (write) , should I protect only the data or the whole object b ?

I precise I'm just refering the whole object not reading the shared data (here _x), suppose that after referring it I'll send it to another class and inside it I'll read _x. I need to protect my data where I'm reading it ?

If getB() return a validate object. then the b removed from the principal thread (where b was created) I find my self with a dangling pointer B* b in the secondry thread ?

   class B{
        public:
        B(){}
        void setX(int x){
            // here I lock to protect _x
            _x = x;
        }
        int getX(){
            // here I lock to protect _x
            return _x;
        }
        private:
        int _x = 0;
    };

    class A{
        public:
        A(B* b)
        : _b(b)
        {}

        B* getB(){
            return _b;
        }

        private:
        B* _b;
    };

    class thread{
        public:
        thread(A* a)
        : _a(a)
        {}
    
    void threadMain(){
        // this is the secondry thread
        B* b = _a->getB(); // // it is fine to not protect inside getB() ?
        // pass b to another class .. C* c = new c(b...) .. c will 
        // read _x via b and I'll use mutex there (getX())
    }

    std::thread member1Thread() {
        return std::thread([=] { threadMain(); });
    }

        private:
        A* _a;
    };


    int main(){ 
            // this is the principal thread
            B* b = new B();
            A a(b);
            thread th(&a);
            std::thread thread(th.member1Thread());
            a.getB()->setX(100);
            // what if this thread delete b after _a->getB() gave a significant object --> B* b will be dangling pointer ?
        return 0;
    }
DoctorX
  • 73
  • 4
  • 2
    What is the ownership of `b`? Currently no one manages it in any way, so who `delete`s `b` and when is not defined. Answer this question and all of your worries of `b` dangling will be resolvable. – user4581301 Jan 12 '22 at 18:13
  • @user4581301 suppose that main (principal thread) will delete `b` (principal ans second thread operate in parallel so I can't say when). cuz b may be delete after `getB()` gave a significant object inside secondry thread. should I protect the object or its shared data `_x` ? – DoctorX Jan 12 '22 at 18:20
  • Locking in the `getB` function only prevents two threads from getting the pointer at the same time. Once each thread has the pointer, they can use it simultaneously with no restrictions, and that's where the damage will be done. You've done the right thing protecting in `setX` and `getX` and not `getB` (unless you have a mechanism that allows `_b` to be changed). – user4581301 Jan 12 '22 at 18:22
  • The best way to prevent the destruction of `b` while secondary thread is running is to join the secondary thread before main thread, or anyone else, is allowed to destroy `b`. If you need a more free-form approach, use `std::shared_ptr` to share ownership. The last owner of the `shared_ptr `deletes `b` when it goes out of scope. – user4581301 Jan 12 '22 at 18:31
  • yes me first I thought in this way but imagine with me this situation. `*b` will point to the object `b` via the second thread and just after the main thread drops and delete the object for the class C is a meaningful object and if I call one of these methods right after its creation -> undefined behavior since `*b` is no longer significant – DoctorX Jan 12 '22 at 18:34
  • Aside note. Try not to start your variable names/defines/etc with an underscore; use `x_` for private member names instead of `_x`: https://stackoverflow.com/questions/228783/what-are-the-rules-about-using-an-underscore-in-a-c-identifier – rturrado Jan 12 '22 at 18:35
  • Note that if secondary thread is still running when `main` exits, `thread` goes out of scope [and deliberately aborts](https://en.cppreference.com/w/cpp/thread/thread/~thread). If you `detach` `thread` to allow it to continue running after the program exits, you're headed into a weird territory that usually ends with the hard termination of the thread.. – user4581301 Jan 12 '22 at 18:35
  • Yes, bad things will happen if you allow `b` to be destroyed when anyone is still using it and there's nothing that can prevent this from happening except you. It's the job of the programmer to establish ownership and ensure the owner does not allow `b` to be prematurely terminated. The easiest way to do this is with [RAII](https://stackoverflow.com/questions/2321511/what-is-meant-by-resource-acquisition-is-initialization-raii), a smart pointer for example, and making sure the owner has a wider scope than the `std::thread` instance that owns secondary thread. – user4581301 Jan 12 '22 at 18:41
  • Without establishing the ownership of `b` in your question (see comment 1), you have an open-ended "What if?" style question that is not well-suited to Stack Overflow and can only really be answered with, establish ownership of `b` and don't let `b` get prematurely destroyed, an obvious and useless answer. – user4581301 Jan 12 '22 at 18:44

0 Answers0