2013-04-17 50 views
2

我正在用兩個線程編寫一個C++應用程序。線程A將消息發送到線程B的消息類型可以是:在線程和內存管理之間傳遞消息

struct MyMessageType 
{ 
    int a; 
    enum MyEnum b; 
    bool someFlag; 
} 

std::queue<MyMessageType> messageQueue在線程之間共享用於傳遞消息。

在發送線程,我會碰到這樣的:

struct MyMessageType newMessage; 
newMessage.a = 14; 
newMessage.b = someEnumeratedValue; 
newMessage.someFlag = false; 
GrabTheMutexProtectingTheQueue(); 
messageQueue.push(newMessage); 
ReleaseTheMutexProtectingTheQueue(); 

我的問題是關於內存管理,是雙重的:

A)如何確保指針newMessage是接收線程獲取消息時有效嗎?例如,如果創建newMessage結束的函數和newMessage因此在接收線程處理消息之前超出了範圍,會發生什麼情況?

B)一旦我能確保newMessage指針在接收線程處理它時有效,如何釋放結構使用的內存?

+1

C中沒有'std :: queue'也許你的意思是C++? – paxdiablo

回答

7

std::queuepush()功能存儲複製不管你給它(見here,所以你不必擔心它走出去的範圍。

隊列中的副本將一直存在,直到用pop()將其刪除。

因此,在發送端,它是(例如)一個簡單的問題:

lock_mutex(); 
myqueue.push (something); 
unlock_mutex(); 
// Do whatever you want with something, the queue has a copy 

,並在接收端:

lock_mutex(); 
while (myqueue.empty()) { 
    unlock_mutex(); 
    // possibly yield to another thread 
    lock_mutex(); 
} 
something = myqueue.front(); 
weaveMagicWith (something); 
myqueue.pop(); 
unlock_mutex(); 

當然,你也可以重新設計爲了最大限度地減少接收端互斥鎖的持續時間(例如,如果編織魔法需要很長時間),這只是一個粗略的例子,展示了一種實現方法。

+0

+1是的。消息太小時,使用指針類型作爲模板參數沒有意義。指針類型僅在消息較大時纔有用(例如,磁盤/網絡緩衝區)。 –

+0

如果weaveMagicWith()可能需要一些時間,最好在釋放互斥體後執行。 front()調用創建了另一個數據副本,因此在weaveMagicWith()之前調用pop()是安全的。 –

+0

對嗎,@ brian?文檔聲明它返回對隊列中第一項的引用。這不是一個副本,是嗎?這也得到了MS文檔的支持:「如果front的返回值分配給引用,則可以修改隊列對象」。 – paxdiablo

相關問題