c++ - FIFO 释放订单的 RAII 等效项
问题描述
RAII 很舒服,我很难为必须按照它们被获取的相同顺序 (FIFO) 而不是按照自然从 RAII 出来的相反顺序 (Stack) 释放的资源提供等效的设计。
在我的具体情况下,我有一个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
}
也就是说,我们将在释放odd
插槽之前释放even
插槽。虽然我可以在其中添加一个“重新排序”队列,但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
第二个被销毁。相同的有效建造和销毁顺序。