Delete an object securely from a multi-threaded program

我是研究僧i 提交于 2019-12-04 21:40:28

What is missing here is the condition that dictates when thread processing is completed. Deletion of a particular object instance is not a good condition. You havent shown us where the object is deleted. If we could see this in the code, the extra context would be helpful.

What I would suggest is instead of deleting the object, set a flag on the object (bool active() for example). This flag will then be checked by all threads, and when it indicates stop processing, then the threads will stop. Set this flag where you are currently deleting the Foo object. Then once all threads have stopped, delete the Foo object.

If you delete the object and expect to be able to acquire its mutex lock, you will possibly get a crash, or at the least unstable behavior, since the mutex is a member of Foo, and it will be destroyed with the object.

Here's an example of what I mean:

class Foo
{
    public:
        void lockMutex();
        void unlockMutex();
        // Active should be mutex protected as well
        // Or you could consider using a pthread_rwlock
        bool active() {return active_;}
        void setActive(bool a) {active_ = a;}
    private:
        pthread_mutex_t mutex;
        bool active_;
};

void* thread ( void* fooPtr )
{
    Foo* fooPointer = (Foo*) fooPtr;

    while ( 1 )
    {
        if ( fooPointer->active() )
        {
            fooPointer->lockMutex();
            /* some code, involving fooPointer */
            fooPointer->unlockMutex();
        }
        else
        {
            pthread_exit ( NULL );
        }
    }

    // somewhere else in the code
    fooPointer->setActive(false);
}

Foo::setActive(true) must be called either in the constructor, or when the object is created. And the Foo object should be deleted once the threads stop, most likely after pthread_join() has completed.

Let's start with the begin of your question:

I've a program, in which I create an instance of Foo and I operate with it in a number of threads. Then I want to delete it securely so those threads do not fall into a segmentation fault.

You cannot delete an object which is in use. No amount of mutexes will fix that.

I've added a destructor to Foo

This is only run when Foo is being deleted. Its contents don't matter much, though: It's wrong to call the dtor while other threads are still using Foo.

I want a thread securely exit when an instance is deleted. How is it possible?

Well, that's the correct question. I could write a whole lot of code for you to use, but that code would just be a copy of boost::weak_ptr. So, I won't bother. Just take the boost code yourself.

Boost not allowed.

Then why are you asking on StackOverflow? That's essentially the same license.

your code posted is not right because c++ object is destroyed by steps blow:

obj->Foo::~Foo();

free memory //maybe delete if allocated by new

so your source is only protoecting the destructor but not the memory free itself.

maybe source code follows could help you, it's simple and crude but I think it can works

    class Foo 
    {

       public:
         void dosomething() {}
    };

    template<typename T>
    class Protect
    {   
    public: 
        struct auto_lock {
            auto_lock(pthread_mutex_t& mutex)
                : _mutex(mutex)
            {
                pthread_mutex_lock ( &_mutex );
            }
            ~ auto_lock() 
            {
                pthread_mutex_unlock ( &_mutex );
            }
            pthread_mutex_t& _mutex;
        };

        Protect(T*& p): _p(p) {}
        T* get() { return _p; }

        void lock() { pthread_mutex_lock ( &_mutex ); }
        void unlock() { pthread_mutex_unlock ( &_mutex );}
        pthread_mutex_t& getlock() { return _mutex; }

        void safe_release() { 
            auto_lock l(_mutex);
            if (_p != NULL)  {
                delete _p;
                _p = NULL;
            }
        }
    private:
        T*& _p;
        pthread_mutex_t _mutex;
    };

void* thread ( void* proPtr )
{
    Protect<Foo>* proPointer = (Protect<Foo>*) proPtr;

    while ( 1 )
    {
        Protect<Foo>::auto_lock l(proPointer->getlock());
        Foo* fooPtr = proPointer->get();
        if ( fooPtr )
        {
            fooPtr->dosomething();
        }
        else
        {
            pthread_exit ( NULL );
        }
    }
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!