2012-07-16 49 views
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; 
    } 

它創建一個運行運行方式,沿着一個指向這個對象實例通過一個線程。原因是一旦線程執行了它將狀態設置爲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; 
    } 

而且這是分離(),它也被稱爲上線的析構函數:

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

我喜歡這種感覺是不是安全的。例如,如果線程對象在堆棧上構建並在其線程運行時超出範圍。 Thread對象析構函數將其狀態和數據成員設爲NULL,但內存位置可能會被覆蓋否?

有沒有解決這個問題的好辦法?

感謝

+1

FYI,Boost.Thread(http://www.boost.org/doc/libs/release/doc/html/thread.html)是周圍的win32的包裝和並行線程。在最新版本的Boost(1.50)中,進行了更改,以便API與C++ 11的「std :: thead」相匹配。 – 2012-07-16 16:48:48

+1

我快速搜索了幾個C++ 11 std :: thread頁面。兩者都以使用Thread-> join()的例子開始。這就像Deja vu重新:創建/終止/加入廣告的噁心。 Delphi,Java,C#和現在的C++ 11 - 同樣的舊垃圾。標準委員會的成員是否曾經寫過任何不平凡的多線程軟件?爲什麼開發人員趕上join()?什麼教科書/網頁作者負責?生活時間的應用程序線程和線程池,很好,所以我們得到什麼:'join()'無論如何,祝你好運 - 你將需要它:) – 2012-07-16 18:00:59

回答

1

你註定,如果線程實例超出範圍,而不線程之前被連接。使Run()成爲一個自由或靜態函數並複製所有數據,該函數需要運行到動態分配的內存中並讓Run()釋放該內存。

在Run()中沒有必要進行太多的測試。由於您的c'tor參數已經與CreateThread()兼容,只需將函數和參數傳遞給CreateThread即可,您應該沒問題。

親切的問候

的Torsten

+0

如果對象會執行Join()(如果活動線程)在析構函數,那麼它會被認爲是安全的嗎? – KaiserJohaan 2012-07-16 16:10:30

+0

@KaiserJohaan當然,線程,調用d'或將阻塞,直到Run()函數完成。但是你通常不想讓代碼加入該線程,因爲你可能希望有多個Thread對象指向同一個真正的執行線程。如果您的Thread類不可複製,則無法將Thread對象存儲在容器中。 – 2012-07-16 16:47:24

+0

@TorstenRobitzki'可能想要多個Thread對象指向同一個真正的執行線程' - 我保留永不這樣做的權利:)同樣在堆棧上構建線程對象。同樣使用任何不是指針類型的容器,因此需要任何種類的「真實」拷貝來加載它。 'myContainer '不好,'myContainer <*Thread>不錯:)。我不明白爲什麼有人會嘗試在另一個線程堆棧上創建一個線程對象 - 這是將RAII轉換爲多線程的一種嘗試,因爲除了這樣做之外,我什麼也看不到。 – 2012-07-16 17:43:16