如何处理 RAII 中的资源等待
How to deal with Resource-waiting in RAII
我是 C++ 新手,目前正在学习 RAII(资源获取即初始化)模式。
我很好奇人们将如何处理他们需要等待的资源。
在Java中,可能要做的事情是:
MyClass obj = new MyClass();
new Thread(
() -> obj.initialize(); // resource acquisition
).start()
...
if (obj.initialized()) {
// Use object
}
换句话说,我们可以在后台进行耗时的资源获取。
我们如何在 C++ 中使用 RAII 做到这一点?或者这是 RAII 的限制?
RAII 在可以获取尚未准备好使用的对象时解决反模式。特别是,您的 Java 代码存在相同的反模式 - MyClass
的用户很容易在构造对象后立即忘记 运行 initialize
方法。
当需要进行复杂的初始化时,执行 RAII 的最简单方法是通过工厂方法。将可能不安全的构造函数设为私有并公开一个 public 静态函数,该函数将为您构造 和 初始化对象。特别是,如果您想 运行 同时进行初始化,没有什么可以阻止您将该工厂方法的 return 类型转换为 std::future
或类似的类型。
关键要点是 RAII 的目的 - 必须不可能获取未初始化的资源。通过将唯一方法获取到始终初始化资源的函数中,您将获得 RAII。
RAII 表示资源由某个对象定义。理想情况下,该对象的构造函数获取资源,而析构函数释放它。在对象有效期间,您可以使用对象与资源进行交互。
如果资源 "needs to be waited on",那么根据 RAII 的规则,这意味着您还没有代表该资源的对象 。相反,您有一个对象代表将来可用的资源。
这就是 C++ 调用此类型的原因 std::future
。它是一个模板,参数是您正在等待其创建的对象的类型。
从概念上讲,future
只是一种将对象(或异常)从生成它的代码(可能是异步的)转发给接收者的方法。
现在给出你的例子,我们需要从 MyClass
中删除 initialize
并使其成为一个函数 returns a MyClass
实例。它可以是 MyClass
的静态成员,也可以只是一个命名空间作用域的函数。
因此代码基本上如下所示:
auto future = std::async(initialize);
...
if(future.wait_for(std::chrono::seconds(0)) == std::future_status::ready)
{
MyClass resource = future.get(); //The `future` is now empty. Any exceptions will be thrown here.
//use resource
}
我是 C++ 新手,目前正在学习 RAII(资源获取即初始化)模式。 我很好奇人们将如何处理他们需要等待的资源。
在Java中,可能要做的事情是:
MyClass obj = new MyClass();
new Thread(
() -> obj.initialize(); // resource acquisition
).start()
...
if (obj.initialized()) {
// Use object
}
换句话说,我们可以在后台进行耗时的资源获取。
我们如何在 C++ 中使用 RAII 做到这一点?或者这是 RAII 的限制?
RAII 在可以获取尚未准备好使用的对象时解决反模式。特别是,您的 Java 代码存在相同的反模式 - MyClass
的用户很容易在构造对象后立即忘记 运行 initialize
方法。
当需要进行复杂的初始化时,执行 RAII 的最简单方法是通过工厂方法。将可能不安全的构造函数设为私有并公开一个 public 静态函数,该函数将为您构造 和 初始化对象。特别是,如果您想 运行 同时进行初始化,没有什么可以阻止您将该工厂方法的 return 类型转换为 std::future
或类似的类型。
关键要点是 RAII 的目的 - 必须不可能获取未初始化的资源。通过将唯一方法获取到始终初始化资源的函数中,您将获得 RAII。
RAII 表示资源由某个对象定义。理想情况下,该对象的构造函数获取资源,而析构函数释放它。在对象有效期间,您可以使用对象与资源进行交互。
如果资源 "needs to be waited on",那么根据 RAII 的规则,这意味着您还没有代表该资源的对象 。相反,您有一个对象代表将来可用的资源。
这就是 C++ 调用此类型的原因 std::future
。它是一个模板,参数是您正在等待其创建的对象的类型。
从概念上讲,future
只是一种将对象(或异常)从生成它的代码(可能是异步的)转发给接收者的方法。
现在给出你的例子,我们需要从 MyClass
中删除 initialize
并使其成为一个函数 returns a MyClass
实例。它可以是 MyClass
的静态成员,也可以只是一个命名空间作用域的函数。
因此代码基本上如下所示:
auto future = std::async(initialize);
...
if(future.wait_for(std::chrono::seconds(0)) == std::future_status::ready)
{
MyClass resource = future.get(); //The `future` is now empty. Any exceptions will be thrown here.
//use resource
}