0

我正在围绕 win32 线程和 pthreads 做一个包装类,其风格类似于 c++11 线程 api。我的问题是关于在实际线程退出时更新线程对象实例。以下是我的解决方案,但我不确定它是否安全。

/* Thread wrapper class */
    class Thread
    {
    public:
        enum ThreadState
        {
            DETACHED = 0,
            RUNNING
        };

        Thread();
        Thread(void* (*start) (void*), void* arg);
        ~Thread();

        Thread& operator=(Thread& other);
        void Join();
        int32_t SetPriority(int32_t priority);
        void Detach();
        ThreadHandle GetNativeHandle();
        ThreadState GetThreadState();

    private:
        ThreadHandle mHandle;
        ThreadState mState;
        void* (*mFunctionPointer) (void*);
        void* mArg;

        static void* Run(void* arg);
        ThreadHandle _CreateThread(void* (*start) (void*), void* arg);
        void _JoinThread(ThreadHandle& handle);

    };

第二个构造函数启动一个线程。这是实现:

    Thread::Thread(void* (*start) (void*), void* arg)
    {
        mFunctionPointer = start;
        mArg = arg;
        mState = Thread::RUNNING;

        mHandle = _CreateThread(&Run, (void*)this);
        if (!mHandle)
            mState = Thread::DETACHED;
    }

它创建一个运行 Run 方法的线程,并传递一个指向该对象实例的指针。原因是一旦线程执行了函数,它就会将状态设置为 DETACHED 以表示它已完成。

这是运行方法

    void* Thread::Run(void* arg)
    {
        Thread* thread = static_cast<Thread*>(arg);

        if (thread && thread->mFunctionPointer && thread->mArg && thread->mState == Thread::RUNNING)
            thread->mFunctionPointer(thread->mArg);

        if (thread && thread->mFunctionPointer && thread->mArg && thread->mState == Thread::RUNNING)
            thread->Detach();

        return NULL;
    }

这也是 Detach(),它也在线程析构函数中调用:

    void Thread::Detach()
    {
        mState = Thread::DETACHED;
        mHandle = NULL;
        mArg = NULL;
        mFunctionPointer = NULL;
    }

我觉得这根本不安全。例如,如果 Thread 对象是在堆栈上构造的,并且在其线程运行时超出范围。Thread 对象析构函数将其状态和数据成员设为 NULL,但内存位置可能会被覆盖,不是吗?

有什么好的方法可以解决这个问题吗?

谢谢

4

1 回答 1

1

如果 Thread 实例超出范围而之前没有加入线程,那么你注定要失败。使 Run() 成为一个免费或静态函数并复制所有数据,该函数需要运行到动态分配的内存中并让 Run() 释放该内存。

在 Run() 中不需要进行如此多的测试。由于您的 c'tor 参数已经与 CreateThread() 兼容,只需将函数和参数传递给 CreateThread 就可以了。

亲切的问候

托尔斯滕

于 2012-07-16T15:54:10.183 回答