簡體   English   中英

需要幫助了解 std::promise 和 std::future 在這種情況下如何工作

[英]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::promisestd::future傳遞到主線程。 is_ready是一個實用的 function 用於檢查 promise 是否滿足。

我的興趣在於main() function 的第三行及其周圍的內容。 起初我嘗試將interruptPromise的值提前設置為 false (這表明中斷沒有發生,因此稍后在其他線程中我將其更改為 true 以表明它確實發生了)。 它導致在while循環開始之前就滿足了interruptPromise ,因此循環沒有被執行。

問題

  1. 當調用set_value時,我知道std::promise變得滿意。 但是我如何提前分配一個值,然后讓std::future對它的更改做出反應(例如, future會對false bool更改為true做出反應)?
  2. 我會需要做這樣的事情嗎?
  3. 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM