io_service.run with multithread

I have learned the example here
http://www.boost.org/doc/libs/1_61_0/doc/html/boost_asio/example/cpp03/chat/chat_client.cpp

I want to make it support multithread and multi io_services,as bellow.
my question is :
if I do like this,should I use a mutex before aysnc_read and handle_read_header,and another mutex for do_write and handle_write.
there is only one recv buffer and a send dqeue for each session.

I wondered for example,if i use a mutex for read and handle_read,I can prevent two threads write to the recv buff at the same time,but I can't prevent a thread write to the recv buf,but the other thread is processing the recv buffer

any suggestions would be appreciated
thank you

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
  for (std::size_t i = 0; i < io_size; ++i)
	{
		for(std::size_t t = 0; t < thread_size; ++t)
		{
			thread_ptr thread(new boost::thread(
				boost::bind(&boost::asio::io_service::run, io_services_[i])));
		}
	}

void session::read()
{
	boost::asio::async_read(socket_,
		boost::asio::buffer(read_msg_.data(), message::header_length),
		boost::bind(&session::handle_read_header, shared_from_this(),
		boost::asio::placeholders::error));
}

void session::handle_read_header(const boost::system::error_code& error)
{
	if (!error && read_msg_.decode_header())
	{
		boost::asio::async_read(socket_,
			boost::asio::buffer(read_msg_.body(), read_msg_.body_length()),
			boost::bind(&session::handle_read_body, shared_from_this(),
			boost::asio::placeholders::error));
	}
	else
	{
		do_close(error);
	}
}
void session::do_write(message msg)
{
	bool write_in_progress = !write_msgs_.empty();
	write_msgs_.push_back(msg);
	if (!write_in_progress)
	{
		boost::asio::async_write(socket_,
			boost::asio::buffer(write_msgs_.front().data(),
			write_msgs_.front().length()),
			boost::bind(&session::handle_write, shared_from_this(),
			boost::asio::placeholders::error,
			write_msgs_.front().length()));
	}
}
void session::handle_write(const boost::system::error_code& error, size_t bytes_transferred)
{
	if (!error)
	{
		write_msgs_.pop_front();
		if (!write_msgs_.empty())
		{
			boost::asio::async_write(socket_,
				boost::asio::buffer(write_msgs_.front().data(),
				write_msgs_.front().length()),
				boost::bind(&session::handle_write, shared_from_this(),
				boost::asio::placeholders::error,
				boost::asio::placeholders::bytes_transferred));
		}
	}
	else
	{
		do_close(error);
	}
}
Last edited on
The situations where multiple io_services are needed are rather unusual - I described them in this SO answer: http://stackoverflow.com/a/6057028

As for async handlers sharing a resource, that's what strand is for. http://www.boost.org/doc/libs/1_61_0/doc/html/boost_asio/reference/io_service__strand.html
thank you Cubbi

I checked out two examples from boost.org
http://www.boost.org/doc/libs/1_61_0/doc/html/boost_asio/example/cpp03/http/server3/connection.cpp

httpserver2 :An HTTP server using an io_service-per-CPU design. each io_service is running in a thread
httpserver3: An HTTP server using a single io_service and a thread pool calling io_service::run().

Now the questions are:
1 for httpserver2,how does it assign a io_service to a CPU?
2 for httpserver3,strand_.wrap is used very simply,just wrap the bind. but,It is said that every async_op would be handled one by one. I wondered that It's just act like one thread,what's the difference?If I got a lot of work to do in handle_read,would this block the thread?
3 If I want to implement a gate server, It receives connections from 1000 clients,and do something with the recieved message ,then transfer to 10 servers,also on the other hand recieve message from 10 servers and dispatch them back to 1000 clients. On this occasion,should I use one io_service or two,one for each? (gate act as server for client and client for server)
4 for a normal server ,is it neccesary to use an io_service for acceptor and another for sessions? or use the same one?
Last edited on
opengl wrote:
1 for httpserver2,how does it assign a io_service to a CPU?

It doesn't. It constructs is N io_services (where N is a commandline parameter), each owning a single-threaded "thread pool".

If I got a lot of work to do in handle_read,would this block the thread?

It would not block threads, but it would block handlers that are configured on the same strand. It's not specific to networking; whenever you're writing a program and have a lot of work to do that is not parallelizable, you get no benefit from additional cores.
Your description of the "gate server" doesn't seem to require sharing, though.

On this occasion,should I use one io_service or two,one for each?
s it neccesary to use an io_service for acceptor and another for sessions?

If you can articulate the reasoning for making more than one, feel free to make more than one. I don't see why you would, though.
Topic archived. No new replies allowed.