Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/136.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 架构决策:返回std::future还是提供回调?_C++_Multithreading_C++11_Asynchronous_Future - Fatal编程技术网

C++ 架构决策:返回std::future还是提供回调?

C++ 架构决策:返回std::future还是提供回调?,c++,multithreading,c++11,asynchronous,future,C++,Multithreading,C++11,Asynchronous,Future,我正在为Arinc429设备设计一个API接口。不同的供应商在设备中提供不同的功能,所以我决定为每个实体提供一组通用的和预期的方法。 特别是,我有一个关于输出通道的问题。它为字节数组的单个输出提供了一个方法,并且在调用该方法后,输出本身是异步的。其中一个设备实现中断,可通过操作系统实用程序(Windows中的WaitForSingleObject)捕获中断 因此,在这个特殊情况下,我有一个实现IArinc429Device的对象,它: 实现方法CaptureInterrupt,该方法在中断发生

我正在为Arinc429设备设计一个API接口。不同的供应商在设备中提供不同的功能,所以我决定为每个实体提供一组通用的和预期的方法。 特别是,我有一个关于输出通道的问题。它为字节数组的单个输出提供了一个方法,并且在调用该方法后,输出本身是异步的。其中一个设备实现中断,可通过操作系统实用程序(Windows中的
WaitForSingleObject
)捕获中断

因此,在这个特殊情况下,我有一个实现
IArinc429Device
的对象,它:

  • 实现方法
    CaptureInterrupt
    ,该方法在中断发生时调用特定通道的回调
  • 保存运行
    CaptureInterrupt
    的线程

但是另一个设备没有实现中断,所以我必须“忙等待”(在计算出的预期时间内睡眠,然后在一小段时间内循环睡眠,以调整可能的不准确度)

实现接口IArinc429ChannelOutput的对象:

  • 实现方法
    SingleOutput
    ,该方法启动异步输出
  • 实现方法
    WaitOutputFinished
    ,该方法等待通道运行,然后将其状态修改为
    stopped
  • 保存运行
    WaitOutputFinished
    的线程
下面是输出通道API的一部分

struct ARINC429_API IArinc429ChannelOutput
{
    // 0 based index
    virtual size_t ChannelIndex() const = 0;
    virtual Arinc429OutMode OutputMode() const = 0;
    virtual Arinc429Freq Frequency() const = 0;
    virtual size_t BufferSize() const = 0;

    virtual void SetFinishOutputCallback(std::function<void()>&& fCallBack) = 0;

    // elements exceeding BufferSize are ignored
    // TODO: return future?
    virtual bool SingleOutput(array_view<const uint32_t> wordArray) = 0;

    virtual void StopOutput() = 0;

    virtual ~IArinc429ChannelOutput() = default;
};
结构ARINC429\u API IARINC429通道输出
{
//基于0的索引
虚拟大小\u t ChannelIndex()常量=0;
虚拟ARINC429OUTPUTMODE OutputMode()常量=0;
虚拟Arinc429Freq()频率常数=0;
虚拟大小\u t BufferSize()常量=0;
虚拟void SetFinishOutputCallback(std::function&&fCallBack)=0;
//超过缓冲区大小的元素将被忽略
//TODO:回归未来?
虚拟布尔单输出(数组\视图字数组)=0;
虚拟void StopOutput()=0;
virtual~IArinc429ChannelOutput()=默认值;
};
考虑到输出的异步性质,我认为从
SingleOutput
返回
std::future
会很方便。对于第二种类型的Arinc429设备,我认为这样做没有问题,因为单独的通道对象拥有自己单独的等待线程

我从一开始就选择在完成的输出上添加回调,因为中断是为第一个设备实现的。此外,回调可以方便地从中发出Qt信号

但是
std::future
对于同步来说更方便,可以用来等待输出完成。虽然使用回调和条件变量也是可以管理的,但我觉得这种方法不太方便

选择什么选项?

a。定义注册和使用回调的例程。

b。将
std::future
定义为
SingleOutput
的返回类型

c。定义两者。这是合理的还是可能的?它意味着调用
std::promise::set_value
而不是调用。


另一个问题是关于实施

对于实现中断的设备,我看不到一种清晰简单的方法来实现返回
std::future
,因为所有通道都有一个公共中断事件和捕获线程

如何为驻留在不同线程中的多个输出通道对象提供未来?请参见
ArincPCI429\u 3::CaptureInterrupt()


void ArincECE206_1ChannelOutput::WaitOutputFinished(size_t words)
{
    // calculate expected period of time to sleep, using amount of words to transfer and channel output speed
    std::chrono::microseconds timeToSleep = ...;

    // 99% is enough
    std::this_thread::sleep_for(timeToSleep);

    // if channel is still running, wait for 1 more word.
    timeToSleep = Arinc429Values::TimeToTransfer(
            refImpl_.outputFreqs[ChannelIndex()],
            1);

    while(IsRunning())
    {
        std::this_thread::sleep_for(timeToSleep);
        ++additionalWords;
    }

    mode_ = Arinc429OutMode::stopped;

    if (callbackOnFinishedOutput_)
        callbackOnFinishedOutput_();
}
struct ARINC429_API IArinc429ChannelOutput
{
    // 0 based index
    virtual size_t ChannelIndex() const = 0;
    virtual Arinc429OutMode OutputMode() const = 0;
    virtual Arinc429Freq Frequency() const = 0;
    virtual size_t BufferSize() const = 0;

    virtual void SetFinishOutputCallback(std::function<void()>&& fCallBack) = 0;

    // elements exceeding BufferSize are ignored
    // TODO: return future?
    virtual bool SingleOutput(array_view<const uint32_t> wordArray) = 0;

    virtual void StopOutput() = 0;

    virtual ~IArinc429ChannelOutput() = default;
};