RAII 等效于 FIFO 发布订单
RAII equivalent for FIFO release order
RAII 非常舒适,我很难为必须以与获取顺序相同的顺序 (FIFO( 而不是以相反的顺序(堆栈(从 RAII 中自然产生的资源提供等效的设计。
在我的具体情况下,我有一个stream
类如下:
template<typename T>
class stream {
...
public:
// Producer API
T& write_acquire(); // This acquires a storage element and will "block"
// until a slot is available in the underlying resource
void write_release(&T); // This releases the storage element, transferring the data to a consumer
// Consumer API
T& read_acquire(); // This acquires a storage element and will "block"
// until a slot has been write_release
void read_release(&T); // This releases the storage element making it available
// for a potential future write_acquire
};
我正在考虑提供一个 RAII 风格的助手:
template<typename T>
class stream_wslot {
stream<T> &s;
T &slot;
public:
stream_wslot(stream<T> &s) : s{s}, slot{s.write_acquire()} {}
~stream_wslot() { s.write_release(slot); }
operator T&() { return slot; }
T& operator=(T &val) { return slot = val; }
};
但问题是以下用法将无法正确运行:
void test(stream<float> &fifo) {
stream_wslot even(fifo);
stream_wslot odd(fifo);
... first ...
... second ...
// releases odd !!!
// releases even
}
也就是说,我们将在释放even
槽之前释放odd
槽。虽然我可以在stream
中添加一个"重新排序"队列,但我想知道是否有一种"干净"的方法可以将 RAII 推广到这些情况。
使用std::optional
,代价非常适中,开销最小,提供了对构造的更多控制,以及定义明确的销毁顺序。这正是您正在寻找的,在这里。
例如:
std::optional<stream_wslot> o_even;
std::optional<stream_wslot> o_odd;
o_odd.emplace(fifo);
o_even.emplace(fifo);
auto &even=*o_even;
auto &odd=*o_odd;
从这一点开始,使用odd
和even
的现有代码将很难区分。总计:odd
首先建造,even
其次建造。odd
首先被摧毁,当离开这个范围时,even
被摧毁。同样有效的建造和破坏命令。
这是一个使用std::queue
并在 C++11 及更高版本中工作的替代方案:
#include <queue>
void test(stream<float> &fifo) {
std::queue<stream_wslot> wslots;
#if __cplusplus >= 201703L // C++17 and later:
auto& even = wslots.emplace(fifo);
auto& odd = wslots.emplace(fifo);
#else // C++11 and C++14:
auto& even = (wslots.emplace(fifo), wslots.front());
auto& odd = (wslots.emplace(fifo), wslots.front());
#endif
// work with even and odd ...
}
首先创建even
引用的元素,然后创建odd
引用的元素。
在作用域结束时,std::queue
首先释放even
引用的元素,然后释放odd
引用的元素。
您可以在另一个线程上运行一个队列,以异步方式实现 FIFO 逻辑。如果wslot
对象是使用该队列的引用构造的,则可以告诉它在销毁时为它们执行write_release()
,但对构造执行常规write_acquire()
,如有必要,这将阻止。
(或者,在建设时,他们可以在某个地方通过一个std::future
,并通过write_release()
破坏来实现承诺。但这只是我含糊不清的挥手(。
相关文章:
- 即使我读取了所有内容,在FIFO上打开的QSocketNotifier也会一直启动
- 任何种类的分数 在任何类型的订单中
- 使用莱布尼茨公式的 Pi 近似
- Node.js fs.open() 在尝试打开 4 个以上的命名管道 (FIFO) 后挂起
- RAII 等效于 FIFO 发布订单
- 使用堆的优先级队列,具有相同键的值不遵循 FIFO(先进先出)
- 漂亮的计数器习语的错误或格式错误的静态订单惨败?
- C++操作员订单评估
- 相当于Linux fifo的Windows
- 客户订单的最短平均等待时间
- 曼德布洛特 从一个线程被反复使用变为两个线程
- 为什么我的石头剪刀布游戏不起作用?
- 使用信号处理程序处理从 FIFO 接收的数据
- 使用sync_with_stdio时打印订单
- 如何重置 int 主订单
- 如何修复以下代码以进行二叉树级别订单打印
- 曼德布洛特切片图像以提高速度
- FIFO块程序,直到其他进程读取
- 算术编码FPAQ0(一个简单的订单-0算术文件压缩机)
- 我可以使用C++向量代替FIFO订单的队列吗?