- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
在this问题 我描述了 boost::asio 和 boost::coroutine 使用模式,这导致我的应用程序随机崩溃,我发布了我的代码和 valgrind 和 GDB 输出。
为了进一步调查问题,我创建了较小的概念验证应用程序,它应用了相同的模式。我看到我在此处发布的源代码较小的程序中出现了同样的问题。
代码启动了几个线程并创建了一个带有几个虚拟连接(用户提供的数字)的连接池。附加参数是无符号整数,它扮演伪请求的角色。 sendRequest
函数的虚拟实现只是启动异步计时器,等待秒数等于输入数和函数的 yileds。
有人能看出这段代码的问题吗?他能提出一些修复建议吗?
#include "asiocoroutineutils.h"
#include "concurrentqueue.h"
#include <iostream>
#include <thread>
#include <boost/lexical_cast.hpp>
using namespace std;
using namespace boost;
using namespace utils;
#define id this_thread::get_id() << ": "
// ---------------------------------------------------------------------------
/*!
* \brief This is a fake Connection class
*/
class Connection
{
public:
Connection(unsigned connectionId)
: _id(connectionId)
{
}
unsigned getId() const
{
return _id;
}
void sendRequest(asio::io_service& ioService,
unsigned seconds,
AsioCoroutineJoinerProxy,
asio::yield_context yield)
{
cout << id << "Connection " << getId()
<< " Start sending: " << seconds << endl;
// waiting on this timer is palceholder for any asynchronous operation
asio::steady_timer timer(ioService);
timer.expires_from_now(chrono::seconds(seconds));
coroutineAsyncWait(timer, yield);
cout << id << "Connection " << getId()
<< " Received response: " << seconds << endl;
}
private:
unsigned _id;
};
typedef std::unique_ptr<Connection> ConnectionPtr;
typedef std::shared_ptr<asio::steady_timer> TimerPtr;
// ---------------------------------------------------------------------------
class ConnectionPool
{
public:
ConnectionPool(size_t connectionsCount)
{
for(size_t i = 0; i < connectionsCount; ++i)
{
cout << "Creating connection: " << i << endl;
_connections.emplace_back(new Connection(i));
}
}
ConnectionPtr getConnection(TimerPtr timer,
asio::yield_context& yield)
{
lock_guard<mutex> lock(_mutex);
while(_connections.empty())
{
cout << id << "There is no free connection." << endl;
_timers.emplace_back(timer);
timer->expires_from_now(
asio::steady_timer::clock_type::duration::max());
_mutex.unlock();
coroutineAsyncWait(*timer, yield);
_mutex.lock();
cout << id << "Connection was freed." << endl;
}
cout << id << "Getting connection: "
<< _connections.front()->getId() << endl;
ConnectionPtr connection = std::move(_connections.front());
_connections.pop_front();
return connection;
}
void addConnection(ConnectionPtr connection)
{
lock_guard<mutex> lock(_mutex);
cout << id << "Returning connection " << connection->getId()
<< " to the pool." << endl;
_connections.emplace_back(std::move(connection));
if(_timers.empty())
return;
auto timer = _timers.back();
_timers.pop_back();
auto& ioService = timer->get_io_service();
ioService.post([timer]()
{
cout << id << "Wake up waiting getConnection." << endl;
timer->cancel();
});
}
private:
mutex _mutex;
deque<ConnectionPtr> _connections;
deque<TimerPtr> _timers;
};
typedef unique_ptr<ConnectionPool> ConnectionPoolPtr;
// ---------------------------------------------------------------------------
class ScopedConnection
{
public:
ScopedConnection(ConnectionPool& pool,
asio::io_service& ioService,
asio::yield_context& yield)
: _pool(pool)
{
auto timer = make_shared<asio::steady_timer>(ioService);
_connection = _pool.getConnection(timer, yield);
}
Connection& get()
{
return *_connection;
}
~ScopedConnection()
{
_pool.addConnection(std::move(_connection));
}
private:
ConnectionPool& _pool;
ConnectionPtr _connection;
};
// ---------------------------------------------------------------------------
void sendRequest(asio::io_service& ioService,
ConnectionPool& pool,
unsigned seconds,
asio::yield_context yield)
{
cout << id << "Constructing request ..." << endl;
AsioCoroutineJoiner joiner(ioService);
ScopedConnection connection(pool, ioService, yield);
asio::spawn(ioService, bind(&Connection::sendRequest,
connection.get(),
std::ref(ioService),
seconds,
AsioCoroutineJoinerProxy(joiner),
placeholders::_1));
joiner.join(yield);
cout << id << "Processing response ..." << endl;
}
// ---------------------------------------------------------------------------
void threadFunc(ConnectionPool& pool,
ConcurrentQueue<unsigned>& requests)
{
try
{
asio::io_service ioService;
while(true)
{
unsigned request;
if(!requests.tryPop(request))
break;
cout << id << "Scheduling request: " << request << endl;
asio::spawn(ioService, bind(sendRequest,
std::ref(ioService),
std::ref(pool),
request,
placeholders::_1));
}
ioService.run();
}
catch(const std::exception& e)
{
cerr << id << "Error: " << e.what() << endl;
}
}
// ---------------------------------------------------------------------------
int main(int argc, char* argv[])
{
if(argc < 3)
{
cout << "Usage: ./async_request poolSize threadsCount r0 r1 ..."
<< endl;
return -1;
}
try
{
auto poolSize = lexical_cast<size_t>(argv[1]);
auto threadsCount = lexical_cast<size_t>(argv[2]);
ConcurrentQueue<unsigned> requests;
for(int i = 3; i < argc; ++i)
{
auto request = lexical_cast<unsigned>(argv[i]);
requests.tryPush(request);
}
ConnectionPoolPtr pool(new ConnectionPool(poolSize));
vector<unique_ptr<thread>> threads;
for(size_t i = 0; i < threadsCount; ++i)
{
threads.emplace_back(
new thread(threadFunc, std::ref(*pool), std::ref(requests)));
}
for_each(threads.begin(), threads.end(), mem_fn(&thread::join));
}
catch(const std::exception& e)
{
cerr << "Error: " << e.what() << endl;
}
return 0;
}
以下是上述代码使用的一些辅助工具:
#pragma once
#include <boost/asio/steady_timer.hpp>
#include <boost/asio/spawn.hpp>
namespace utils
{
inline void coroutineAsyncWait(boost::asio::steady_timer& timer,
boost::asio::yield_context& yield)
{
boost::system::error_code ec;
timer.async_wait(yield[ec]);
if(ec && ec != boost::asio::error::operation_aborted)
throw std::runtime_error(ec.message());
}
class AsioCoroutineJoiner
{
public:
explicit AsioCoroutineJoiner(boost::asio::io_service& io)
: _timer(io), _count(0) {}
void join(boost::asio::yield_context yield)
{
assert(_count > 0);
_timer.expires_from_now(
boost::asio::steady_timer::clock_type::duration::max());
coroutineAsyncWait(_timer, yield);
}
void inc()
{
++_count;
}
void dec()
{
assert(_count > 0);
--_count;
if(0 == _count)
_timer.cancel();
}
private:
boost::asio::steady_timer _timer;
std::size_t _count;
}; // AsioCoroutineJoiner class
class AsioCoroutineJoinerProxy
{
public:
AsioCoroutineJoinerProxy(AsioCoroutineJoiner& joiner)
: _joiner(joiner)
{
_joiner.inc();
}
AsioCoroutineJoinerProxy(const AsioCoroutineJoinerProxy& joinerProxy)
: _joiner(joinerProxy._joiner)
{
_joiner.inc();
}
~AsioCoroutineJoinerProxy()
{
_joiner.dec();
}
private:
AsioCoroutineJoiner& _joiner;
}; // AsioCoroutineJoinerProxy class
} // utils namespace
为了代码的完整性,最后缺少的部分是 ConcurrentQueue 类。贴在这里太长了,但是如果你想要的话可以找到它here .
应用程序的示例用法是:
./connectionpooltest 3 3 5 7 8 1 0 9 2 4 3 6
其中第一个数字 3 是假连接数,第二个数字 3 是使用的线程数。后面的数字是虚假请求。
valgrind 和GDB 的输出和上面提到的一样question .
使用的 boost 版本是 1.57。编译器是 GCC 4.8.3。操作系统为CentOS Linux release 7.1.1503
最佳答案
似乎所有 valgrind 错误都是由于 BOOST_USE_VALGRIND 宏未定义为 Tanner Sansbury 在与 this 相关的注释中指出的题。似乎除此之外程序都是正确的。
关于c++ - 这个 boost::asio 和 boost::coroutine 使用模式有什么问题?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31639888/
使用 asio 库,我想为 asio::serial_port 读/写调用使用超时。 是否可以使用相同的 asio::serial_port asio::io_context 和用于 asio 的相同
对于我正在从事的副业项目应该使用哪种类型的解析器,我有点困惑。我在 asio 文档中找不到答案。 我知道 DNS 可以与 UDP 或 TCP 一起使用,并且通常通过 TCP 发送较大的响应。 asio
在仅从一个线程调用 io_service::run() 的情况下,从不同线程调用 async_write 和 async_read 是否安全?谢谢! 最佳答案 Is it safe to call a
我想知道Boost ASIO 有多受欢迎。它是否被用于任何流行的网络密集型软件中? 最佳答案 用于管理 IBM Blue Gene/Q 的系统软件 super 计算机广泛使用Boost.Asio。
我想使用一个函数来读取套接字端口,并在收到 IP 数据包时交还控制权。 boost::asio::ip::udp::socket 有一个函数接收(或 async_receive),它返回读取了多少字节
我试图调整 Boost 文档中的 SSL 服务器示例 here但我想制作一个应用程序,您可以在其中使用普通 boost::asio::ip::tcp::socket或 SSL 套接字,但我还没有找到将
在查看 boost asio co_spawn 文档 ( https://www.boost.org/doc/libs/1_78_0/doc/html/boost_asio/reference/co_
我正在尝试使用 Boost.ASIO 库,但我找不到如何列出 boost 的可用端口(带有串行端口服务)或套接字(带有网络服务)。 你知道这是否可能吗? 谢谢你。 最佳答案 Boost.Asio 不提
我想使用boost::asio从多个stdout中同时读取stderr和boost::process。但是,我在使用boost::asio时遇到了编译问题,可以重建以下无法编译的最小示例: #incl
提前为一个愚蠢的问题道歉 - 我对这一切都很陌生。 所以我从 here 下载了 asio ,并尝试#include asio.hpp,但出现以下错误; fatal error: boost/confi
我是使用 boost 的项目的一部分作为一个 C++ 库。现在我们要使用 SMTP/POP3/SSL/HTTP/HTTPS。我在 Poco::Net 中检测到几个拟合类和函数 Poco::Net::P
有谁知道有任何实现 Web Sockets 的尝试吗?使用 Boost asio 的 API? 最佳答案 我意识到这是一个旧线程,但想更新以帮助那些寻找答案的人:WebSocket++完全符合要求。
和 asio::thread_pool 有什么区别和一个 asio::io_context谁的run()函数是从多个线程调用的?我可以更换我的 boost::thread_group调用 io_con
我想连接到由目标 IP 地址和端口号指定的服务器套接字。 boost::asio::connect 似乎不允许使用它。我有 ip 目的地作为无符号 int 值。 更新:我能够做到 ba::ip::tc
我在 pc 上有 3 个网络接口(interface),并且想确保当我进行 udp 套接字发送时,它通过特定的网络接口(interface)发送(我有发送数据时使用的 ip 地址)。 这是代码。 ud
我正在使用 ASIO 开发网络应用程序并提到了Chat-Server/Client 我问过类似的问题Here 为了更好地解释,我在这里添加了更多代码: 我的 Cserver Class class C
我已经阅读了 boost asio 引用资料,浏览了教程并查看了一些示例。尽管如此,我还是看不出应该如何拆除套接字: 我应该调用 close() 还是由套接字的析构函数完成? 什么时候应该调用 shu
我认为标题已经说明了大部分内容,但我也有兴趣了解在没有现有解决方案的情况下如何将 DTLS 支持引入 asio 最佳答案 ASIO 本身不支持DTLS 但有一个GitHub 库asio_dtls已向
我正在将 async_read 与 streambuf 一起使用。但是,我想将读取的数据量限制为 4,这样我就可以在进入正文之前正确处理 header 。 我如何使用 async_read 做到这一点
从this example开始,我想用 async_read_until() 替换 async_read()。 所以我查了一下this example ,并查看了如何调用 async_read_unt
我是一名优秀的程序员,十分优秀!