C++ 架构决策:返回std::future还是提供回调?
我正在为Arinc429设备设计一个API接口。不同的供应商在设备中提供不同的功能,所以我决定为每个实体提供一组通用的和预期的方法。 特别是,我有一个关于输出通道的问题。它为字节数组的单个输出提供了一个方法,并且在调用该方法后,输出本身是异步的。其中一个设备实现中断,可通过操作系统实用程序(Windows中的C++ 架构决策:返回std::future还是提供回调?,c++,multithreading,c++11,asynchronous,future,C++,Multithreading,C++11,Asynchronous,Future,我正在为Arinc429设备设计一个API接口。不同的供应商在设备中提供不同的功能,所以我决定为每个实体提供一组通用的和预期的方法。 特别是,我有一个关于输出通道的问题。它为字节数组的单个输出提供了一个方法,并且在调用该方法后,输出本身是异步的。其中一个设备实现中断,可通过操作系统实用程序(Windows中的WaitForSingleObject)捕获中断 因此,在这个特殊情况下,我有一个实现IArinc429Device的对象,它: 实现方法CaptureInterrupt,该方法在中断发生
WaitForSingleObject
)捕获中断
因此,在这个特殊情况下,我有一个实现IArinc429Device
的对象,它:
- 实现方法
,该方法在中断发生时调用特定通道的回调李>CaptureInterrupt
- 保存运行
的线程李>CaptureInterrupt
但是另一个设备没有实现中断,所以我必须“忙等待”(在计算出的预期时间内睡眠,然后在一小段时间内循环睡眠,以调整可能的不准确度) 实现接口IArinc429ChannelOutput的对象:
- 实现方法
,该方法启动异步输出李>SingleOutput
- 实现方法
,该方法等待通道运行,然后将其状态修改为WaitOutputFinished
李>stopped
- 保存运行
的线程李>WaitOutputFinished
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;
};