清理超时的未来
Clean-up a timed-out future
我需要 运行 一个带有超时的函数。如果它没有在给定的超时内 return,我需要丢弃它并回退到不同的方法。
以下是一个(大大)简化的示例代码以突出问题。 (实际上,这是一个总是 运行ning 的高可用应用程序。我首先从缓存中读取,然后仅当缓存中有陈旧数据时才尝试从数据库中读取。但是,如果数据库查询时间很长,我需要继续处理过时的数据。)
我的问题是,如果 future 读取超时,我是否必须单独处理 future 的清理(即保留副本并不时检查它是否准备就绪)?或者我可以简单地忽略它(即保持代码不变)。
/* DB query can be time-consuming, but the result is fresh */
string readFromDatabase(){
// ...
// auto dbValue = db.query("select name from users where id=" + _id);
// ...
return dbValue;
}
/* Cache query is instant, but the result could be stale */
string readFromLocalCache(){
// ...
// auto cachedVal = _cache[_id];
// ...
return cachedVal;
}
int getValue(){
// Idea:
// - Try reading from the database.
// - If the db query didn't return within 1 second, fallback to the other method.
using namespace std::chrono_literals;
auto fut = std::async(std::launch::async, [&](){ return readFromDatabase(); });
switch (fut.wait_for(1s)){
case std::future_status::ready: // query returned within allotted time
{
auto freshVal = fut.get();
// update cache
return freshVal;
}
case std::future_status::timeout: // timed out, fallback ------ (*)
{
break;
}
case std::future_status::deferred: // should not be reached
{
break;
}
}
return readFromLocalCache();
// quetion? what happens to `fut`?
}
My question is, in the case where the future read timed out, do I have to handle the clean-up of the future separately (i.e. keep a copy and check if it is ready time-to-time)? or can I simply ignore it (i.e. keep the code as is).
从我个人的角度来看,这取决于你想要什么。在您当前的(最小)实现下,getValue
函数将被未来的析构函数阻止(参见 cppreference page and some SO questions)。
如果您不想要阻塞行为,有一些解决方案,如本 question 中所建议的,例如:
- 将
future
移动到某个外部范围
- 使用分离的执行器和一些方便的 code/data 结构来处理 return 状态
- 看看是否可以用一些超时支持 I/O 操作替换
future
,例如 select/poll
等等
我需要 运行 一个带有超时的函数。如果它没有在给定的超时内 return,我需要丢弃它并回退到不同的方法。
以下是一个(大大)简化的示例代码以突出问题。 (实际上,这是一个总是 运行ning 的高可用应用程序。我首先从缓存中读取,然后仅当缓存中有陈旧数据时才尝试从数据库中读取。但是,如果数据库查询时间很长,我需要继续处理过时的数据。)
我的问题是,如果 future 读取超时,我是否必须单独处理 future 的清理(即保留副本并不时检查它是否准备就绪)?或者我可以简单地忽略它(即保持代码不变)。
/* DB query can be time-consuming, but the result is fresh */
string readFromDatabase(){
// ...
// auto dbValue = db.query("select name from users where id=" + _id);
// ...
return dbValue;
}
/* Cache query is instant, but the result could be stale */
string readFromLocalCache(){
// ...
// auto cachedVal = _cache[_id];
// ...
return cachedVal;
}
int getValue(){
// Idea:
// - Try reading from the database.
// - If the db query didn't return within 1 second, fallback to the other method.
using namespace std::chrono_literals;
auto fut = std::async(std::launch::async, [&](){ return readFromDatabase(); });
switch (fut.wait_for(1s)){
case std::future_status::ready: // query returned within allotted time
{
auto freshVal = fut.get();
// update cache
return freshVal;
}
case std::future_status::timeout: // timed out, fallback ------ (*)
{
break;
}
case std::future_status::deferred: // should not be reached
{
break;
}
}
return readFromLocalCache();
// quetion? what happens to `fut`?
}
My question is, in the case where the future read timed out, do I have to handle the clean-up of the future separately (i.e. keep a copy and check if it is ready time-to-time)? or can I simply ignore it (i.e. keep the code as is).
从我个人的角度来看,这取决于你想要什么。在您当前的(最小)实现下,getValue
函数将被未来的析构函数阻止(参见 cppreference page and some SO questions)。
如果您不想要阻塞行为,有一些解决方案,如本 question 中所建议的,例如:
- 将
future
移动到某个外部范围 - 使用分离的执行器和一些方便的 code/data 结构来处理 return 状态
- 看看是否可以用一些超时支持 I/O 操作替换
future
,例如 select/poll
等等