[英]Need help understanding how std::promise and std::future work in this case
#include <iostream>
#include <thread>
#include <atomic>
#include <future>
void listenForInput(std::promise<bool>&& interruptPromise)
{
std::cin.get();
std::atomic_thread_fence(std::memory_order_acquire);
interruptPromise.set_value(true);
std::cout << "[Speech 100] no u \n";
}
bool is_ready(std::future<bool> const& f)
{
return f.wait_for(std::chrono::seconds(0)) == std::future_status::ready;
}
int main()
{
std::atomic_thread_fence(std::memory_order_acquire);
std::promise<bool> interruptPromise;
//interuptPromise.set_value(false);
/* Commenting line above makes program work. Uncommenting results in while
loop below not being executed */
std::atomic_thread_fence(std::memory_order_release);
std::future<bool> interruptFuture = interuptPromise.get_future();
std::thread reply(listenForInput, std::move(interruptPromise));
while (!is_ready(interruptFuture))
{
std::cout << "Your mother was a hamster, "
"and your father smelt of elderberries "
"(Press any key to reply)\n";
std::this_thread::sleep_for( std::chrono::seconds(2) );
}
reply.join();
std::cin.get();
return 0;
}
在上面的主線程代碼中,同一行文本不斷顯示,直到它被另一個線程中斷。 中斷發生在用戶的任何輸入之后。 用戶輸入的消息通過std::promise
和std::future
傳遞到主線程。 is_ready
是一個實用的 function 用於檢查 promise 是否滿足。
我的興趣在於main()
function 的第三行及其周圍的內容。 起初我嘗試將interruptPromise
的值提前設置為 false (這表明中斷沒有發生,因此稍后在其他線程中我將其更改為 true 以表明它確實發生了)。 它導致在while
循環開始之前就滿足了interruptPromise
,因此循環沒有被執行。
set_value
時,我知道std::promise
變得滿意。 但是我如何提前分配一個值,然后讓std::future
對它的更改做出反應(例如, future
會對false
bool
更改為true
做出反應)?std::promise
是否具有某些類型的默認值(如果它需要的話)?Primise/future 不是一個會改變的值,它是一個稍后交付的值。
如果您想要一個改變的值,您可以將互斥鎖、條件變量和布爾值中的一個拼接在一起。 但是,根據我的經驗,推理在多線程環境中多次更改的 bool 會破壞大多數人的大腦。
更好的選擇是像上面保護的數據隊列,嘗試 pop 或嘗試 pop 所有從隊列中取出數據的方法(如果有的話)。
template<class T>
struct threadsafe_queue{
std::optional<T> try_pop();
std::optional<T> wait_and_pop();
bool is_aborted() const;
std::deque<T> pop_all();
void push(T);
void abort();
private:
std::condition_variable cv;
mutable std::mutex m;
std::deque<T> queue;
bool isAborted=false;
std::unique_lock<std::mutex> lock() const;
};
寫上面,然后通過隊列發送用戶輸入。 主線程會嘗試彈出並處理(如果有)。
std::optional<T> try_pop(){
auto l=lock();
if (is_aborted()||queue.empty()) return {};
auto r=queue.front();
queue.pop_front();
return r;
}
std::optional<T> wait_and_pop(){
auto l=lock();
cv.wait(l, [&]{return is_aborted()||!queue.empty();});
if (is_aborted()) return {};
auto r=queue.front();
queue.pop_front();
return r;
}
void push(T t){
auto l=lock();
if (is_aborted()) return;
queue.push_back(std::move(t));
cv.notify_one();
}
void abort(){
auto l=lock();
isAborted=true;
cv.notify_all();
}
有一些示例實現。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.