我想實作等待某些事件并在延遲后處理它們的演算法。每個事件都有它自己的預定義延遲。處理程式可以在單獨的執行緒中執行。CPU 節流、主機過載等問題可能會被忽略——它并非旨在成為一個精確的實時系統。
例子。
- 在時刻 N 到達一個延遲 1 秒的事件。我們想在 N 1 秒的時刻處理它。
- 在 N 0.5 秒時刻到達另一個延遲 0.3 秒的事件。我們想在 N 0.8 秒的時刻處理它。
方法。
我想到的唯一直接的方法是在迭代之間使用盡可能延遲最小的回圈,例如每 10 毫秒,并檢查是否現在應該處理時間線上的任何事件。但這不是一個好主意,因為延遲可能從 10 毫秒到 10 分鐘不等。
另一種方法是讓一個執行緒在事件之間休眠。但是我不知道如何在現在和下一次預定喚醒之間有一個新事件需要處理時如何強制“喚醒”它。
也可以為每個事件使用一個執行緒并且只是休眠,但是可能有數千個同時發生的事件,這實際上可能導致執行緒用完。
該解決方案可以與語言無關,但我更喜歡 C STD 庫解決方案。
uj5u.com熱心網友回復:
另一種方法是讓一個執行緒在事件之間休眠。但是我不知道如何在現在和下一次預定喚醒之間有一個新事件需要處理時如何強制“喚醒”它。
我想這些問題的解決方案是,至少在 *nix 系統上,在timer的幫助下poll或epoll。它允許你讓執行緒休眠直到某個給定的事件。給定的事件可能是某些東西出現或計時器超時。由于問題是關于演算法的一般演算法/想法,并且代碼會占用大量空間,因此我只給出偽代碼:stdin
epoll = create_epoll();
timers = vector<timer>{};
while(true) {
event = epoll.wait_for_event(timers);
if (event.is_timer_timeout()) {
t = timers.find_timed_out();
t.handle_event();
timers.erase(t);
} else if (event.is_incoming_stdin_data()) {
data = stdin.read();
timers.push_back(create_timer(data));
}
}
uj5u.com熱心網友回復:
共享優先級佇列的兩個執行緒。
到達執行緒:等待到達。當事件到達時計算處理程式運行的時間。將處理程式添加到具有處理程式時間優先級的佇列(佇列頂部將是下一個要處理的事件
處理程式執行緒:現在等于佇列頂部處理程式的時間,然后運行處理程式。睡眠以獲得時鐘解析度。
注意:檢查您的佇列是否是執行緒安全的。如果沒有,那么您將不得不使用互斥鎖。
這看起來很簡單,但是有很多陷阱等待沒有經驗的人。所以,我不建議從頭開始編碼。最好使用圖書館。經典是 boost::asio。然而,這開始顯示它的年齡,并且有比需要的更多的花里胡哨。所以,就個人而言,我使用了更輕量級的東西,并且用 C 17 編碼https://github.com/JamesBremner/await
這是一個演示應用程式,展示了它如何解決這個問題。此演示的事件來自鍵盤,格式為 testd4000,這意味著名為“test”的事件應在 4000 毫秒后運行。處理程式只是列印出事件的名稱
#include "await.h"
raven::await::cAwait waiter;
class cCIN
{
public:
static std::string myString;
std::string myPrompt;
void operator()()
{
std::cout << myPrompt;
std::cin >> myString;
}
};
std::string cCIN::myString;
cCIN theCIN;
class cTimer
{
public:
int myDelaymsecs;
bool myfree;
cTimer()
: myfree(true)
{
}
void operator()()
{
myfree = false;
std::this_thread::sleep_for(
std::chrono::milliseconds(myDelaymsecs));
myfree = true;
}
};
// construct pool of 10 timers
std::vector<cTimer> theTimers(10);
// handle some keyboard input
void cinHandler()
{
// check for stop request
if (theCIN.myString == "stop")
{
waiter.stop();
return;
}
// display input
//std::cout << "input: " << theCIN.myString << std::endl;
int p = theCIN.myString.find("d");
auto name = theCIN.myString.substr(0, p);
// set timer fromm pool for requested delay
bool timerfound = false;
for (auto &t : theTimers)
{
if (t.myfree)
{
t.myDelaymsecs = atoi(theCIN.myString.substr(p 1).c_str());
waiter(t,
[name]
{
std::cout << "\n"
<< name << " handler running\n";
});
timerfound = true;
break;
}
}
if( ! timerfound )
{
std::cout << "Sorry, timer pool exhausted\n";
exit(1);
}
// wait for more input
waiter(theCIN, cinHandler);
}
int main()
{
theCIN.myPrompt = "enter event name and delay e.g. \"testd4000\"";
waiter(theCIN, cinHandler);
waiter.run();
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/421211.html
標籤:
上一篇:為什么std::basic_string_view有兩個相等比較運算子?
下一篇:如何將陣列傳遞給另一個函式?C
