简体   繁体   English

Boost.Asio 是在帖子之后调用的处理程序吗?

[英]Boost.Asio is the handler called after that the post?

I need to post a lamda to an io_context but I want to have the guarantee that the handler is executed only after the post() call.我需要将 lamda 发布到io_context但我想保证处理程序仅在post()调用之后执行。 Following a simplified snippet:遵循一个简化的片段:

auto l = [] { cout << "hello lambda"; };

int f(asio::io_context& io) {
  io.post(l);
}

int main() {
  asio::io_context io;
  thread th{[&io] { io.run(); };

  f(io);
  cout << "hello main";

  th.join();
  return 0;
}

Is it guarantee that "hello main!"难道保证“你好主!” is alayws called before "hello lamda"?在“hello lamda”之前调用 alayws 吗?

PS I have taken the liberty of threating the question as "Is it guarantee that "hello main!" is alayws called before "hello lamda"?" PS 我冒昧地威胁这个问题,因为“它是否保证在“你好 lamda”之前调用 alayws? because "I want to have the guarantee that the handler is executed only after the post()" is trivially true.因为“我想保证仅在 post() 之后才执行处理程序”是微不足道的。 That's because handlers are guaranteed to only be executed on a thread currently running run()/poll() on an execution context那是因为处理程序保证只在当前正在执行上下文中运行run()/poll()的线程上执行

Swatting some syntactical errors and the missing return statement this still has the race condition as described in the comments:解决一些语法错误和缺少的 return 语句,仍然具有评论中描述的竞争条件:

The thread running the io service may return before post ever gets a chance to run.运行 io 服务的线程可能会在post有机会运行之前返回。

There are two typical approaches to solve this:有两种典型的方法可以解决这个问题:

Using a work guard使用工作守卫

Live On Coliru住在 Coliru

boost::asio::io_context io;
auto work = make_work_guard(io);
std::thread th{[&io] { io.run(); }};

f(io);
std::cout << "hello main\n";

work.reset();
th.join();

Using the thread_pool使用thread_pool

Recent Boost versions introduced a full featured threadpool:最近的 Boost 版本引入了一个全功能的线程池:

Live On Coliru住在 Coliru

boost::asio::thread_pool io(1); // one thread

f(io.get_executor());
std::cout << "hello main\n";

io.join();

Ordering Tasks: Single Service Thread排序任务:单个服务线程

The most direct way is to simply post them all in order:最直接的方法是简单地按顺序发布它们:

post(io, [] { std::cout << "hello main\n"; });
f(io.get_executor());

This means that hello main will always occur before the lambda posted from f .这意味着hello main将始终发生在从f发布的 lambda 之前。

Ordering: Multiple Service Threads订购:多个服务线程

If you have a true pool:如果你有一个真正的池:

boost::asio::thread_pool io(10);

You can use a strand:您可以使用链:

auto strand = make_strand(io);
post(strand, [] { std::cout << "hello main\n"; });
f(strand);

This still guarantees the ordering of the tasks in the same way.这仍然以相同的方式保证了任务的排序。

Live On Coliru住在 Coliru

Prints印刷

hello main
hello lambda

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM