2011-08-25 28 views
0

自動變量我想繞過線程的一些數據,但要使用全局變量,如果我可以管理它避免。我寫了我的線程程序的方式有一個單獨的函數通過爲每個線程的生命週期中的「相」的用戶:舉例來說,這將是產生線程的典型用法:訪問和修改另一個線程的堆棧

void init_thread(void *arg) { 
    graphics_init(); 
} 
void process_msg_thread(message *msg, void *arg) { 
    if (msg->ID == MESSAGE_DRAW) { 
    graphics_draw(); 
    } 
} 
void cleanup_thread(void *arg) { 
    graphics_cleanup(); 
} 

int main() { 
    threadCreator factory; 
    factory.createThread(init_thread, 0, process_msg_thread, 0, cleanup_thread, 0); 
    // even indexed arguments are the args to be passed into their respective functions 
    // this is why each of those functions must have a fixed function signature is so they can be passed in this way to the factory 
} 

// Behind the scenes: in the newly spawned thread, the first argument given to 
// createThread() is called, then a message pumping loop which will call the third 
// argument is entered. Upon receiving a special exit message via another function 
// of threadCreator, the fifth argument is called. 

的最直接方式要做到這一點是使用全局。我想盡量避免這樣做,因爲它是不好的編程習慣,因爲它會產生混亂。

一定出現問題時,我嘗試稍微改進我的例子:

void init_thread(void *arg) { 
    GLuint tex_handle[50]; // suppose I've got 50 textures to deal with. 
    graphics_init(&tex_handle); // fill up the array with them during graphics init which loads my textures 
} 
void process_msg_thread(message *msg, void *arg) { 
    if (msg->ID == MESSAGE_DRAW) { // this message indicates which texture my thread was told to draw 
    graphics_draw_this_texture(tex_handle[msg->texturehandleindex]); // send back the handle so it knows what to draw 
    } 
} 
void cleanup_thread(void *arg) { 
    graphics_cleanup(); 
} 

我大大簡化這裏的圖形系統的交互,但你明白了吧。在該示例中代碼tex_handle是一個自動可變的,並且init_thread完成時其所有值都被丟失,所以將不提供當process_msg_thread需要引用它。

我可以使用全局解決這個問題,但是這意味着我不能(例如)其中兩個線程同時有,因爲他們將彼此的質感把手名單上踐踏,因爲它們使用相同的一個。

我可以使用線程局部全局,但是是一個好主意?

,我想出了最後一個念頭。我可以在我的父線程的堆中分配存儲空間,併發送一個指向子節點的指針。所以我可以在父線程離開時釋放它,因爲我打算在它退出之前清理它的子線程。所以,這樣的事情:

void init_thread(void *arg) { 
    GLuint *tex_handle = (GLuint*)arg; // my storage space passed as arg 
    graphics_init(tex_handle); 
} 
void process_msg_thread(message *msg, void *arg) { 
    GLuint *tex_handle = (GLuint*)arg; // same thing here 
    if (msg->ID == MESSAGE_DRAW) { 
    graphics_draw_this_texture(tex_handle[msg->texturehandleindex]); 
    } 
} 
int main() { 
    threadCreator factory; 
    GLuint *tex_handle = new GLuint[50]; 
    factory.createThread(init_thread, tex_handle, process_msg_thread, tex_handle, cleanup_thread, 0); 
    // do stuff, wait etc 
    ... 
    delete[] tex_handle; 
} 

這看上去或多或少安全的,因爲我的價值觀去堆,我的主線程分配,然後它可以讓孩子惹它按照自己的意願。由於指針被賦予所有需要訪問的功能,因此孩子們可以自由使用存儲空間。

所以這讓我想到,爲什麼不只是它是一個自動變量:

int main() { 
    threadCreator factory; 
    GLuint tex_handle[50]; 
    factory.createThread(init_thread, &tex_handle, process_msg_thread, &tex_handle, cleanup_thread, 0); 
    // do stuff, wait etc 
    ... 
} // tex_handle automatically cleaned up at this point 

這意味着孩子線程直接訪問父的堆棧。我想知道這是否是猶太教。 我在網上找到了這個:http://software.intel.com/sites/products/documentation/hpc/inspectorxe/en-us/win/ug_docs/olh/common/Problem_Type__Potential_Privacy_Infringement.htm

看來英特爾Inspector XE檢測到這種行爲。所以也許我不應該這樣做?這是否僅僅是URL的建議中對隱私侵權的警告,還是可能出現的其他潛在問題,我不知道?

P.S.在思考完所有這些之後,我意識到也許這種將線程分解爲一堆獨立調用的函數的架構並不是一個好主意。我的意圖是消除爲產生的每個線程編寫消息處理循環的複雜性。我曾預料到可能存在的問題,如果我有一個總是檢查消息的線程實現(比如我的自定義線程將被終止),那麼我可以保證一些未來的用戶不會意外忘記檢查這個條件在他們的每個消息循環中。

我的解決方案的問題是,這些單獨的功能現在是分開的,不能相互通信。他們可能只能通過全局變量和線程本地全局變量來實現。我猜想線程本地全局變量可能是我最好的選擇。

P.P.S.這讓我想起了RAII以及線程的概念,至少如我最終表示的那樣,它與資源有一定的相似性。也許我可以建立一個比傳統方式更自然地表現線程的對象......不知何故。我想我會去睡覺。

回答

2

將你的線程函數放到一個類中。然後他們可以使用實例變量進行通信這要求您的線程工廠進行更改,但是解決您的問題的最簡單方法。

只要您可以保證堆棧框架包含數據的函數在您的子線程退出之前永遠不會返回,您的使用自動變量的想法也將起作用。這並不容易實現,即使main()返回子線程仍然可以運行。