gpt4 book ai didi

c++ - 何时需要运行 io_service 以及为什么

转载 作者:行者123 更新时间:2023-11-30 04:03:57 25 4
gpt4 key购买 nike

我有以下代码:

#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/date_time.hpp>
#include <boost/function.hpp>
#include <boost/noncopyable.hpp>
#include <boost/smart_ptr/shared_ptr.hpp>
#include <boost/thread.hpp>

#include <map>
#include <utility>

namespace koicxx {

template <typename T>
class temp_storage : private boost::noncopyable
{
typedef boost::shared_ptr<boost::asio::deadline_timer> shared_timer_t;
typedef std::map<T, shared_timer_t> timer_map_t;
typedef std::pair<T, shared_timer_t> timer_pair_t;
typedef boost::function<void(const T&, const boost::system::error_code&)> callback_t;

public:
temp_storage(boost::asio::io_service& io_service) :
_io_service(io_service) {}

bool add(const T& element, const boost::asio::deadline_timer::duration_type& timeout, callback_t callback = callback_t())
{
boost::lock_guard<boost::mutex> lock(_sync);

const std::pair<timer_map_t::iterator, bool>& res =
_internal_storage.insert(
timer_pair_t(
element
, shared_timer_t(new boost::asio::deadline_timer(_io_service, timeout))
));

if (!res.second)
{
return false;
}

const timer_map_t::iterator& itr = res.first;

if (callback)
{
itr->second->async_wait(
boost::bind(
callback
, itr->first
, boost::asio::placeholders::error
));
}

itr->second->async_wait(
boost::bind(
&temp_storage::remove_callback
, this
, itr->first
, boost::asio::placeholders::error
));

return true;
}

bool remove(const T& element)
{
boost::lock_guard<boost::mutex> lock(_sync);

const timer_map_t::iterator& itr = _internal_storage.find(element);
if (itr == _internal_storage.end())
{
return false;
}
itr->second->cancel();

_internal_storage.erase(itr);

return true;
}

bool contains(const T& element)
{
boost::lock_guard<boost::mutex> lock(_sync);

return _internal_storage.find(element) != _internal_storage.end();
}

void clear()
{
boost::lock_guard<boost::mutex> lock(_sync);

for (timer_map_t::value_type& i : _internal_storage)
{
i.second->cancel();
}

_internal_storage.clear();
}

private:
void remove_callback(const T& element, const boost::system::error_code& e)
{
if (e == boost::asio::error::operation_aborted)
{
return;
}
remove(element);
}

boost::asio::io_service& _io_service;
timer_map_t _internal_storage;
boost::mutex _sync;
};

} // namespace koicxx

int main()
{
boost::asio::io_service io_service;
koicxx::temp_storage<int> some_storage(io_service);
some_storage.add(0, boost::posix_time::seconds(2));
some_storage.add(1, boost::posix_time::seconds(3));
some_storage.add(2, boost::posix_time::seconds(5));

while (true)
{
if (some_storage.contains(0))
{
std::cout << 0 << ' ';
}
if (some_storage.contains(1))
{
std::cout << 1 << ' ';
}
if (some_storage.contains(2))
{
std::cout << 2 << ' ';
}
std::cout << '\n';

boost::this_thread::sleep_for(boost::chrono::seconds(1));
}
}

我什么时候需要运行 io_service,为什么?我可以让 io_service 成为类(class)的成员吗?这段代码有什么问题吗?

提前致谢。

最佳答案

您的计时器永远不会过期。

当调用 async_wait 时,您告诉 Asio 的是:当计时器到期时,我希望您安排执行此回调。请注意,这里的"dispatch"并不意味着“立即执行”,而是“将其插入到准备执行的队列中”。所述队列是 io_service 内部结构的一部分。在 io_service 上调用 run 将阻塞,直到所有待处理的工作都已安排并执行。

这里的问题是 run 会等待已安排的回调(即已经准备好执行的回调)和仍在等待安排的回调(即您已调用 async_wait< 的回调 但是计时器还没有过期)。因此,仅从主线程调用 run 将简单地阻塞,直到所有三个计时器都已过期,这可能不是您想要的。

您现在有两个选择:您可以打开第二个线程来调用run。这可行,但您最终会得到两个几乎什么都不做的线程(主线程主要在循环中休眠,工作线程主要在 run 调用时休眠)。

一种更轻量级的方法是调用 poll而不是从循环中。与 run 不同,poll 仅执行已安排执行的回调,但不执行仍在等待的回调。如果没有这样的回调可用,poll 会立即返回而不是阻塞:

template <typename T>
class temp_storage : private boost::noncopyable
{
public:
void do_poll() {
io_service_.poll();
}
[...]
};

int main()
{
[...]
while (true)
{
[...]
some_storage.do_poll();
boost::this_thread::sleep_for(boost::chrono::seconds(1));
}
}

关于c++ - 何时需要运行 io_service 以及为什么,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23994061/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com