2017-08-08 65 views
1

通常如果我想模擬一些工作或等待確切的時間間隔,我使用condition_variable::wait_for或最差的thread::this_thread::sleep_for。但是condition_variabledocumentation指出wait_forwait_until方法可能會阻止比請求更長的時間。如何保證確切的線程睡眠間隔?

該功能可能會阻塞更長比timeout_duration由於調度或者資源爭用延遲。

確切的等待間隔可以保證多少?

UPDATE

我能達到它沒有condition_variable

+4

標準C++沒有這樣的功能。很可能,您的操作系統也不是。 –

+0

所以你可以做的最接近的事情就是讓自己的函數爲大增量睡1秒或更大,然後輪詢等待正確的返回時間,但它會相當混亂和低效 –

+0

@GradyPlayer:爲什麼是你選擇任意1秒?在具有較高優先級任務的繁忙系統上,它可能爲1000秒,在未使用的系統上可能沒有開銷。 – MSalters

回答

6

你不能這樣做。

爲了有這樣的確切保證,你需要一個實時操作系統。

C++並不保證您在實時操作系統上。

因此,它提供了典型的非RTOS提供的保證。

請注意,在RTOS上進行編程還有其他複雜性,遠遠超出了這個問題的範圍。

實際上,有一點當人們真的需要細粒度的時序控制時(比如說,他們在每幀或每行掃描線緩衝器等或音頻緩衝器或其他什麼的時候)都會檢查if時間很短,如果是這樣,等待。如果時間更長,他們會等待比他們想等待的時間少一點,然後醒來並旋轉。

這也不能保證可以正常工作,但對於幾乎所有情況都可以很好地工作。

在RTOS上,平臺可以提供您想要的基元。這些超出了標準C++的範圍。沒有典型的桌面操作系統是我知道的RTOS。如果您正在爲戰鬥機的控制硬件或類似設備編程,那麼您可能正在使用RTOS進行編程。

我希望你不是寫戰鬥機控制軟件,並在堆棧溢出問這個問題。

+0

好的答案,喜歡最後一行。 – Annabelle

+0

@Yakk更糟的是更糟糕。撰寫戰鬥機控制軟件的人要我回答一個問題。 – Viktor

0

如果您確實在某個確切的持續時間內進行了假設睡眠,然後執行了一些響應操作(例如獲取當前時間或將消息打印到屏幕上),那麼該操作可能會延遲某個未知的時間段時間例如由於處理器負載。這相當於立即發生(幾乎)發生的行爲,但計時器花費的時間比預期的要長。即使在最好的情況下,定時器完全按照您的請求時間完成,並且操作系統允許您的操作在不搶佔進程的情況下完成,但執行該操作需要幾個時鐘週期。換句話說,在一個標準的操作系統中,定時器完全按照要求的時間完成是不可能的或者甚至是沒有意義的。

這怎麼能克服?學術上的答案是,您可以使用專用軟件和硬件,例如實時操作系統,但這比開發常規編程軟件要複雜得多。在一般情況下,你可能真正想知道的是,文件所指的延遲並不大,即通常小於1/100秒。

0

憑藉蠻力循環...例如:

chrono::microseconds sleep_duration{1000}; 

auto now = chrono::high_resolution_clock::now() 

while(true) 
{ 
    auto elapsed = chrono::duration_cast<hrono::microseconds>(chrono::high_resolution_clock::now() - now); 
    if (elapsed > sleep_duration) 
     break; 
} 

這是如此,你不能有這樣的精確度有點難看,但桌面操作系統不是實時的。

爲了放鬆你看看下面的代碼片段的CPU:

void little_sleep(std::chrono::microseconds us) 
{ 
    auto start = std::chrono::high_resolution_clock::now(); 
    auto end = start + us; 
    do { 
     std::this_thread::yield(); 
    } while (std::chrono::high_resolution_clock::now() < end); 
} 
+0

謝謝。但請注意,'std :: chrono :: high_resolution_clock'只是一個別名。檢查[這裏](http://en.cppreference.com/w/cpp/chrono/high_resolution_clock)。 – Viktor

+0

這是真的,在ubuntu 16.04上它是'system_clock'的別名。如果時鐘精度不夠,請使用特定於操作系統的調用 –

+0

這並不能保證精確的「睡眠」。先發制人的操作系統可以讓你的線程隨時進入睡眠狀態(甚至在執行你的等待循環時)。所以你需要做一些事情來防止它(線程的RTOS或合作調度程序(沒有收益)或RT優先級等)。) – geza

0

這就要看你能期待什麼精度。一般來說,正如其他人所說的正常操作系統(Linux,Windows)不能保證。

爲什麼?
你的操作系統可能有線程的概念。如果是這樣,那麼就有一個調度程序,它會中斷線程並將執行切換到等待隊列中的其他線程。這可能會破壞定時器的準確性。

我該怎麼辦?

  1. 如果您使用的是嵌入式系統 - 去裸機,即不使用 OS或使用所謂的硬實時操作系統。
  2. 如果您使用的是Linux,請在Google中查找Linux RT搶佔補丁程序。你必須重新編譯你的內核以包含路徑(儘管不那麼複雜),然後你可以創建高於50的線程 - 這意味着優先於內核的線程 - 這最終意味着你可以有一個線程可以中斷調度程序和內核一般,提供相當好的時間精度。在我的情況下,它是三個數量級(從幾毫秒的延遲到少數我們)。
  3. 如果您使用的是Windows,我不知道有關此修補程序,但您可以在Microsoft網站上搜索High Precisions計時器。也許提供的準確性將足夠滿足您的需求。