【问题标题】:Combining a thread_pool with a deadline_timer - issues with template (time)将thread_pool与deadline_timer结合-模板问题(时间)
【发布时间】:2017-04-19 16:28:06
【问题描述】:

我已经集成了Boost的asio服务,并结合线程池使用。

创建了一个同时处理期货和异步任务的线程池后,我想进一步扩展它以处理截止时间计时器(反模式?)。不幸的是,我在处理模板化代码方面达到了我的极限。更准确地说,我想传递一个 boost::posix_time (例如: boost::posix_time::milliseconds(100) 或 boost::posix_time::seconds(5) ),但我很难理解我怎么能让这成为可能。

下面的部分代码是我的线程池的当前实现。

//////////////////////////////////////////////////////////////////////////
class thread_pool
{
public:

    // ...
    // Other boring stuff here...


    //////////////////////////////////////////////////////////////////////////
    template<class Task>
    void enqueue_async(Task task)
    {
        m_pIO->post( std::bind(&thread_pool::wrap_task, this,
                                                  std::function< void() >( task )));
    }

    //////////////////////////////////////////////////////////////////////////
    // NOTE: Needing help here - 'expiry_time' should be relative.
    template <class Task, class ???>
    void enqueue_deadline_async(Task task, const ??? & expiry_time)
    {
        const std::shared_ptr<boost::asio::basic_deadline_timer<???> > apTimer = std::make_shared<boost::asio::deadline_timer>(*get_service_pointer(), expiry_time);
        apTimer->async_wait(std::bind(&thread_pool::enqueue_async, this, task));
    }

private:

    //////////////////////////////////////////////////////////////////////////
    void wrap_task( std::function< void() > task )
    {
        try
        {
            task();
        }
        catch (const std::exception &e)
        {
            // Todo: Log that there is a problem!!
            BOOST_ASSERT_MSG(0,e.what());
        }
    }

};

到目前为止,我一直在使用 enqueue_task(...) 将异步任务排队以供线程池处理。我现在想扩展线程池,以便能够异步调用回调参数到截止时间计时器(请参阅 enqueue_deadline_async())但让线程池处理任务。

将thread_pool与deadline_time集成的原因是:

  • 尽量减少代码中同时运行的 io_service 数量。
  • 防止deadline_time 阻塞io_service 太久 - 减少对其他挂起计时器的影响。

最后,我在 io_service 中的嵌套调用是否危险?

环境配置:

  • Ubuntu v17.04 (Zesty) x86_x64
  • Boost v1.63
  • GCC 6.3

【问题讨论】:

    标签: c++ boost-asio


    【解决方案1】:

    一些事情,

    template <class Task, class ???>
    void enqueue_deadline_async(Task task, const ??? & expiry_time)
    

    因为它是一个可推导的模板参数,只需给它命名,就可以了

    template <class Task, class T>
    void enqueue_deadline_async(Task task, const T & expiry_time)
    

    接下来:

    const std::shared_ptr<boost::asio::basic_deadline_timer<???> > apTimer = std::make_shared<boost::asio::deadline_timer>(*get_service_pointer(), expiry_time);
    

    首先,boost::asio::deadline_timer 已经允许问题中包含您想要的内容。所以不要与basic_deadline_timer 搞混。其次,无论如何,共享指针都需要转换为 apTimer 的类型,这使得它的用处更小(因为选择另一个计时时钟模型甚至无法编译)。

    解决方案

    只要使用deadline_timer也使用的接口即可:

    template <class Task>
    void enqueue_deadline_async(Task task, const boost::posix_time::time_duration& expiry_time)
    

    有效:

    int main() {
        thread_pool tp;
        tp.enqueue_deadline_async([]{ }, boost::posix_time::seconds(5));
        tp.enqueue_deadline_async([]{ }, boost::posix_time::milliseconds(5));
    }
    

    【讨论】:

    • 您能提供任何文件吗?谷歌搜索boost enqueue_deadline_async 只得到这个答案(从网络数据爬虫传播到多个网站),这让我质疑这个答案的合法性。
    • @searchengine27 我认为您误解了“声称”的内容。问题是关于如何接受持续时间。建议是使用 boost::posix_time::time_duration 正是使用 in the interface of deadline_timer - 证明 coliru.stacked-crooked.com/a/829d4d9c8460769e (换句话说:enqueue_deadline_async 只是 OP 自己的功能,正如您在他的问题代码中看到的那样)
    • 看来我的投票现在已经锁定(meta.stackexchange.com/questions/80762/why-do-votes-get-locked)。这就是我不喜欢 SO 的原因。
    • @searchengine27 没有人让你投票 :) 我不介意,干杯!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-12-19
    • 2018-06-25
    • 1970-01-01
    • 2015-12-03
    • 2019-06-02
    • 1970-01-01
    • 2018-11-14
    相关资源
    最近更新 更多