2012-01-08 44 views
1

我有一個情況,我有一個發射器對象和一組接收器。接收器屬於同一類,實際上代表了一組相同類型的設備。我正在使用Qt框架。動態地向一個對象發射信號

  • 發射器本身首先獲取信號,從其中一個設備獲取信息。

  • 在相應的插槽中,發射器必須檢查哪些接收器已準備就緒,然後發送自己的信號以請求數據到其中一個設備(以先準備好的爲準)。

發射器接收信號的速度非常快,大約爲幾毫秒。有三種方法我可以考慮只從其中一個設備安全地請求數據(這些設備存在於它們自己的線程中,所以我需要一個線程安全的機制)。設備數量不是靜態的,可以改變。設備總數很少(絕對在5-6之下)。

1)連接到所有設備時,他們被添加或刪除。發出一個請求並讓設備對象自己過濾出請求是否使用某個特定的設備標籤。這種方法很好,因爲發生檢查的請求位置將在專用線程的上下文中執行,但隨着設備數量的增加而浪費。

2)當需要發送請求時,在發射器中動態連接和斷開連接。

3)當需要發送請求時,使用QMetaObject :: invokeMethod()。

表現很重要。有誰知道哪種方法是「最好的」,或者是否有更好的方法?

問候

的PRI

注:爲了澄清:從發射器應用程序獲取的信號,通過查詢設備以獲取信息。瘋狂的ASCII藝術去:

(APP)< ---->(發射器)< ------>(接收器)< - | - >物理設備

回答

0

根據這些信息,你提供了我仍然會推薦的Reactor實現。如果你不使用ACE,那麼你可以實現你自己的。基本架構如下:

  1. 使用select當從應用程序接收到信號或數據時喚醒。
  2. 如果有一個插座準備發送列表上,則你隨便挑一個,並將其發送數據
  3. 當數據發送Receiver從設置插座/可用
  4. 在處理數據處理程序的刪除自身Reciever將自己重新註冊到可用收件人列表。

我建議ACE的原因是因爲它具有最簡單的Reactor模式實現之一。

+0

我的問題措辭嚴重,並更新它來澄清一點。 1)是的,但現在我只關心從應用程序到接收器的信號流。 2)接收器是相同的,但不共享數據。 ACE好像對此可能是過度的。 – Prismatic 2012-01-09 00:05:18

+0

@Pris Reactor即使不與'ACE'一起工作,我仍在調整答案。 – Karlson 2012-01-09 00:32:18

0

我很喜歡這裏是多線程環境。

如果是,那麼答案爲您的具體問題之間僅限於Qt的信號/槽系統:

1)絕對不是要走的路。在從Emitter發出的事件中,等於Receivers的事件總數將排隊等待設備的線程事件循環,則一旦線程到達那些事件,就會發生相同數量的時隙調用。即使大部分在第一行中丟失的只是if(id!=m_id) return;,但它在Qt的核心中仍然有很多事情發生。在您的一個插槽中放置一個由Qt::QueuedConnection信號引發的斷點,然後通過查看實際堆棧跟蹤來驗證此斷點。從xyEventLoop::processEvents(...)來看,它通常至少有4次來電,所以「剛回來」在時間上絕對不是「免費」的。 2)不確定Qt的內部實現是如何實現的,但是從我所知的連接和斷開連接中,很可能包括將發送者和接收者插入和刪除某些列表,這些列表最有可能通過QMutex鎖定進行訪問。 - 也可能在時間上是「昂貴的」,並且快速連接和斷開絕對不是最佳實踐。

3)可能是至少「昂貴的時間明智」的解決方案,你可以發現,仍然使用Qt的singnal插槽系統。可選)QSignalMapper。它的設計完全符合您在選項1)中的計劃。

有更優化的解決方案您EmitterReceivers之間的溝通,但我會首先選擇最易於使用和快速的執行選項最好的做法,但有足夠快,運行 - 一個機會時間(即選項3)。 )。然後,完成後,看看它是否符合您的性能要求。如果沒有,並且只有這樣,才考慮在數據提供者中使用共享內存和數據提供者互斥體 - 數據使用者體系結構(Emitter線程在循環列表中快速發佈請求數據,而Receiver線程只要有時間就讀取它們,然後發佈結果回到了類似的方式,而Emitter線程不斷調查已完成的結果。)