简体   繁体   English

如何反转 set_value() 并“停用”promise?

[英]How do I reverse set_value() and 'deactivate' a promise?

I have a total n00b question here on synchronization.我在这里有一个关于同步的总 n00b 问题。 I have a 'writer' thread which assigns a different value 'p' to a promise at each iteration.我有一个“编写器”线程,它在每次迭代时为 promise 分配一个不同的值“p”。 I need 'reader' threads which wait for shared_futures of this value and then process them, and my question is how do I use future/promise to ensure that the reader threads wait for a new update of 'p' before performing their processing task at each iteration?我需要'reader'线程等待这个值的shared_futures然后处理它们,我的问题是我如何使用future/promise来确保reader线程在执行他们的处理任务之前等待'p'的新更新每次迭代? Many thanks.非常感谢。

You can "reset" a promise by assigning it to a blank promise.您可以通过将 promise 分配给空白 promise 来“重置” promise。

myPromise = promise< int >();

A more complete example:一个更完整的例子:

promise< int > myPromise;

void writer()
{
    for( int i = 0; i < 10; ++i )
    {
        cout << "Setting promise.\n";
        myPromise.set_value( i );

        myPromise = promise< int >{};       // Reset the promise.

        cout << "Waiting to set again...\n";
        this_thread::sleep_for( chrono::seconds( 1 ));
    }
}

void reader()
{
    int result;
    do
    {
        auto myFuture = myPromise.get_future();
        cout << "Waiting to receive result...\n";
        result = myFuture.get();
        cout << "Received " << result << ".\n";
    } while( result < 9 );
}

int main()
{
    std::thread write( writer );
    std::thread read( reader );

    write.join();
    read.join();

    return 0;
}

A problem with this approach, however, is that synchronization between the two threads can cause the writer to call promise::set_value() more than once between the reader's calls to future::get() , or future::get() to be called while the promise is being reset.然而,这种方法的一个问题是,两个线程之间的同步可能导致编写器在读者调用future::get()future::get()之间多次调用promise::set_value() ) 到在 promise 被复位时被调用。 These problems can be avoided with care (eg with proper sleeping between calls), but this takes us into the realm of hacking and guesswork rather than logically correct concurrency.这些问题可以小心避免(例如,在调用之间进行适当的睡眠),但这会将我们带入 realm 的黑客和猜测而不是逻辑上正确的并发。

So although it's possible to reset a promise by assigning it to a fresh promise, doing so tends to raise broader synchronization issues.因此,尽管可以通过将 promise 分配给新的 promise 来重置 promise,但这样做往往会引发更广泛的同步问题。

A promise / future pair is designed to carry only a single value (or exception.). promise / future对设计为仅携带单个值(或异常)。 To do what you're describing, you probably want to adopt a different tool.要执行您所描述的操作,您可能希望采用不同的工具。

If you wish to have multiple threads (your readers) all stop at a common point, you might consider a barrier .如果您希望多个线程(您的读者)都停在一个共同点,您可以考虑使用barrier

The following code demonstrates how the producer/consumer pattern can be implemented with future and promise .以下代码演示了如何使用futurepromise实现生产者/消费者模式。

There are two promise variables, used by a producer and a consumer thread.有两个promise变量,由生产者和消费者线程使用。 Each thread resets one of the two promise variables and waits for the other one.每个线程重置两个promise变量之一并等待另一个。

#include <iostream>
#include <future>
#include <thread>
using namespace std;

// produces integers from 0 to 99
void producer(promise<int>& dataready, promise<void>& consumed)
{
    for (int i = 0; i < 100; ++i) {
        // do some work here ...
        consumed = promise<void>{};      // reset
        dataready.set_value(i);          // make data available
        consumed.get_future().wait();    // wait for the data to be consumed
    
    }
    dataready.set_value(-1);                     // no more data
}

// consumes integers
void consumer(promise<int>& dataready, promise<void>& consumed)
{
    for (;;) {
        int n = dataready.get_future().get();    // wait for data ready
        if (n >= 0) {
            std::cout << n << ",";
            dataready = promise<int>{};  // reset
            consumed.set_value();        // mark data as consumed
            // do some work here ...
        }
        else
            break;
    }
}

int main(int argc, const char*argv[])
{
    promise<int> dataready{};
    promise<void> consumed{};

    thread th1([&] {producer(dataready, consumed); });
    thread th2([&] {consumer(dataready, consumed); });

    th1.join();
    th2.join();
    std::cout  << "\n";

    return 0;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 std :: promise set_value和线程安全 - std::promise set_value and thread safety std::promise::set_value 崩溃 - Crash in std::promise::set_value crash std::promise::set_value() 和 std::future::wait() 是否提供 memory 围栏? - Do std::promise::set_value() and std::future::wait() provide a memory fence? 为什么std :: promise :: set_value()有两个重载 - Why does std::promise::set_value() have two overloads 为什么从主线程调用时,`std::promise::set_value` 会抛出错误? - Why does `std::promise::set_value` throw an error when invoked from the main thread? 编译错误:boost :: promise <T> :: set_value(const T&)不存在 - Compile error: boost::promise<T>::set_value(const T&) doesn't exist 固定到核心的FIFO线程上的std :: promise :: set_value不会唤醒std :: future - std::promise::set_value on FIFO thread pinned to a core doesn't wake std::future 使用 c++ libgpiod 库,如何将 gpio 行设置为输出并使用 set_value() function 操作单行? - Using c++ libgpiod library, how can I set gpio lines to be outputs and manipulate single lines with set_value() function? 对成员函数set_value的错误调用是ambigious(在使用pugixml库的xcode中) - error call to member function set_value is ambigious (in xcode using pugixml library) 如何访问集合中的结构值? - How do I access a struct value that is in a set?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM