我執行,超過一個USB設備會談到電機控制器的類。除了用於指示通過通信鏈接獲取的參數是否爲「新鮮」的方法之外,我已經做了所有工作。我有什麼至今:實現通信超時
class MyCommClass
{
public:
bool getSpeed(double *speed);
private:
void rxThread();
struct MsgBase
{ /* .. */ };
struct Msg1 : public MsgBase
{ /* .. */ };
struct Msg2 : public MsgBase
{ /* .. */ };
/* .. */
struct MsgN : public MsgBase
{ /* .. */ };
Msg1 msg1;
Msg2 msg2;
/* .. */
MsgN msgn;
std::map< unsigned long id, MsgBase *msg > messages;
};
rxThead()
是在一個單獨的線程檢查是否有可用的消息的USB設備運行的無限循環。每個消息具有rxThread()
用來它粘成右msgx
對象的唯一標識符。我需要的是當用戶調用getSpeed()
功能,它需要能夠告訴當前速度值是否爲「鮮」或「失效」,即包含速度值的msgx
對象是否在指定的超時期限內更新。所以每個消息對象都需要實現自己的超時(因爲它們根據消息而不同)。
所有消息由電機控制器定期發送的,但也有一些想要獲取其內容改變傳輸(但他們也將定期,如果內容不改變發送)。這意味着以超過標稱速率接收消息是可以的,但它應該在最大超時時間內至少出現一次。
的USB設備提供時間戳與消息一起,所以我有機會獲得這些信息。時間戳不反映當前時間,它是一個unsigned long
數字,分辨率爲微秒,設備每次收到消息時都會更新。我懷疑該設備從我調用其初始化函數的時間開始,從0
開始遞增。一對夫婦不同的方式我能想到實現這個的是:
每個報文對象啓動運行無限等待(WaitForSingleObject的)的超時時間的線程。在超時之後,它檢查一個計數器變量(在等待之前被緩存了)是否增加了。如果不是,它將標記該消息的標誌設置爲陳舊。每次
rxThread()
更新該消息對象時,計數器都會遞增。rxThread()
除填充消息外,還遍歷消息列表並檢查每個消息的最後一次更新的時間戳。如果時間戳超過超時時間,則將該消息標記爲陳舊。此方法可能會遇到所需處理量的問題。在大多數機器上它可能不會成爲問題,但是這些代碼需要在一臺速度很慢的「工業計算機」上運行。
我真的很感激你的想法和建議,如何實現這一點。除了我剛纔提到的兩個之外,我都接受了其他想法。我使用的是Visual Studio 2005,因爲USB設備驅動程序僅適用於Windows,所以跨平臺可移植性不是什麼大問題。目前我正在監控大約8條消息,但如果解決方案足夠輕便,我可以添加多個(也許是另外8個)更多,而不會遇到處理馬力限制的情況,那將會很不錯。
在此先感謝, Ashish。
時間戳不是當前時間,它只是一個具有微秒分辨率的'unsigned long'計數器,它將繼續滾動。因此,確定超時的唯一方法是取兩個時間戳的差值或緩存現有時間戳,然後等待超時期限並查看時間戳是否已更新。 'getSpeed()'本身並不是週期性的調用,所以它不知道消息什麼時候通過查看時間戳數字來更新。我會用時間戳的詳細信息更新描述。 – Praetorian 2010-09-29 02:36:34
您可以根據收到的值存儲自己的時間戳。這與您的第二個實現想法的工作方式大致相同。 – Hasturkun 2010-09-29 02:47:49
@ Hasturkun在那裏有個好主意。我只在消息上存儲自己的時間戳,然後在'getSpeed()'中檢查'now - timestamp'。注意:如果你的超時值需要很小和/或精確,實現可能會很費力。在Windows下可以依賴的最佳精度是按照gettickcount()〜〜16ms(因爲QueryPerformanceCounter通常遭受核心錯誤同步問題,MS責備BIOS/HAL實現者,可能容易上百或上千毫秒)。 – 2010-09-29 04:10:26