0

c++11 スレッド API に似たスタイルで、win32 スレッドと pthreads のラッパー クラスを作成しています。私の問題は、実際のスレッドが終了したときにスレッド オブジェクト インスタンスを更新することに関するものです。以下は私が持っている解決策ですが、安全かどうかはわかりません。

/* 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);

    };

2 番目のコンストラクターは、スレッドを開始します。実装は次のとおりです。

    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 に答える