Boost.Fiber 是否会在网络请求(例如网络上的数据库调用)时自动让步?
Does Boost.Fiber automatically yield on network requests, such as a database call over the network?
Boost.Fiber 是否会在网络请求时自动让步(如果我理解正确,它们会在 I/O 期间自动让步 CPU),例如通过网络调用数据库?我想用它来设置阻塞数据库调用,我在其中插入大量信息并且有很多小记录需要在收到时插入。对于微线程,我的另一个选择是 libdill/libmill。
总体思路是:
- 接收数据
- 创建光纤并将数据传递给它
- fiber 获取数据库连接并发送 INSERT 查询(带有 postgres 的 libpqxx)
- 其他纤程运行并且可以在数据库查询进行时访问数据库
- 从数据库查询returns,进行错误处理和处理响应
纤维是否像我想象的那样工作?
这是使用 RapidJSON 和 boost.fiber 的代码的简化基本结构,但我从网络 (websocket) 获取消息:
inline
void doDatabaseCall( Document &msg ) {
//Get connection & do query with libpqxx
}
Document msg;
msg.Parse( "{\"myVar\": \"test\"}" );
Document msg2;
msg2.Parse( "{\"myVar\": \"test2\"}" );
boost::fibers::fiber f1( doDatabaseCall, msg);
boost::fibers::fiber f2( doDatabaseCall, msg2);
f1.join();
f2.join();
Does Boost.Fiber automatically yield on network requests (if I understand correctly they yield the CPU during I/O), such as a database call over the network?
不,他们没有。
您似乎正在寻找的是 Boost Coroutines,结合用于异步 IO 的 Boost Asio。他们将屈服。
有些数据库操作库利用 Asio 进行异步执行(例如 Amy) or WebSockets (e.g. Boost Beast)
boost.fiber 确实与 boost.asio 集成 - 您需要 install a special scheduler - boost.fiber /sub-directory 示例中提供了示例)。
int main( int argc, char* argv[]) {
try {
std::shared_ptr< boost::asio::io_service > io_svc = std::make_shared< boost::asio::io_service >();
boost::fibers::use_scheduling_algorithm< boost::fibers::asio::round_robin >( io_svc);
// server
tcp::acceptor a( * io_svc, tcp::endpoint( tcp::v4(), 9999) );
boost::fibers::fiber( server, io_svc, std::ref( a) ).detach();
// client
const unsigned iterations = 2;
const unsigned clients = 3;
boost::fibers::barrier b( clients);
for ( unsigned i = 0; i < clients; ++i) {
boost::fibers::fiber(
client, io_svc, std::ref( a), std::ref( b), iterations).detach();
}
io_svc->run();
std::cout << "done." << std::endl;
return EXIT_SUCCESS;
} catch ( std::exception const& e) {
print("Exception: ", e.what(), "\n");
}
return 0;
}
Boost.Fiber 是否会在网络请求时自动让步(如果我理解正确,它们会在 I/O 期间自动让步 CPU),例如通过网络调用数据库?我想用它来设置阻塞数据库调用,我在其中插入大量信息并且有很多小记录需要在收到时插入。对于微线程,我的另一个选择是 libdill/libmill。
总体思路是:
- 接收数据
- 创建光纤并将数据传递给它
- fiber 获取数据库连接并发送 INSERT 查询(带有 postgres 的 libpqxx)
- 其他纤程运行并且可以在数据库查询进行时访问数据库
- 从数据库查询returns,进行错误处理和处理响应
纤维是否像我想象的那样工作?
这是使用 RapidJSON 和 boost.fiber 的代码的简化基本结构,但我从网络 (websocket) 获取消息:
inline
void doDatabaseCall( Document &msg ) {
//Get connection & do query with libpqxx
}
Document msg;
msg.Parse( "{\"myVar\": \"test\"}" );
Document msg2;
msg2.Parse( "{\"myVar\": \"test2\"}" );
boost::fibers::fiber f1( doDatabaseCall, msg);
boost::fibers::fiber f2( doDatabaseCall, msg2);
f1.join();
f2.join();
Does Boost.Fiber automatically yield on network requests (if I understand correctly they yield the CPU during I/O), such as a database call over the network?
不,他们没有。
您似乎正在寻找的是 Boost Coroutines,结合用于异步 IO 的 Boost Asio。他们将屈服。
有些数据库操作库利用 Asio 进行异步执行(例如 Amy) or WebSockets (e.g. Boost Beast)
boost.fiber 确实与 boost.asio 集成 - 您需要 install a special scheduler - boost.fiber /sub-directory 示例中提供了示例)。
int main( int argc, char* argv[]) {
try {
std::shared_ptr< boost::asio::io_service > io_svc = std::make_shared< boost::asio::io_service >();
boost::fibers::use_scheduling_algorithm< boost::fibers::asio::round_robin >( io_svc);
// server
tcp::acceptor a( * io_svc, tcp::endpoint( tcp::v4(), 9999) );
boost::fibers::fiber( server, io_svc, std::ref( a) ).detach();
// client
const unsigned iterations = 2;
const unsigned clients = 3;
boost::fibers::barrier b( clients);
for ( unsigned i = 0; i < clients; ++i) {
boost::fibers::fiber(
client, io_svc, std::ref( a), std::ref( b), iterations).detach();
}
io_svc->run();
std::cout << "done." << std::endl;
return EXIT_SUCCESS;
} catch ( std::exception const& e) {
print("Exception: ", e.what(), "\n");
}
return 0;
}