【问题标题】:How to run a method in a low priority thread in C++?如何在 C++ 的低优先级线程中运行方法?
【发布时间】:2014-02-26 17:36:53
【问题描述】:

我在linux上使用gcc4.7 c++和boost

我有一个使用 boost::signals2 的 EventDispatcher 类,如下所示。 onUpdate()可以被多个线程调用

class EventDispather
{
public:
void subscribe(Listener l)
{
    _signal.connect(l)
}

void onUpdate(Data data)
{
    _signal(data);
}

private:
    boost::signals2::signal<void (Data)> _signal;
};

现在我想在类中再添加一个信号来处理一些低优先级的侦听器。当 onUpdate() 执行时,它首先通知高优先级的侦听器。然后是应该在低优先级线程中调用低优先级的线程并立即返回。新代码如下:

class EventDispather
{
public:
void subscribe(Listener l, Priority priority=high)
{
    if(priority == high)
    {
        _signal.connect(l);
    }
    else
    {
        _signalLowPriority.connect(l);
    }
}

void onUpdate(Data data)
{
    _signal(data);

    //how to trigger _signalLowPriority in a low priority thread?
}

private:
    boost::signals2::signal<void (Data)> _signal;
    boost::signals2::signal<void (Data)> _signalLowPriority;
};

问题:

  • 如何在低优先级线程中触发_signalLowPriority()而不等待?
  • 另外,我不想在每次onUpdate() 执行时都创建一个新线程,而是重用一个线程......如何?

如果我的目标可以通过使用标准库和/或 boost 来完成,那就太好了,但如果真的有帮助,我可以使用任何其他库。

【问题讨论】:

  • 如果_signalLowPriority 在上一次调用完成之前再次被调用怎么办?
  • 理想情况下,单个低优先级线程应该等到前一个 Data 对象的 _signalLowPriority() 调用完成,然后用新的 Data 对象调用 _signalLowPriority()。

标签: c++ multithreading boost


【解决方案1】:

实现您想要的最简单的方法是将_signalLowPriority 调用发布到boost::asio::io_service,它在单独的线程中运行。这是一些(未经测试的)代码:

class EventDispather : enable_shared_from_this<EventDispather> // simplifies lifespan management, wrt async. slot invocations
{
  EventDispather() : work_(new io_service::work(io_)) // prevent io_serivce::run() from exiting when running out of work
  {
    auto self = shared_from_this();
    // capturing "self" (even without using it) ensures that this instance will outlive the async. "queue" that uses `io_` and `_signalLowPriority` members
    thread th([self, this]() { io_.run(); });
    set_priory_with_some_native_api(thread.native_handle());
    th.detach();
  }

  void stop()
  {
    // after work_ is reset, io_service::run() will process the pending functors and then exit; thus, the above lambda will get destroyed - along with its captured "self" shared_ptr
    work_.reset();
  }

  void onUpdate(Data data)
  {
    _signal(data);
    // if io_ is running in 1 thread, all _signalLowPriority invocations will be serialized 
    io_.post([data, this]() { _signalLowPriority(data); });
  }

private:
  io_service io_;
  shared_ptr<io_serive::work> work_;
  // add here all your signals etc...
};

注意:虽然_signalLowPriority 是线程安全的,但它的插槽必须准备好在单独的线程中调用!

当然,您可以从stdboost 使用threadenable_shared_from_thisshared_ptr

【讨论】:

  • 出色的工作,非常有见地。你有没有觉得为这样简单的事情安装整个 io_service 很浪费?
  • @sehe 取决于你所说的“浪费”是什么意思:)。从用户 p.o.v 来看,只需 1 个#include 和几行代码。
  • @IgorR。 io_成员的生活呢?线程调用 io_.run() 并分离。当 EventDispather 被破坏时,io_ 和线程运行 io_run() 会发生什么?
  • @Ryan 请阅读代码中的 cmets。继承enable_shared_from_this 并将shared_ptr 捕获到this 的全部意义在于确保EventDispather 不会在io_.run() 进行中被破坏。 (当然,这意味着EventDispather 应该使用new 创建并仅通过shared_ptrs 进行管理。)
猜你喜欢
  • 2019-11-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-11-26
  • 1970-01-01
  • 2011-04-19
  • 1970-01-01
相关资源
最近更新 更多