2

I am building an application based on an example on the boost website. These are the relevant definitions to know of:

typedef boost::shared_ptr&lt connection &gt connection_ptr;
std::set&lt connection_ptr&gt connections_;
std::vector&lt boost::shared_ptr&lt boost::thread&gt &gt threads;

where connection is a class.

In one of the files, connection_manager.cpp, they are doing like this:

void connection_manager::start(connection_ptr c)
{
  connections_.insert(c);
  c->start();
}

Now, I want to start every new connection in a separate thread due to my program structure. So I have modified the above according to:

void connection_manager::start(connection_ptr c)
{
    boost::shared_ptr&lt boost::thread &gt thread(new boost::thread(
                        boost::bind(&connection::start, c)));

    // push the newely created thread into the vector
    threads.push_back(thread);

    // save the connection in our set
    connections_.insert(c);
}

My problem, and hence this question, is when I want to only one of these connection_ objects. In the link provided earlier, they do like this:

void connection_manager::stop(connection_ptr c)
{
    connections_.erase(c);
    c->stop();

    // find the connection in among the threads and join that thread
}

But as the comment above suggests, how do I find c amongst all the threads and stop only that thread. I want to call the join() function for that thread.


Update:

I think that this is actually what I really want to have! So I declare my variable as

std::map &lt connection_ptr, boost::shared_ptr &lt boost::thread &gt &gt threads;

But then, how do I create a new tread, same way as before? Like:

boost::shared_ptr &lt boost::thread &gt thread(new boost::thread(
                        boost::bind(&connection::start, c)));

But what is then the next step? Sorry for being confused... :-)

Nick Craver
  • 623,446
  • 136
  • 1,297
  • 1,155
Thomas Johansson
  • 583
  • 2
  • 6
  • 15

2 Answers2

2

If you use a map (or other associative container) instead of vector you can maintain an association between connections and threads:

std::map<connection_ptr, boost::shared_ptr<boost::thread> > threads;

allows you to write:

threads[connection] = thread;

instead of the push_back call after you create the thread and then:

threads[connection]->stop();

later on when you want to look it up.

NB: As a general comment applications which maintain a 1:1 mapping between threads and network connections are quite vulnerable to Denial of Service (DoS) attacks.

Flexo
  • 87,323
  • 22
  • 191
  • 272
  • Just so that I understood you correct: Having a map as you purpose, is that something that is quite vulnerable? How can I do instead? – Thomas Johansson May 14 '11 at 10:24
  • The problem is that it's very easy for somebody evil to write a program that connects to your application 100s of times per second. Creating threads is fairly expensive in terms of RAM and CPU time required per thread. If each of these connections creates a new thread (and then possibly ties it up further) then the performance of the system will gradually grind to a halt. The normal solution is to use a [thread pool](http://stackoverflow.com/questions/4084777/creating-a-thread-pool-using-boost) to create up to some fixed number of threads and then share each thread between several connections. – Flexo May 14 '11 at 14:27
  • I am trying to figure this out, thanks for the help. "Share each thread between several connections" you say, would that means something like [HTTP Server 2 Example](http://www.boost.org/doc/libs/1_39_0/doc/html/boost_asio/example/http/server2/io_service_pool.cpp). The io_services are created in different threads. New connections are then using one of these. Is this what you mean? What does it means for the program flow to have the io services in different threads? That also the (for example the callback of async_read()) be executed in different threads then? – Thomas Johansson May 15 '11 at 07:39
  • 1
    That looks like the kind of thing I was suggesting. (I thought there might be a nicer way to do this with ASIO, but I can't remember for sure). Basically what happens is for small numbers of connections the size of the pool > number of connections, so you do basically get 1:1 connection:thread ratio. As the number of connections increases though you start to have multiple connections being serviced by one thread, but the performance of this this tends to degrade more gracefully under load. – Flexo May 15 '11 at 08:48
  • Okey I get it, thanks! But, to have a better performance, how would you suggest that I would do? I am fairly new to this performance/thread-thing, so is there anything I could change in the HTTP Server 2 example to have a better performance? – Thomas Johansson May 15 '11 at 09:44
  • In the HTTP server 2 example performance is likely to be good if a) the right number of threads are used to service the requests, benchmark under "realistic" work loads to see and b) if all the requests are relatively equal. If you have some requests which are trivial and some which are more complex then it's possible that round-robin selection won't be optimal. – Flexo May 15 '11 at 13:02
  • Thanks! In my case I think this will be a good solution. Just one more questions: That the io_services are executed in different threads, does that also mean that the connections using them will be running in different thread? I.e, the connection will be running in the same thread as its io_service? – Thomas Johansson May 16 '11 at 06:04
  • @ThomasJohansson Yes, the async callbacks run in the same thread as the io_service. (You can also have a single io_service object processed by multiple threads, see http://www.boost.org/doc/libs/1_48_0/doc/html/boost_asio/tutorial/tuttimer5.html) (P.S. you should both add an upvote to awoodland's answer, and accept one of the answers you've received!) – Darren Cook Feb 13 '12 at 01:44
1

If your connection is always bound to a thread, it would make sense to simply have the connection object point to the thread it's running in and move the logic of starting in a thread to the connection class itself.

Jan Hudec
  • 73,652
  • 13
  • 125
  • 172